easier direct editing of list items
[sgn.git] / js / CXGN / List.js
blob40552958dbe9fe83d806ad7e908415434b5ef685
2 /*
4 =head1 NAME
6 CXGN.List - a javascript library to implement the lists on the SGN platform
8 =head1 DESCRIPTION
10 There are two important list functions in this library, listed below. All other functions should be considered private and/or deprecated.
13 * addToListMenu(listMenuDiv, dataDiv)
15 this function will generate a select of all available lists and allow the content to be added to a list (from a search, etc). The first parameter is the id of the div tag where the menu should be drawn. The second parameter is the div that contains the data to be added. This can be a textfield, a div or span tag, or a multiple select tag.
17 * pasteListMenu(divName, menuDiv, buttonName)
19 this will generate an html select box of all the lists, and a "paste" button, to paste into a textarea (typically). The divName is the id of the textarea, the menuDiv is the id where the paste menu should be placed.
22 Public List object functions
24 * listSelect(divName, types)
26 will create an html select with id and name 'divName'. Optionally, a list of types can be specified that will limit the menu to the respective types.
28 Usage:
29 You have to instantiate the list object first:
31 var lo = new CXGN.List(); var s = lo.listSelect('myseldiv', [ 'trials' ]);
34 * validate(list_id, type, non_interactive)
36 * transform(list_id, new_type)
39 =head1 AUTHOR
41 Lukas Mueller <lam87@cornell.edu>
43 =cut
47 //JSAN.use('jqueryui');
49 if (!CXGN) CXGN = function () { };
51 CXGN.List = function () {
52     this.list = [];
56 CXGN.List.prototype = {
58     // Return the data as a straight list
59     //
60     getList: function(list_id) {
61         var list;
63         jQuery.ajax( {
64             url: '/list/contents/'+list_id,
65             async: false,
66             success: function(response) {
67                 if (response.error) {
68                     //document.write(response.error);
69                 }
70                 else {
71                     list = response;
72                 }
73             },
74             error: function(response) {
75                 alert("An error occurred.");
76             }
77         });
78         return list;
80     },
83     // this function also returns some metadata about
84     // list, namely its type.
85     //
86     getListData: function(list_id) {
87         var list;
89         jQuery.ajax( {
90             url: '/list/data',
91             async: false,
92             data: { 'list_id': list_id },
93             success: function(response) {
94                 if (response.error) {
95                     alert(response.error);
96                 }
97                 else {
98                     list = response;
99                 }
100             }
101         });
103         return list;
104     },
106     getListType: function(list_id) {
107         var type;
109         jQuery.ajax( {
110             url: '/list/type/'+list_id,
111             async: false,
112             success: function(response) {
113                 if (response.error) {
114                     alert(response.error);
115                 }
116                 else {
117                     type = response.list_type;
118                     return type;
119                 }
120             },
121             error: function () {
122                 alert('An error occurred. Cannot determine type. ');
123             }
125         });
126         return type;
127     },
129     setListType: function(list_id, type) {
131         jQuery.ajax( {
132             url: '/list/type/'+list_id+'/'+type,
133             async: false,
134             success: function(response) {
135                 if (response.error) {
136                     alert(response.error);
137                 }
138                 else {
139                     //alert('Type of list '+list_id+' set to '+type);
140                 }
141             }
142         });
143     },
146     allListTypes: function() {
147         var types;
148         jQuery.ajax( {
149             url: '/list/alltypes',
150             async: false,
151             success: function(response) {
152                 if (response.error) {
153                     alert(response.error);
154                 }
155                 else {
156                     types = response;
157                 }
158             }
159         });
160         return types;
162     },
164     typesHtmlSelect: function(list_id, html_select_id, selected) {
165         var types = this.allListTypes();
166         var html = '<select class="form-control" id="'+html_select_id+'" onchange="javascript:changeListType(\''+html_select_id+'\', '+list_id+');" >';
167         html += '<option name="null">(none)</option>';
168         for (var i=0; i<types.length; i++) {
169             var selected_html = '';
170             if (types[i][1] == selected) {
171                 selected_html = ' selected="selected" ';
172             }
173             html += '<option name="'+types[i][1]+'"'+selected_html+'>'+types[i][1]+'</option>';
174         }
175         html += '</select>';
176         return html;
177     },
179     newList: function(name) {
180         var oldListId = this.existsList(name);
181         var newListId = 0;
183         if (name == '') {
184             alert('Please provide a name for the new list.');
185             return 0;
186         }
188         if (oldListId === null) {
189             jQuery.ajax( {
190                 url: '/list/new',
191                 async: false,
192                 data: { 'name': name },
193                 success: function(response) {
194                     if (response.error) {
195                         alert(response.error);
196                     }
197                     else {
198                         newListId=response.list_id;
199                     }
200                 }
201             });
202             return newListId;
203         }
204         else {
205             alert('A list with name "'+ name + '" already exists. Please choose another list name.');
206             return 0;
207         }
208         alert("An error occurred. Cannot create new list right now.");
209         return 0;
210     },
212     availableLists: function(list_type) {
213         var lists = [];
214         jQuery.ajax( {
215             url: '/list/available',
216             data: { 'type': list_type },
217             async: false,
218             success: function(response) {
219                 if (response.error) {
220                     //alert(response.error);  //do not alert here
221                 }
222                 lists = response;
223             },
224             error: function(response) {
225                 alert("An error occurred");
226             }
227         });
228         return lists;
229     },
231     publicLists: function(list_type) {
232         var lists = [];
233         jQuery.ajax( {
234             url: '/list/available_public',
235             data: { 'type': list_type },
236             async: false,
237             success: function(response) {
238                 if (response.error) {
239                     alert(response.error);
240                 }
241                 lists = response;
242             },
243             error: function(response) {
244                 alert("An error occurred");
245             }
246         });
247         return lists;
248     },
250     //return the newly created list_item_id or 0 if nothing was added
251     //(due to duplicates)
252     addItem: function(list_id, item) {
253         var exists_item_id = this.existsItem(list_id,item);
254         if (exists_item_id ===0 ) {
255             jQuery.ajax( {
256                 async: false,
257                 url: '/list/item/add',
258                 data:  { 'list_id': list_id, 'element': item },
259                 success: function(response) {
260                     if (response.error) {
261                         alert(response.error);
262                         return 0;
263                     }
264                 }
265             });
266             var new_list_item_id = this.existsItem(list_id,item);
267             return new_list_item_id;
268         }
269         else { return 0; }
270     },
272     addBulk: function(list_id, items) {
273         var elements = items.join("\t");
275         var count;
276         jQuery.ajax( {
277             async: false,
278             method: 'POST',
279             url: '/list/add/bulk',
280             data:  { 'list_id': list_id, 'elements': elements },
281             success: function(response) {
282                 if (response.error) {
283                     alert(response.error);
284                 }
285                 else {
286                     if (response.duplicates) {
287                         alert("The following items are already in the list and were not added: "+response.duplicates.join(", "));
288                     }
289                     count = response.success;
290                 }
291             },
292             error: function(response) {
293                 alert("ERROR: "+response);
294             }
295         });
296         return count;
297     },
299     removeItem: function(list_id, item_id) {
300         jQuery.ajax( {
301             async: false,
302             url: '/list/item/remove',
303             data: { 'list_id': list_id, 'item_id': item_id }
304         });
305     },
307     updateItem: function(list_id, item_id, content) {
308         jQuery.ajax( {
309             async: false,
310             url: '/list/item/update',
311             data: { 'list_id': list_id, 'item_id': item_id, 'content':content }
312         });
313     },
315     deleteList: function(list_id) {
316         jQuery.ajax( {
317             url: '/list/delete',
318             async: false,
319             data: { 'list_id': list_id }
320         });
321     },
323     renderLists: function(div) {
324         var lists = this.availableLists();
325         var html = '';
326         html = html + '<div class="input-group"><input id="add_list_input" type="text" class="form-control" placeholder="Create New List" /><span class="input-group-btn"><button class="btn btn-primary" type="button" id="add_list_button" value="new list">New List</button></span></div><br/>';
328         if (lists.length===0) {
329             html = html + "None";
330             jQuery('#'+div+'_div').html(html);
331         }
333         html += '<table class="table table-hover table-condensed">';
334         html += '<thead><tr><th>&nbsp;</th><th>List Name</th><th>Count</th><th>Type</th><th colspan="4">Actions</th></tr></thead><tbody>';
335         for (var i = 0; i < lists.length; i++) {
336             html += '<tr><td><input type="checkbox" id="list_select_checkbox_'+lists[i][0]+'" name="list_select_checkbox" value="'+lists[i][0]+'"/></td>';
337             html += '<td><b>'+lists[i][1]+'</b></td>';
338             html += '<td>'+lists[i][3]+'</td>';
339             html += '<td>'+lists[i][5]+'</td>';
340             html += '<td><a title="View" id="view_list_'+lists[i][1]+'" href="javascript:showListItems(\'list_item_dialog\','+lists[i][0]+')"><span class="glyphicon glyphicon-th-list"></span></a></td>';
341             html += '<td><a title="Delete" id="delete_list_'+lists[i][1]+'" href="javascript:deleteList('+lists[i][0]+')"><span class="glyphicon glyphicon-remove"></span></a></td>';
342             html += '<td><a target="_blank" title="Download" id="download_list_'+lists[i][1]+'" href="/list/download?list_id='+lists[i][0]+'"><span class="glyphicon glyphicon-arrow-down"></span></a></td>';
343             if (lists[i][6] == 0){
344                 html += '<td><a title="Make Public" id="share_list_'+lists[i][1]+'" href="javascript:togglePublicList('+lists[i][0]+')"><span class="glyphicon glyphicon-share-alt"></span></a></td></tr>';
345             } else if (lists[i][6] == 1){
346                 html += '<td><a title="Make Private" id="share_list_'+lists[i][1]+'" href="javascript:togglePublicList('+lists[i][0]+')"><span class="glyphicon glyphicon-ban-circle"></span></a></td></tr>';
347             }
348         }
349         html = html + '</tbody></table>';
350         html += '<div id="list_group_select_action"></div>';
352         jQuery('#'+div+'_div').html(html);
354         jQuery('#add_list_button').click(function() {
355             var lo = new CXGN.List();
357             var name = jQuery('#add_list_input').val();
359             lo.newList(name);
360             lo.renderLists(div);
361         });
363         jQuery('#view_public_lists_button').click(function() {
364             jQuery('#public_list_dialog').modal('show');
365             var lo = new CXGN.List();
366             lo.renderPublicLists('public_list_dialog_div');
367         });
369         jQuery("input[name='list_select_checkbox']").click(function() {
370             var total=jQuery("input[name='list_select_checkbox']:checked").length;
371             var list_group_select_action_html='';
372             if (total == 0) {
373                 list_group_select_action_html += '';
374             } else {
375                 var selected = [];
376                 jQuery("input:checkbox:checked").each(function() {
377                     selected.push(jQuery(this).attr('value'));
378                 });
380                 list_group_select_action_html = '<hr><div class="row well well-sm"><div class="col-sm-4">For Selected Lists:</div><div class="col-sm-8">';
381                 if (total == 1) {
382                     list_group_select_action_html += '<a id="delete_selected_list_group" class="btn btn-primary btn-sm" style="color:white" href="javascript:deleteSelectedListGroup(['+selected+'])">Delete</a>&nbsp;<a id="make_public_selected_list_group" class="btn btn-primary btn-sm" style="color:white" href="javascript:makePublicSelectedListGroup(['+selected+'])">Make Public</a>&nbsp;<a id="make_private_selected_list_group" class="btn btn-primary btn-sm" style="color:white" href="javascript:makePrivateSelectedListGroup(['+selected+'])">Make Private</a>';
383                 } else if (total > 1) {
384                     list_group_select_action_html += '<a id="delete_selected_list_group" class="btn btn-primary btn-sm" style="color:white" href="javascript:deleteSelectedListGroup(['+selected+'])">Delete</a>&nbsp;<a id="make_public_selected_list_group" class="btn btn-primary btn-sm" style="color:white" href="javascript:makePublicSelectedListGroup(['+selected+'])">Make Public</a>&nbsp;<a id="make_private_selected_list_group" class="btn btn-primary btn-sm" style="color:white" href="javascript:makePrivateSelectedListGroup(['+selected+'])">Make Private</a><br/><br/><div class="input-group input-group-sm"><input type="text" class="form-control" id="new_combined_list_name" placeholder="New List Name"><span class="input-group-btn"><a id="combine_selected_list_group" class="btn btn-primary btn-sm" style="color:white" href="javascript:combineSelectedListGroup(['+selected+'])">Combine</a></span></div>';
385                 }
386                 list_group_select_action_html += '</div></div>';
387             }
388             jQuery("#list_group_select_action").html(list_group_select_action_html);
389         });
390     },
392     renderPublicLists: function(div) {
393         var lists = this.publicLists();
394         var html = '';
396         html += '<table id="public_list_data_table" class="table table-hover table-condensed">';
397         html += '<thead><tr><th>List Name</th><th>Count</th><th>Type</th><th>Actions</th><th>&nbsp;</th><th>&nbsp;</th></tr></thead><tbody>';
398         for (var i = 0; i < lists.length; i++) {
399             html += '<tr><td><b>'+lists[i][1]+'</b></td>';
400             html += '<td>'+lists[i][3]+'</td>';
401             html += '<td>'+lists[i][5]+'</td>';
402             html += '<td><a title="View" id="view_public_list_'+lists[i][1]+'" href="javascript:showPublicListItems(\'list_item_dialog\','+lists[i][0]+')"><span class="glyphicon glyphicon-th-list"></span></a></td>';
403             html += '<td><a target="_blank" title="Download" id="download_public_list_'+lists[i][1]+'" href="/list/download?list_id='+lists[i][0]+'"><span class="glyphicon glyphicon-arrow-down"></span></a></td>';
404             html += '<td><a title="Copy to Your Lists" id="copy_public_list_'+lists[i][1]+'" href="javascript:copyPublicList('+lists[i][0]+')"><span class="glyphicon glyphicon-plus"></span></a></td>';
405         }
406         html = html + '</tbody></table>';
408         jQuery('#'+div).html(html);
410         jQuery('#public_list_data_table').DataTable({
411             "destroy": true,
412             "columnDefs": [   { "orderable": false, "targets": [3,4,5] }  ]
413         });
414     },
416     listNameById: function(list_id) {
417         lists = this.availableLists();
418         for (var n=0; n<lists.length; n++) {
419             if (lists[n][0] == list_id) { return lists[n][1]; }
420         }
421     },
423     publicListNameById: function(list_id) {
424         lists = this.publicLists();
425         for (var n=0; n<lists.length; n++) {
426             if (lists[n][0] == list_id) { return lists[n][1]; }
427         }
428     },
430     renderItems: function(div, list_id) {
432         var list_data = this.getListData(list_id);
433         var items = list_data.elements;
434         var list_type = list_data.type_name;
435         var list_name = this.listNameById(list_id);
437         var html = '';
438         html += '<table class="table"><tr><td>List ID</td><td id="list_id_div">'+list_id+'</td></tr>';
439         html += '<tr><td>List name:<br/><input type="button" class="btn btn-primary btn-xs" id="updateNameButton" value="Update" /></td>';
440         html += '<td><input class="form-control" type="text" id="updateNameField" size="10" value="'+list_name+'" /></td></tr>';
441         html += '<tr><td>Type:<br/><input id="list_item_dialog_validate" type="button" class="btn btn-primary btn-xs" value="Validate" onclick="javascript:validateList('+list_id+',\'type_select\')" /></td><td>'+this.typesHtmlSelect(list_id, 'type_select', list_type)+'</td></tr>';
442         html += '<tr><td>Add New Items:<br/><button class="btn btn-primary btn-xs" type="button" id="dialog_add_list_item_button" value="Add">Add</button></td><td><textarea id="dialog_add_list_item" type="text" class="form-control" placeholder="Add Item To List" /></textarea></td></tr></table>';
444         html += '<table id="list_item_dialog_datatable" class="table table-condensed table-hover table-bordered"><thead style="display: none;"><tr><th><b>List items</b> ('+items.length+')</th><th>&nbsp;</th></tr></thead><tbody>';
446         for(var n=0; n<items.length; n++) {
447             html = html +'<tr><td id="list_item_toggle_edit_div_'+items[n][0]+'" ><div name="list_item_toggle_edit" data-listitemdiv="list_item_toggle_edit_div_'+items[n][0]+'" data-listitemid="'+items[n][0]+'" data-listitemname="'+items[n][1]+'" >'+ items[n][1] + '</div></td><td><input id="'+items[n][0]+'" type="button" class="btn btn-default btn-xs" value="Remove" /></td></tr>';
448         }
449         html += '</tbody></table>';
451         jQuery('#'+div+'_div').html(html);
453         jQuery('#list_item_dialog_datatable').DataTable({
454             destroy: true,
455             scrollY:        '30vh',
456             scrollCollapse: true,
457             paging:         false,
458         });
460         for (var n=0; n<items.length; n++) {
461             var list_item_id = items[n][0];
463             jQuery('#'+items[n][0]).click(
464                 function() {
465                     var lo = new CXGN.List();
466                     var i = lo.availableLists();
468                     lo.removeItem(list_id, this.id );
469                     lo.renderItems(div, list_id);
470                     lo.renderLists('list_dialog');
471                 });
472         }
474         jQuery('#dialog_add_list_item_button').click(
475             function() {
476                 addMultipleItemsToList('dialog_add_list_item', list_id);
477                 var lo = new CXGN.List();
478                 lo.renderItems(div, list_id);
479             }
480         );
482         jQuery('#updateNameButton').click(
483             function() {
484                 var lo = new CXGN.List();
485                 var new_name =  jQuery('#updateNameField').val();
486                 var list_id = jQuery('#list_id_div').html();
487                 lo.updateName(list_id, new_name);
488                 alert("Changed name to "+new_name+" for list id "+list_id);
489             }
490         );
492         jQuery('div[name="list_item_toggle_edit"]').click(function() {
493             var list_item_id = jQuery(this).data('listitemid');
494             var list_item_name = jQuery(this).data('listitemname');
495             var list_item_div = jQuery(this).data('listitemdiv');
496             var list_item_edit_html = '<div class="input-group"><input type="text" class="form-control" value="'+list_item_name+'" placeholder="'+list_item_name+'" id="list_item_edit_input_'+list_item_id+'" data-listitemid="'+list_item_id+'" /><span class="input-group-btn"><button class="btn btn-default" type="button" name="list_item_edit_submit" data-inputid="list_item_edit_input_'+list_item_id+'">Ok</button></span></div>';
497             jQuery("#"+list_item_div).empty().html(list_item_edit_html);
498         });
500         jQuery(document).on('click', 'button[name="list_item_edit_submit"]', function() {
501             var lo = new CXGN.List();
502             var list_id = jQuery('#list_id_div').html();
503             var input_id = jQuery(this).data('inputid');
504             lo.updateItem(list_id, jQuery("#"+input_id).data('listitemid'), jQuery("#"+input_id).val());
505             lo.renderItems(div, list_id);
506         });
507     },
509     renderPublicItems: function(div, list_id) {
510         var list_data = this.getListData(list_id);
511         var items = list_data.elements;
512         var list_type = list_data.type_name;
513         var list_name = this.publicListNameById(list_id);
515         var html = '';
516         html += '<table class="table"><tr><td>List ID</td><td id="list_id_div">'+list_id+'</td></tr>';
517         html += '<tr><td>List name:</td>';
518         html += '<td>'+list_name+'</td></tr>';
519         html += '<tr><td>Type:</td><td>'+list_type+'</td></tr>';
520         html += '</table>';
521         html += '<table id="public_list_item_dialog_datatable" class="table table-condensed table-hover table-bordered"><thead style="display: none;"><tr><th><b>List items</b> ('+items.length+')</th></tr></thead><tbody>';
522         for(var n=0; n<items.length; n++) {
523             html = html +'<tr><td>'+ items[n][1] + '</td></tr>';
524         }
525         html += '</tbody></table>';
527         jQuery('#'+div+'_div').html(html);
529         jQuery('#public_list_item_dialog_datatable').DataTable({
530             destroy: true,
531             scrollY:        '30vh',
532             scrollCollapse: true,
533             paging:         false,
534         });
535     },
537     existsList: function(name) {
538         var list_id = 0;
539         jQuery.ajax( {
540             url: '/list/exists',
541             async: false,
542             data: { 'name': name },
543             success: function(response) {
544                 list_id = response.list_id;
545             }
546         });
547         return list_id;
548     },
550     existsItem: function(list_id, name) {
551         var list_item_id =0;
552         jQuery.ajax( {
553             url: '/list/exists_item',
554             async: false,
555             data: { 'list_id' : list_id, 'name':name },
556             success: function(response) {
557                 list_item_id = response.list_item_id;
558             }
559         });
560         return list_item_id;
561     },
563     addToList: function(list_id, text) {
564         if (! text) {
565             return;
566         }
567         var list = text.split("\n");
568         var duplicates = [];
570         var info = this.addBulk(list_id, list);
572         return info;
574     },
576     /* listSelect: Creates an html select with lists of requested types.
578        Parameters:
579          div_name: The div_name where the select should appear
580          types: a list of list types that should be listed in the menu
581          add_empty_element: text. if present, add an empty element with the
582            provided text as description
583     */
585     listSelect: function(div_name, types, empty_element) {
586         var lists = new Array();
588         if (types) {
589             for (var n=0; n<types.length; n++) {
590                 var more = this.availableLists(types[n]);
591                 if (more) {
592                     for (var i=0; i<more.length; i++) {
593                         lists.push(more[i]);
594                     }
595                 }
596             }
597         }
598         else {
599             lists = this.availableLists();
600         }
602         var html = '<select class="form-control input-sm" id="'+div_name+'_list_select" name="'+div_name+'_list_select" >';
603         if (empty_element) {
604             html += '<option value="">'+empty_element+'</option>\n';
605         }
606         for (var n=0; n<lists.length; n++) {
607             html += '<option value='+lists[n][0]+'>'+lists[n][1]+'</option>';
608         }
609         html = html + '</select>';
610         return html;
611     },
613     updateName: function(list_id, new_name) {
614         jQuery.ajax( {
615             url: '/list/name/update',
616             async: false,
617             data: { 'name' : new_name, 'list_id' : list_id },
618             success: function(response) {
619                 if (response.error) {
620                     alert(response.error);
621                     return;
622                 }
623                 else {
624                     alert("The name of the list was changed to "+new_name);
625                 }
626             },
627             error: function(response) { alert("An error occurred."); }
628         });
629         this.renderLists('list_dialog');
630     },
632     validate: function(list_id, type, non_interactive) {
633         var missing = new Array();
634         var error = 0;
635         jQuery.ajax( {
636             url: '/list/validate/'+list_id+'/'+type,
637             async: false,
638             success: function(response) {
639                 if (response.error) {
640                     alert(response.error);
641                 }
642                 else {
643                     missing = response.missing;
644                 }
645             },
646             error: function(response) { alert("An error occurred while validating the list "+list_id); error=1; }
647         });
649         if (error === 1 ) { return; }
651         if (missing.length==0) {
652             if (!non_interactive) { alert("This list passed validation."); }
653             return 1;
654         }
655         else {
657             jQuery("#validate_accession_error_display tbody").html('');
658             
659             var missing_accessions_html = "<div class='well well-sm'><h3>Add the missing accessions to a list</h3><div id='validate_stock_missing_accessions' style='display:none'></div><div id='validate_stock_add_missing_accessions'></div><hr><h4>Go to <a href='/breeders/accessions'>Manage Accessions</a> to add these new accessions.</h4></div><br/>";
660             
662             jQuery("#validate_stock_add_missing_accessions_html").html(missing_accessions_html);
664                 var missing_accessions_vals = '';
665                 if (missing){
666                 for(var i=0; i<missing.length; i++) {
667                     missing_accessions_vals = missing_accessions_vals + missing[i] + '\n';
668                 }
669                 }
670                 jQuery("#validate_stock_missing_accessions").html(missing_accessions_vals);
671                 addToListMenu('validate_stock_add_missing_accessions', 'validate_stock_missing_accessions', {
672           selectText: true,
673           listType: 'accessions'
674         });
675             
677             jQuery("#validate_accession_error_display tbody").append(missing.join(","));
678             jQuery('#validate_accession_error_display').modal("show");
679             return;
680         
681             //alert("List validation failed. Elements not found: "+ missing.join(","));
682             //return 0;
683         }
684     },
686     transform: function(list_id, transform_name) {
687         var transformed = new CXGN.List();
688         var ajaxResponse = [];
689         jQuery.ajax( {
690             url: '/list/transform/'+list_id+'/'+transform_name,
691             async: false,
692             success: function(response) {
693                 if (response.error) {
694                     alert(response.error);
695                 }
696                 else {
697                     ajaxResponse = response;
698                     //console.log("transformed="+ajaxResponse);
699                 }
700             },
701             error: function(response) { alert("An error occurred while validating the list "+list_id); }
702         });
703         return ajaxResponse.transform;
704     },
706     transform2Ids: function(list_id, data) {
707         if (data === undefined) var data = this.getListData(list_id);
708         //console.log("data ="+JSON.stringify(data));
709         var list_type = data.type_name;
711         var new_type;
712         switch (list_type)
713         {
714           case "traits":
715               new_type = 'traits_2_trait_ids';
716               break;
717           case "locations":
718               new_type = 'locations_2_location_ids';
719               break;
720           case "trials":
721           case "breeding_programs":
722               new_type = 'projects_2_project_ids';
723               break;
724           case "accessions":
725               new_type = 'accessions_2_accession_ids';
726               break;
727           case "plots":
728               new_type = 'plots_2_plot_ids';
729               break;
730           default:
731               return { 'error' : "cannot convert the list because of unknown type" };
732         }
733         //if (window.console) console.log("new type = "+new_type);
734         var transformed = this.transform(list_id, new_type);
735         //if (window.console) console.log("transformed="+JSON.stringify(transformed));
736         return transformed;
738     }
741 function setUpLists() {
742     jQuery("button[name='lists_link']").click(
743         function() { show_lists(); }
744     );
748 function show_lists() {
749     jQuery('#list_dialog').modal("show");
751     var l = new CXGN.List();
752     l.renderLists('list_dialog');
755 /* deprecated */
756 function pasteListMenu (div_name, menu_div, button_name) {
757     var lo = new CXGN.List();
759     var html='';
761     if (button_name === undefined) {
762         button_name = 'paste';
763     }
765     html = lo.listSelect(div_name);
766     html = html + '<button class="btn btn-info btn-sm" type="button" value="'+button_name+'" onclick="javascript:pasteList(\''+div_name+'\')" >'+button_name+'</button>';
768     jQuery('#'+menu_div).html(html);
771 function pasteList(div_name) {
772     var lo = new CXGN.List();
773     var list_id = jQuery('#'+div_name+'_list_select').val();
774         console.log(list_id);
775     var list = lo.getList(list_id);
776         console.log(list);
777     // textify list
778     var list_text = '';
779     for (var n=0; n<list.length; n++) {
780       list_text = list_text + list[n]+"\r\n";
781     }
782         console.log(list_text);
783     jQuery('#'+div_name).val(list_text);
784   }
787   addToListMenu
789   Parameters:
790   * listMenuDiv - the name of the div where the menu will be displayed
791   * dataDiv - the div from which the data will be copied (can be a div, textarea, or html select
792   * options - optional hash with the following keys:
793     - selectText: if the dataDiv is an html select and selectText is true, the text and not the value will be copied into the list
794     - listType: the type of lists to display in the menu
795     - typesSourceDiv: obtain the type from this source div
800 function addToListMenu(listMenuDiv, dataDiv, options) {
801     var lo = new CXGN.List();
803     var html;
804     var selectText;
805     var listType;
806     var typeSourceDiv;
807     var type;
809     if (options) {
810         if (options.selectText) {
811             selectText = options.selectText;
812         }
813         if (options.typeSourceDiv) {
814             var sourcetype = getData(options.typeSourceDiv, selectText);
815             if (sourcetype) {
816                 type = sourcetype.replace(/(\n|\r)+$/, '');
817             }
818         }
819         if (options.listType) {
820             type = options.listType;
821         }
822     }
823     html = '<div class="row"><div class="col-sm-6" style="margin-right:0px; padding-right:0px;"><input class="form-control input-sm" type="text" id="'+dataDiv+'_new_list_name" placeholder="New list..." />';
824     html += '</div><div class="col-sm-6" style="margin-left:0px; padding-left:0px; margin-right:0px; padding-right:0px;"><input type="hidden" id="'+dataDiv+'_list_type" value="'+type+'" />';
825     html += '<input class="btn btn-primary btn-sm" id="'+dataDiv+'_add_to_new_list" type="button" value="add to new list" /></div></div><br />';
827     html += '<div class="row"><div class="col-sm-6" style="margin-right:0px; padding-right:0px;">'+lo.listSelect(dataDiv, [ type ]);
829     html += '</div><div class="col-sm-6" style="margin-left:0px; padding-left:0px; margin-right:0px; padding-right:0px;"><input class="btn btn-primary btn-sm" id="'+dataDiv+'_button" type="button" value="add to list" /></div></div>';
831     jQuery('#'+listMenuDiv).html(html);
833     var list_id = 0;
835     jQuery('#'+dataDiv+'_add_to_new_list').click(
836         function() {
837             var lo = new CXGN.List();
838             var new_name = jQuery('#'+dataDiv+'_new_list_name').val();
839             var type = jQuery('#'+dataDiv+'_list_type').val();
841             var data = getData(dataDiv, selectText);
843             list_id = lo.newList(new_name);
844             if (list_id > 0) {
845                 var elementsAdded = lo.addToList(list_id, data);
846                 if (type) { lo.setListType(list_id, type); }
847                 alert("Added "+elementsAdded+" list elements to list "+new_name+" and set type to "+type);
848             }
849         }
850     );
852     jQuery('#'+dataDiv+'_button').click(
853         function() {
854             var data = getData(dataDiv, selectText);
855             list_id = jQuery('#'+dataDiv+'_list_select').val();
856             var lo = new CXGN.List();
857             var elementsAdded = lo.addToList(list_id, data);
859             alert("Added "+elementsAdded+" list elements");
860             return list_id;
861         }
862     );
868 function getData(id, selectText) {
869     var divType = jQuery("#"+id).get(0).tagName;
870     var data;
872     if (divType == 'DIV' || divType =='SPAN' || divType === undefined) {
873         data = jQuery('#'+id).html();
874     }
875     if (divType == 'SELECT' && selectText) {
876         if (jQuery.browser.msie) {
877             // Note: MS IE unfortunately removes all whitespace
878             // in the jQuery().text() call. Program it out...
879             //
880             var selectbox = document.getElementById(id);
881             var datalist = new Array();
882             for (var n=0; n<selectbox.length; n++) {
883                 if (selectbox.options[n].selected) {
884                     var x=selectbox.options[n].text;
885                     datalist.push(x);
886                 }
887             }
888             data = datalist.join("\n");
889             //alert("data:"+data);
891         }
892         else {
893             data = jQuery('#'+id+" option:selected").text();
894         }
896     }
897     if (divType == 'SELECT' && ! selectText) {
898         var return_data = jQuery('#'+id).val();
900         if (return_data instanceof Array) {
901             data = return_data.join("\n");
902         }
903         else {
904             data = return_data;
905         }
906     }
907     if (divType == 'TEXTAREA') {
908         data = jQuery('textarea#'+id).val();
909     }
910     return data;
914 /* deprecated */
915 function addTextToListMenu(div) {
916     var lo = new CXGN.List();
917     var html = lo.listSelect(div);
918     html = html + '<input id="'+div+'_button" type="button" value="add to list" />';
920     document.write(html);
922     jQuery('#'+div+'_button').click(
923         function() {
924             var text = jQuery('textarea#div').val();
925             var list_id = jQuery('#'+div+'_list_select').val();
926             lo.addToList(list_id, text);
927             lo.renderLists('list_dialog');
928         }
929     );
932 /* deprecated */
933 function addSelectToListMenu(div) {
934     var lo = new CXGN.List();
935     var html = lo.listSelect(div);
936     html = html + '<input id="'+div+'_button" type="button" value="add to list" />';
938     document.write(html);
940     jQuery('#'+div+'_button').click(
941         function() {
942             var selected_items = jQuery('#'+div).val();
943             var list_id = jQuery('#'+div+'_list_select').val();
944             addArrayToList(selected_items, list_id);
945             lo.renderLists('list_dialog');
946         }
947     );
951 /* deprecated */
952 // add the text in a div to a list
953 function addDivToList(div_name) {
954     var list_id = jQuery('#'+div_name+'_list_select').val();
955     var lo = new CXGN.List();
956     var list = jQuery('#'+div_name).val();
957     var items = list.split("\n");
959     for(var n=0; n<items.length; n++) {
960         var added = lo.addItem(list_id, items[n]);
961         if (added > 0) { }
962     }
965 /* deprecated */
966 function addTextToList(div, list_id) {
967     var lo = new CXGN.List();
968     var item = jQuery('#'+div).val();
969     var id = lo.addItem(list_id, item);
970     if (id == 0) {
971         alert('Item "'+item+'" was not added because it already exists');
972     }
973     lo.renderLists('list_dialog');
976 /* deprecated */
977 function addMultipleItemsToList(div, list_id) {
978     var lo = new CXGN.List();
979     var content = jQuery('#'+div).val();
980     if (content == '') {
981         alert("No items - Please enter items to add to the list.");
982 return;
983     }
984 //    var items = content.split("\n");
986   //  var duplicates = new Array();
987     var items = content.split("\n");
988     lo.addBulk(list_id, items);
989    // for (var n=0; n<items.length; n++) {
990 //      var id = lo.addItem(list_id, items[n]);
991 //      if (id == 0) {
992 //          duplicates.push(items[n]);
993 //      }
994   //  }
995     //if (duplicates.length >0) {
996 //      alert("The following items were not added because they are already in the list: "+ duplicates.join(", "));
997   //  }
998 //lo.renderLists('list_dialog');
1001 /* deprecated */
1002 function addArrayToList(items, list_id) {
1003 var lo = new CXGN.List();
1004    var duplicates = new Array();
1005     for (var n=0; n<items.length; n++) {
1006         var id = lo.addItem(list_id, items[n]);
1007         if (id == 0) {
1008             duplicates.push(items[n]);
1009         }
1010     }
1011     if (duplicates.length >0) {
1012         alert("The following items were not added because they are already in the list: "+ duplicates.join(", "));
1013     }
1016 function deleteList(list_id) {
1017     var lo = new CXGN.List();
1018     var list_name = lo.listNameById(list_id);
1019     if (confirm('Delete list "'+list_name+'"? (ID='+list_id+'). This cannot be undone.')) {
1020         lo.deleteList(list_id);
1021         lo.renderLists('list_dialog');
1022         alert('Deleted list '+list_name);
1023     }
1026 function togglePublicList(list_id) {
1027     jQuery.ajax({
1028         "url": "/list/public/toggle",
1029         "type": "POST",
1030         "data": {'list_id': list_id},
1031         success: function(r) {
1032             var lo = new CXGN.List();
1033             if (r.error) {
1034                 alert(r.error);
1035             } else if (r.r == 1) {
1036                 alert("List set to Private");
1037             } else if (r.r == 0) {
1038                 alert("List set to Public");
1039             }
1040             lo.renderLists('list_dialog');
1041         },
1042         error: function() {
1043             alert("Error Setting List to Public! List May Not Exist.");
1044         }
1045     });
1046     var lo = new CXGN.List();
1047     lo.renderLists('list_dialog');
1050 function makePublicList(list_id) {
1051     jQuery.ajax({
1052         "url": "/list/public/true",
1053         "type": "POST",
1054         "data": {'list_id': list_id},
1055         success: function(r) {
1056             var lo = new CXGN.List();
1057             if (r.error) {
1058                 alert(r.error);
1059             }
1060         },
1061         error: function() {
1062             alert("Error Setting List to Public! List May Not Exist.");
1063         }
1064     });
1067 function makePrivateList(list_id) {
1068     jQuery.ajax({
1069         "url": "/list/public/false",
1070         "type": "POST",
1071         "data": {'list_id': list_id},
1072         success: function(r) {
1073             var lo = new CXGN.List();
1074             if (r.error) {
1075                 alert(r.error);
1076             }
1077         },
1078         error: function() {
1079             alert("Error Setting List to Private! List May Not Exist.");
1080         }
1081     });
1084 function copyPublicList(list_id) {
1085     jQuery.ajax({
1086         "url": "/list/public/copy",
1087         "type": "POST",
1088         "data": {'list_id': list_id},
1089         success: function(r) {
1090             if (r.error) {
1091                 alert(r.error);
1092             } else if (r.success == 'true') {
1093                 alert("Public List Copied to Your Lists.");
1094             }
1095         },
1096         error: function() {
1097             alert("Error Copying Public List! List May Not Exist.");
1098         }
1099     });
1100     var lo = new CXGN.List();
1101     lo.renderLists('list_dialog');
1104 function deleteItemLink(list_item_id) {
1105     var lo = new CXGN.List();
1106     lo.deleteItem(list_item_id);
1107     lo.renderLists('list_dialog');
1110 function working_modal_show() {
1111     jQuery("#working_modal").modal('show');
1114 function working_modal_hide() {
1115     jQuery("#working_modal").modal('hide');
1118 function showListItems(div, list_id) {
1119     working_modal_show();
1120     var l = new CXGN.List();
1121     l.renderItems(div, list_id);
1122     jQuery('#'+div).modal("show");
1123     working_modal_hide();
1126 function showPublicListItems(div, list_id) {
1127     var l = new CXGN.List();
1128     jQuery('#'+div).modal("show");
1129     l.renderPublicItems(div, list_id);
1132 function addNewList(div_id) {
1133     var lo = new CXGN.List();
1134     var name = jQuery('#'+div_id).val();
1136     if (name == '') {
1137         alert("Please specify a name for the list.");
1138         return;
1139     }
1141     var list_id = lo.existsList(name);
1142     if (list_id > 0) {
1143         alert('The list '+name+' already exists. Please choose another name.');
1144         return;
1145     }
1146     lo.newList(name);
1147     lo.renderLists('list_item_dialog');
1150 function changeListType(html_select_id, list_id) {
1151     var type = jQuery('#'+html_select_id).val();
1152     var l = new CXGN.List();
1153     l.setListType(list_id, type);
1154     l.renderLists('list_dialog');
1158    validateList - check if all the elements in a list are of the correct type
1160    Parameters:
1161    * list_id: the id of the list
1162    * html_select_id: the id of the html select containing the type list
1166 function validateList(list_id, html_select_id) {
1167     var lo = new CXGN.List();
1168     var type = jQuery('#'+html_select_id).val();
1169     lo.validate(list_id, type);
1172 function deleteSelectedListGroup(list_ids) {
1173     var arrayLength = list_ids.length;
1174     if (confirm('Delete the selected lists? This cannot be undone.')) {
1175         for (var i=0; i<arrayLength; i++) {
1176             var lo = new CXGN.List();
1177             lo.deleteList(list_ids[i]);
1178         }
1179         lo.renderLists('list_dialog');
1180     }
1183 function makePublicSelectedListGroup(list_ids) {
1184     var arrayLength = list_ids.length;
1185     if (confirm('Make selected lists public?')) {
1186         for (var i=0; i<arrayLength; i++) {
1187             makePublicList(list_ids[i]);
1188         }
1189         var lo = new CXGN.List();
1190         lo.renderLists('list_dialog');
1191     }
1194 function makePrivateSelectedListGroup(list_ids) {
1195     var arrayLength = list_ids.length;
1196     if (confirm('Make selected lists private?')) {
1197         for (var i=0; i<arrayLength; i++) {
1198             makePrivateList(list_ids[i]);
1199         }
1200         var lo = new CXGN.List();
1201         lo.renderLists('list_dialog');
1202     }
1205 function combineSelectedListGroup(list_ids) {
1206     var arrayLength = list_ids.length;
1207         var list_name = jQuery('#new_combined_list_name').val();
1208     if (confirm('Combine selected lists into a new list called '+list_name+'?')) {
1209                 var lo = new CXGN.List();
1210                 var new_list_id = lo.newList(list_name);
1211                 for (var i=0; i<arrayLength; i++) {
1212                         list = lo.getListData(list_ids[i]);
1213                         var numElements = list.elements.length;
1214                         var arrayItems = [];
1215                         for (var j=0; j<numElements; j++) {
1216                                 arrayItems.push(list.elements[j][1]);
1217                         }
1218                         lo.addBulk(new_list_id, arrayItems);
1219                 }
1220         lo.renderLists('list_dialog');
1221     }