refresh matview stockprop happens in ajax controller
[sgn.git] / js / CXGN / List.js
blobcb69f944fc0e3014e7d9d49eed0707103dec8e42
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); //do not alert here
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         var trimmed_content = content.trim();
309         jQuery.ajax( {
310             async: false,
311             url: '/list/item/update',
312             data: { 'list_id': list_id, 'item_id': item_id, 'content': trimmed_content }
313         });
314     },
316     deleteList: function(list_id) {
317         jQuery.ajax( {
318             url: '/list/delete',
319             async: false,
320             data: { 'list_id': list_id }
321         });
322     },
324     renderLists: function(div) {
325         var lists = this.availableLists();
326         var html = '';
327         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/>';
329         if (lists.length===0) {
330             html = html + "None";
331             jQuery('#'+div+'_div').html(html);
332         }
334         html += '<table class="table table-hover table-condensed">';
335         html += '<thead><tr><th>&nbsp;</th><th>List Name</th><th>Count</th><th>Type</th><th colspan="4">Actions</th></tr></thead><tbody>';
336         for (var i = 0; i < lists.length; i++) {
337             html += '<tr><td><input type="checkbox" id="list_select_checkbox_'+lists[i][0]+'" name="list_select_checkbox" value="'+lists[i][0]+'"/></td>';
338             html += '<td><b>'+lists[i][1]+'</b></td>';
339             html += '<td>'+lists[i][3]+'</td>';
340             html += '<td>'+lists[i][5]+'</td>';
341             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>';
342             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>';
343             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>';
344             if (lists[i][6] == 0){
345                 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>';
346             } else if (lists[i][6] == 1){
347                 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>';
348             }
349         }
350         html = html + '</tbody></table>';
351         html += '<div id="list_group_select_action"></div>';
353         jQuery('#'+div+'_div').html(html);
355         jQuery('#add_list_button').click(function() {
356             var lo = new CXGN.List();
358             var name = jQuery('#add_list_input').val();
360             lo.newList(name);
361             lo.renderLists(div);
362         });
364         jQuery('#view_public_lists_button').click(function() {
365             jQuery('#public_list_dialog').modal('show');
366             var lo = new CXGN.List();
367             lo.renderPublicLists('public_list_dialog_div');
368         });
370         jQuery("input[name='list_select_checkbox']").click(function() {
371             var total=jQuery("input[name='list_select_checkbox']:checked").length;
372             var list_group_select_action_html='';
373             if (total == 0) {
374                 list_group_select_action_html += '';
375             } else {
376                 var selected = [];
377                 jQuery("input[name='list_select_checkbox']:checked").each(function() {
378                     selected.push(jQuery(this).attr('value'));
379                 });
381                 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">';
382                 if (total == 1) {
383                     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>';
384                 } else if (total > 1) {
385                     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>';
386                 }
387                 list_group_select_action_html += '</div></div>';
388             }
389             jQuery("#list_group_select_action").html(list_group_select_action_html);
390         });
391     },
393     renderPublicLists: function(div) {
394         var lists = this.publicLists();
395         var html = '';
397         html += '<table id="public_list_data_table" class="table table-hover table-condensed">';
398         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>';
399         for (var i = 0; i < lists.length; i++) {
400             html += '<tr><td><b>'+lists[i][1]+'</b></td>';
401             html += '<td>'+lists[i][3]+'</td>';
402             html += '<td>'+lists[i][5]+'</td>';
403             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>';
404             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>';
405             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>';
406         }
407         html = html + '</tbody></table>';
409         jQuery('#'+div).html(html);
411         jQuery('#public_list_data_table').DataTable({
412             "destroy": true,
413             "columnDefs": [   { "orderable": false, "targets": [3,4,5] }  ]
414         });
415     },
417     listNameById: function(list_id) {
418         lists = this.availableLists();
419         for (var n=0; n<lists.length; n++) {
420             if (lists[n][0] == list_id) { return lists[n][1]; }
421         }
422     },
424     publicListNameById: function(list_id) {
425         lists = this.publicLists();
426         for (var n=0; n<lists.length; n++) {
427             if (lists[n][0] == list_id) { return lists[n][1]; }
428         }
429     },
431     renderItems: function(div, list_id) {
433         var list_data = this.getListData(list_id);
434         var items = list_data.elements;
435         var list_type = list_data.type_name;
436         var list_name = this.listNameById(list_id);
438         var html = '';
439         html += '<table class="table"><tr><td>List ID</td><td id="list_id_div">'+list_id+'</td></tr>';
440         html += '<tr><td>List name:<br/><input type="button" class="btn btn-primary btn-xs" id="updateNameButton" value="Update" /></td>';
441         html += '<td><input class="form-control" type="text" id="updateNameField" size="10" value="'+list_name+'" /></td></tr>';
442         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\')" /><div id="fuzzySearchAccessionListDiv"></div><div id="synonymListButtonDiv"></div><div id="availableSeedlotButtonDiv"></div></td><td>'+this.typesHtmlSelect(list_id, 'type_select', list_type)+'</td></tr>';
443         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>';
445         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>';
447         for(var n=0; n<items.length; n++) {
448             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>';
449         }
450         html += '</tbody></table>';
452         jQuery('#'+div+'_div').html(html);
454         jQuery('#list_item_dialog_datatable').DataTable({
455             destroy: true,
456             scrollY:        '30vh',
457             scrollCollapse: true,
458             paging:         false,
459         });
461     if (list_type == 'accessions'){
462         jQuery('#fuzzySearchAccessionListDiv').html('<br/><button id="fuzzySearchAccessionListButton" class="btn btn-primary btn-xs" onclick="javascript:fuzzySearchList('+list_id+',\''+list_type+'\')" >Fuzzy Search</button>');
463         jQuery('#availableSeedlotButtonDiv').html('<br/><button id="availableSeedlotButton" class="btn btn-primary btn-xs" onclick="(new CXGN.List()).seedlotSearch('+list_id+')">See Availible Seedlots</button>');
464     }
465     if (['seedlots', 'plots', 'accessions', 'vector_constructs', 'crosses', 'populations', 'plants'].indexOf(list_type) >= 0){
466         jQuery('#synonymListButtonDiv').html('<br/><button id="synonymListButton" class="btn btn-primary btn-xs" onclick="(new CXGN.List()).synonymSearch('+list_id+')">Find Synonyms</button>');
467     }
468     jQuery(document).on("change", "#type_select", function(){
469         if (jQuery('#type_select').val() == 'accessions'){
470             jQuery('#availableSeedlotButtonDiv').html('<br/><button id="availableSeedlotButton" class="btn btn-primary btn-xs" onclick="(new CXGN.List()).seedlotSearch('+list_id+')">See Availible Seedlots</button>');
471             jQuery('#fuzzySearchAccessionListDiv').html('<br/><button id="fuzzySearchAccessionListButton" class="btn btn-primary btn-xs" onclick="javascript:fuzzySearchList('+list_id+',\''+list_type+'\')" >Fuzzy Search</button>');
472         } else {
473             jQuery('#fuzzySearchAccessionListDiv').html('');
474             jQuery('#availableSeedlotButtonDiv').html('')
475         }
476                                 if (['seedlots', 'plots', 'accessions', 'vector_constructs', 'crosses', 'populations', 'plants'].indexOf(jQuery('#type_select').val()) >= 0){
477                         jQuery('#synonymListButtonDiv').html('<br/><button id="synonymListButton" class="btn btn-primary btn-xs" onclick="(new CXGN.List()).synonymSearch('+list_id+')">Find Synonyms</button>');
478                     } else {
479                                         jQuery('#synonymListButtonDiv').html('');
480                                 }
481     });
483         for (var n=0; n<items.length; n++) {
484             var list_item_id = items[n][0];
486             jQuery('#'+items[n][0]).click(
487                 function() {
488                     var lo = new CXGN.List();
489                     var i = lo.availableLists();
491                     lo.removeItem(list_id, this.id );
492                     lo.renderItems(div, list_id);
493                     lo.renderLists('list_dialog');
494                 });
495         }
497         jQuery('#dialog_add_list_item_button').click(
498             function() {
499                 addMultipleItemsToList('dialog_add_list_item', list_id);
500                 var lo = new CXGN.List();
501                 lo.renderItems(div, list_id);
502             }
503         );
505         jQuery('#updateNameButton').click(
506             function() {
507                 var lo = new CXGN.List();
508                 var new_name =  jQuery('#updateNameField').val();
509                 var list_id = jQuery('#list_id_div').html();
510                 lo.updateName(list_id, new_name);
511                 alert("Changed name to "+new_name+" for list id "+list_id);
512             }
513         );
515         jQuery('div[name="list_item_toggle_edit"]').click(function() {
516             var list_item_id = jQuery(this).data('listitemid');
517             var list_item_name = jQuery(this).data('listitemname');
518             var list_item_div = jQuery(this).data('listitemdiv');
519             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>';
520             jQuery("#"+list_item_div).empty().html(list_item_edit_html);
521         });
523         jQuery(document).on('click', 'button[name="list_item_edit_submit"]', function() {
524             var lo = new CXGN.List();
525             var list_id = jQuery('#list_id_div').html();
526             var input_id = jQuery(this).data('inputid');
527             lo.updateItem(list_id, jQuery("#"+input_id).data('listitemid'), jQuery("#"+input_id).val());
528             lo.renderItems(div, list_id);
529         });
530     },
532     renderPublicItems: function(div, list_id) {
533         var list_data = this.getListData(list_id);
534         var items = list_data.elements;
535         var list_type = list_data.type_name;
536         var list_name = this.publicListNameById(list_id);
538         var html = '';
539         html += '<table class="table"><tr><td>List ID</td><td id="list_id_div">'+list_id+'</td></tr>';
540         html += '<tr><td>List name:</td>';
541         html += '<td>'+list_name+'</td></tr>';
542         html += '<tr><td>Type:</td><td>'+list_type+'</td></tr>';
543         html += '</table>';
544         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>';
545         for(var n=0; n<items.length; n++) {
546             html = html +'<tr><td>'+ items[n][1] + '</td></tr>';
547         }
548         html += '</tbody></table>';
550         jQuery('#'+div+'_div').html(html);
552         jQuery('#public_list_item_dialog_datatable').DataTable({
553             destroy: true,
554             scrollY:        '30vh',
555             scrollCollapse: true,
556             paging:         false,
557         });
558     },
560     existsList: function(name) {
561         var list_id = 0;
562         jQuery.ajax( {
563             url: '/list/exists',
564             async: false,
565             data: { 'name': name },
566             success: function(response) {
567                 list_id = response.list_id;
568             }
569         });
570         return list_id;
571     },
573     existsItem: function(list_id, name) {
574         var list_item_id =0;
575         jQuery.ajax( {
576             url: '/list/exists_item',
577             async: false,
578             data: { 'list_id' : list_id, 'name':name },
579             success: function(response) {
580                 list_item_id = response.list_item_id;
581             }
582         });
583         return list_item_id;
584     },
586     addToList: function(list_id, text) {
587         if (! text) {
588             return;
589         }
590         var list = text.split("\n");
591         var duplicates = [];
593         var info = this.addBulk(list_id, list);
595         return info;
597     },
599     addCrossProgenyToList: function(list_id, text) {
600         if (! text) {
601             return;
602         }
603         var list = text.split("\n");
604         list = list.filter(function(n){ return n != '' });
605         console.log(list);
606         var addeditems;
607         jQuery.ajax( {
608             url: '/list/add_cross_progeny',
609             async: false,
610             data: { 'list_id':list_id, 'cross_id_list' : JSON.stringify(list) },
611             success: function(response) {
612                 console.log(response);
613                 addeditems = response.success.count;
614             }
615         });
616         //var info = this.addBulk(list_id, list);
618         return addeditems;
619     },
621     /* listSelect: Creates an html select with lists of requested types.
623        Parameters:
624          div_name: The div_name where the select should appear
625          types: a list of list types that should be listed in the menu
626          add_empty_element: text. if present, add an empty element with the
627            provided text as description
628     */
630     listSelect: function(div_name, types, empty_element, refresh) {
631         var lists = new Array();
632         var public_lists = new Array();
634         if (types) {
635             for (var n=0; n<types.length; n++) {
636                 var more = this.availableLists(types[n]);
637                 var more_public_lists = this.publicLists(types[n]);
638                 if (more) {
639                     for (var i=0; i<more.length; i++) {
640                         lists.push(more[i]);
641                     }
642                 }
643                 if (more_public_lists) {
644                     for (var i=0; i<more_public_lists.length; i++) {
645                         public_lists.push(more_public_lists[i]);
646                     }
647                 }
648             }
649         }
650         else {
651             lists = this.availableLists();
652             public_lists = this.publicLists();
653         }
655         var html = '<select class="form-control input-sm" id="'+div_name+'_list_select" name="'+div_name+'_list_select" >';
656         if (empty_element) {
657             html += '<option value="" >'+empty_element+'</option>\n';
658         }
659         html += '<option disabled>--------YOUR LISTS BELOW--------</option>';
660         for (var n=0; n<lists.length; n++) {
661             html += '<option value='+lists[n][0]+'>'+lists[n][1]+'</option>';
662         }
663         html += '<option disabled>--------PUBLIC LISTS BELOW--------</option>';
664         for (var n=0; n<public_lists.length; n++) {
665             html += '<option value='+public_lists[n][0]+'>'+public_lists[n][1]+'</option>';
666         }
668   if (refresh) {
669     if (types.length > 1) { types = types.join(',') };
670           html = '<div class="input-group" id="'+div_name+'_list_select_div">'+html+'</select><span class="input-group-btn"><button class="btn btn-default" type="button" id="'+div_name+'_list_refresh" title="Refresh lists" onclick="refreshListSelect(\''+div_name+'\',\''+types+'\')"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span></button></span></div>';
671     return html;
672   }
673   else {
674     html = html + '</select>';
675         return html;
676   }
679     updateName: function(list_id, new_name) {
680         jQuery.ajax( {
681             url: '/list/name/update',
682             async: false,
683             data: { 'name' : new_name, 'list_id' : list_id },
684             success: function(response) {
685                 if (response.error) {
686                     alert(response.error);
687                     return;
688                 }
689                 else {
690                     alert("The name of the list was changed to "+new_name);
691                 }
692             },
693             error: function(response) { alert("An error occurred."); }
694         });
695         this.renderLists('list_dialog');
696     },
698     validate: function(list_id, type, non_interactive) {
699         var missing = new Array();
700         var error = 0;
701         jQuery.ajax( {
702             url: '/list/validate/'+list_id+'/'+type,
703             async: false,
704             success: function(response) {
705                 //console.log(response);
706                 if (response.error) {
707                     alert(response.error);
708                 } else {
709                     missing = response.missing;
710                 }
711             },
712             error: function(response) {
713                 alert("An error occurred while validating the list "+list_id);
714                 error=1;
715             }
716         });
718         if (error === 1 ) { return; }
720         if (missing.length==0) {
721             if (!non_interactive) { alert("This list passed validation."); }
722             return 1;
723         } else {
725             if (type == 'accessions') {
726                 jQuery("#validate_accession_error_display tbody").html('');
728                 var missing_accessions_html = "<div class='well well-sm'><h3>List of Accessions Not Valid!</h3><div id='validate_stock_missing_accessions' style='display:none'></div></div><div id='validate_stock_add_missing_accessions_for_list' style='display:none'></div><button class='btn btn-primary' onclick=\"window.location.href='/breeders/accessions?list_id="+list_id+"'\" >Go to Manage Accessions to add these new accessions to database now.</button><br/><br/><div class='well well-sm'><h3>Optional: Add Missing Accessions to A List</h3><div id='validate_stock_add_missing_accessions_for_list_div'></div></div>";
731                 jQuery("#validate_stock_add_missing_accessions_html").html(missing_accessions_html);
733                 var missing_accessions_vals = '';
734                 var missing_accessions_vals_for_list = '';
735                 for(var i=0; i<missing.length; i++) {
736                     missing_accessions_vals = missing_accessions_vals + missing[i] + '<br/>';
737                     missing_accessions_vals_for_list = missing_accessions_vals_for_list + missing[i] + '\n';
738                 }
740                 jQuery("#validate_stock_missing_accessions").html(missing_accessions_vals);
741                 jQuery("#validate_stock_add_missing_accessions_for_list").html(missing_accessions_vals_for_list);
742                 addToListMenu('validate_stock_add_missing_accessions_for_list_div', 'validate_stock_add_missing_accessions_for_list', {
743                     selectText: true,
744                     listType: 'accessions'
745                 });
747                 jQuery("#validate_accession_error_display tbody").append(missing_accessions_vals);
748                 jQuery('#validate_accession_error_display').modal("show");
750                 //alert("List validation failed. Elements not found: "+ missing.join(","));
751                 //return 0;
752             } else {
753                 alert('List did not pass validation because of these items: '+missing.join(", "));
754             }
755             return;
756         }
757     },
758                 seedlotSearch: function(list_id){
759                         var self = this;
760                         jQuery('#availible_seedlots_modal').modal('show');
761                         var accessions = this.getList(list_id);
762                         if (window.available_seedlots){
763                                 window.available_seedlots.build_table(accessions);
764                         } else {
765                                 throw "avalilible_seedlots.mas not included";
766                         }
767                         jQuery('#new-list-from-seedlots').unbind('submit');
768                         jQuery("#new-list-from-seedlots").submit(function(){
769                                 jQuery('#working_modal').modal('show');
770                                 try {
771                                         var form = jQuery(this).serializeArray().reduce(function(map,obj){
772                                                 map[obj.name] = obj.value;
773                                                 return map;
774                                         }, {});
775                                         console.log(form);
776                                         var list = new CXGN.List();
777                                         var names = window.available_seedlots.get_selected().map(function(d){
778                                                 return d.name;
779                                         });
780                                         var newListID = list.newList(form["name"]);
781                                         if (!newListID) throw "List creation failed.";
782                                         list.setListType(newListID,"seedlots");
783                                         var count = list.addBulk(newListID, names);
784                                         if (!count) throw "Added nothing to list or addition failed.";
785                                         jQuery('#working_modal').modal('hide');
786                                         alert("List \""+form["name"]+"\" created with "+count+" entries.");
787                                         self.renderLists('list_dialog');
788                                 }
789                                 catch(err) {
790                                         setTimeout(function(){throw err;});
791                                 }
792                                 finally {
793                                         jQuery('#working_modal').modal('hide');
794                                         return false;
795                                 }
796                         });
797                 },
798                 synonymSearch: function(list_id){
799       var self = this;
800                         jQuery.ajax( {
801                                         url: '/list/desynonymize?list_id='+list_id,
802                                         async: false,
803                                         beforeSend: function(){
804                                                         jQuery('#working_modal').modal('show');
805                                         },
806                                         success: function(response) {
807                                                         jQuery('#working_modal').modal('hide');
808                                                         console.log(response);
809                                                         if (response.success) {
810                                                                 html = "";
811                                                                 jQuery('#synonym_search_result_display').modal('show');
812                                                                 html += "<table class='table table-hover table-bordered'><thead><tr><th>Name in List</th><th>Unique Name</th></tr></thead><tbody>";
813                                                                 for (var i = 0; i < response.previous_list.length; i++) {
814                                                                         if (response.previous_list[i] in response.synonyms){
815                                                                                 html+="<tr><td>"+response.previous_list[i]+"</td><td>&harr; "+response.previous_list[i]+"</td></tr>";
816                                                                         } else {
817                                                                                 var match = false;
818                                                                                 for (var uniquename in response.synonyms) {
819                                                                             if (!match && response.synonyms.hasOwnProperty(uniquename)) {
820                                                                               if (response.synonyms[uniquename].indexOf(response.previous_list[i])>=0){
821                                                                                                         match = true;
822                                                                                                         html+="<tr><td><span style='color:blue'>"+response.previous_list[i]+"</span></td>";
823                                                                                                         html+="<td><span style='color:blue'>&rarr; "+uniquename+"</span></td></tr>";
824                                                                                                 }
825                                                                             }
826                                                                                 }
827                                                                                 if (!match){
828                                                                                         html+="<tr><td><span style='color:red'>"+response.previous_list[i]+"</span></td>";
829                                                                                         html+="<td><span style='color:red'>&times; Not a Name or Synonym</span></td></tr>";
830                                                                                 }
831                                                                         }
832                                                                 }
833                                                                 html += "</tbody></table>";
834                                                                 jQuery('#synonym_search_result_display_html').html(html);
835                                                                 jQuery('#new-list-from-unames').unbind('submit');
836                 jQuery('#new-list-from-unames').submit(function () {
837                   jQuery('#working_modal').modal('show');
838                   try {
839                     var form = jQuery(this).serializeArray().reduce(function(map,obj){
840                                                                                         map[obj.name] = obj.value;
841                                                                                         return map;
842                                                                                 }, {});
843                                                                                 console.log(form);
844                     var list = new CXGN.List();
845                     var newListID = list.newList(form["name"]);
846                     if (!newListID) throw "List creation failed.";
847                                                                                 list.setListType(newListID,response.list_type);
848                     var count = list.addBulk(newListID,response.list);
849                     if (!count) throw "Added nothing to list or addition failed.";
850                                                                                 jQuery('#working_modal').modal('hide');
851                     alert("List \""+form["name"]+"\" created with "+count+" entries.");
852                     self.renderLists('list_dialog');
853                   }
854                   catch(err) {
855                     setTimeout(function(){throw err;});
856                   }
857                   finally {
858                     jQuery('#working_modal').modal('hide');
859                     return false;
860                   }
861                 });
862                                                         } else {
863                                                                         alert("An error occurred while desynonymizing list ID:"+list_id);
864                                                         }
865                                         },
866                                         error: function(response) {
867                                                         alert("An error occurred while desynonymizing list ID:"+list_id);
868                                                         jQuery('#working_modal').modal('hide');
869                                                         error=1;
870                                         }
871                         });
872                 },
873     fuzzySearch: function(list_id, list_type) {
874         var error = 0;
875         jQuery.ajax( {
876             url: '/list/fuzzysearch/'+list_id+'/'+list_type,
877             async: false,
878             beforeSend: function(){
879                 jQuery('#working_modal').modal('show');
880             },
881             success: function(response) {
882                 jQuery('#working_modal').modal('hide');
883                 //console.log(response);
884                 var html = "";
885                 if (response.success) {
886                     html += "<h2>Accessions that exactly match</h2>";
887                     html += "<table class='table table-hover table-bordered' ><thead><tr><th>Found In Database</th></tr></thead><tbody>";
888                     for(var i=0; i<response.found.length; i++){
889                         html += "<tr><td>"+response.found[i].unique_name+"</td></tr>";
890                     }
891                     html += "</tbody></table>";
892                     html += "<h2>Accessions that fuzzy match</h2>";
893                     html += "<table class='table table-hover table-bordered' ><thead><tr><th>Name In Your List</th><th>Found In Database</th><th>Distance Score</th></tr></thead><tbody>";
894                     for(var i=0; i<response.fuzzy.length; i++){
895                         for(j=0; j <response.fuzzy[i].matches.length; j++){
896                             if (response.fuzzy[i].matches[j].is_synonym){
897                                 html += "<tr><td>"+response.fuzzy[i].name+"</td><td>"+response.fuzzy[i].matches[j].name+" (SYNONYM OF: "+response.fuzzy[i].matches[j].synonym_of+") </td><td>"+response.fuzzy[i].matches[j].distance+"</td></tr>";
898                             } else {
899                                 html += "<tr><td>"+response.fuzzy[i].name+"</td><td>"+response.fuzzy[i].matches[j].name+"</td><td>"+response.fuzzy[i].matches[j].distance+"</td></tr>";
900                             }
901                         }
902                     }
903                     html += "</tbody></table>";
904                     html += "<h2>Accessions that have no match</h2>";
905                     html += "<table class='table table-hover table-bordered' ><thead><tr><th>Not Found In Database</th></tr></thead><tbody>";
906                     for(var i=0; i<response.absent.length; i++){
907                         html += "<tr><td>"+response.absent[i]+"</td></tr>";
908                     }
909                     html += "</tbody></table>";
910                     html += "<form id='fuzzy_search_result_download' method='post' action='/ajax/accession_list/fuzzy_download' target='TheWindow'><input type='hidden' name='fuzzy_response' value='"+JSON.stringify(response.fuzzy)+"' /></form>";
911                     jQuery('#fuzzy_search_result_display_html').html(html);
912                     jQuery('#fuzzy_search_result_display').modal('show');
913                 } else {
914                     alert("An error occurred while fuzzy searching list "+list_id);
915                 }
916             },
917             error: function(response) {
918                 alert("An error occurred while validating the list "+list_id);
919                 error=1;
920             }
921         });
923         if (error === 1 ) { return; }
924     },
926     transform: function(list_id, transform_name) {
927         var transformed = new CXGN.List();
928         var ajaxResponse = [];
929         jQuery.ajax( {
930             url: '/list/transform/'+list_id+'/'+transform_name,
931             async: false,
932             success: function(response) {
933                 if (response.error) {
934                     alert(response.error);
935                 }
936                 else {
937                     ajaxResponse = response;
938                     //console.log("transformed="+ajaxResponse);
939                 }
940             },
941             error: function(response) { alert("An error occurred while validating the list "+list_id); }
942         });
943         return ajaxResponse.transform;
944     },
946     transform2Ids: function(list_id, data) {
947         if (data === undefined) var data = this.getListData(list_id);
948         //console.log("data ="+JSON.stringify(data));
949         var list_type = data.type_name;
951         var new_type;
952         switch (list_type)
953         {
954           case "traits":
955               new_type = 'traits_2_trait_ids';
956               break;
957           case "locations":
958               new_type = 'locations_2_location_ids';
959               break;
960           case "trials":
961           case "breeding_programs":
962               new_type = 'projects_2_project_ids'; 
963               break;
964           case "accessions":
965               new_type = 'accessions_2_accession_ids';
966               break;
967           case "plots":
968               new_type = 'plots_2_plot_ids';
969               break;
970           default:
971               return { 'error' : "cannot convert the list because of unknown type" };
972         }
973         //if (window.console) console.log("new type = "+new_type);
974         var transformed = this.transform(list_id, new_type);
975         //if (window.console) console.log("transformed="+JSON.stringify(transformed));
976         return transformed;
978     }
981 function setUpLists() {
982     jQuery("button[name='lists_link']").click(
983         function() { show_lists(); }
984     );
988 function show_lists() {
989    jQuery('#list_dialog').modal("show");
991     var l = new CXGN.List();
992     l.renderLists('list_dialog');
995 /* deprecated */
996 function pasteListMenu (div_name, menu_div, button_name, list_type) {
997     var lo = new CXGN.List();
999     var html='';
1001     if (button_name === undefined) {
1002         button_name = 'paste';
1003     }
1004     if (list_type){
1005         html = lo.listSelect(div_name, [list_type]);
1006     }else {
1007         html = lo.listSelect(div_name);
1008     }
1009     html = html + '<button class="btn btn-info btn-sm" type="button" value="'+button_name+'" onclick="javascript:pasteList(\''+div_name+'\')" >'+button_name+'</button>';
1011     jQuery('#'+menu_div).html(html);
1014 function pasteList(div_name) {
1015     var lo = new CXGN.List();
1016     var list_id = jQuery('#'+div_name+'_list_select').val();
1017         console.log(list_id);
1018     var list = lo.getList(list_id);
1019         console.log(list);
1020     // textify list
1021     var list_text = '';
1022     for (var n=0; n<list.length; n++) {
1023       list_text = list_text + list[n]+"\r\n";
1024     }
1025         console.log(list_text);
1026     jQuery('#'+div_name).val(list_text);
1027   }
1029   /* refreshListSelect: refreshes an html select with lists of requested types.
1031      Parameters:
1032        div_name: The div_name where the select should appear
1033        types: a list of list types that should be listed in the menu
1034   */
1036   function refreshListSelect(div_name, types) {
1037     var lo = new CXGN.List();
1038     var types = types.split(",");
1039     document.getElementById(div_name).innerHTML = (lo.listSelect(div_name, types, 'Options refreshed.', 'refresh')); 
1040     //console.log("List options refreshed!");
1041   }
1044   addToListMenu
1046   Parameters:
1047   * listMenuDiv - the name of the div where the menu will be displayed
1048   * dataDiv - the div from which the data will be copied (can be a div, textarea, or html select
1049   * options - optional hash with the following keys:
1050     - selectText: if the dataDiv is an html select and selectText is true, the text and not the value will be copied into the list
1051     - listType: the type of lists to display in the menu
1052     - typesSourceDiv: obtain the type from this source div
1057 function addToListMenu(listMenuDiv, dataDiv, options) {
1058     var lo = new CXGN.List();
1060     var html;
1061     var selectText;
1062     var listType;
1063     var typeSourceDiv;
1064     var type;
1065     var addition_type;
1066     var list_name_value = "";
1068     if (options) {
1069         if (options.selectText) {
1070             selectText = options.selectText;
1071         }
1072         if (options.typeSourceDiv) {
1073             var sourcetype = getData(options.typeSourceDiv, selectText);
1074             if (sourcetype) {
1075                 type = sourcetype.replace(/(\n|\r)+$/, '');
1076             }
1077         }
1078         if (options.listType) {
1079             type = options.listType;
1080         }
1081         if (options.additionType) {
1082             addition_type = options.additionType;
1083         }
1084         if (options.listName){
1085             list_name_value = options.listName;
1086         }
1087     }
1089     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..." value="'+list_name_value+'"/>';
1090     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+'_addition_type" value="'+addition_type+'" /><input type="hidden" id="'+dataDiv+'_list_type" value="'+type+'" />';
1091     html += '<input class="btn btn-primary btn-sm" id="'+dataDiv+'_add_to_new_list" type="button" value="add to new list" /></div></div><br />';
1093     html += '<div class="row"><div class="col-sm-6" style="margin-right:0px; padding-right:0px;">'+lo.listSelect(dataDiv, [ type ]);
1095     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>';
1097     jQuery('#'+listMenuDiv).html(html);
1099     var list_id = 0;
1101     jQuery('#'+dataDiv+'_add_to_new_list').click( function() {
1102         var lo = new CXGN.List();
1103         var new_name = jQuery('#'+dataDiv+'_new_list_name').val();
1104         var type = jQuery('#'+dataDiv+'_list_type').val();
1105         var addition_type = jQuery('#'+dataDiv+'_addition_type').val();
1107         var data = getData(dataDiv, selectText);
1108         list_id = lo.newList(new_name);
1109         if (list_id > 0) {
1110             var elementsAdded;
1111             if (addition_type == 'cross_progeny') {
1112                 elementsAdded = lo.addCrossProgenyToList(list_id, data);
1113             } else {
1114                 elementsAdded = lo.addToList(list_id, data);
1115             }
1116             if (type) {
1117                 lo.setListType(list_id, type);
1118             }
1119             alert("Added "+elementsAdded+" list elements to list "+new_name+" and set type to "+type);
1120         }
1121     });
1123     jQuery('#'+dataDiv+'_button').click(
1124         function() {
1125             var data = getData(dataDiv, selectText);
1126             list_id = jQuery('#'+dataDiv+'_list_select').val();
1127             var lo = new CXGN.List();
1128             var elementsAdded = lo.addToList(list_id, data);
1130             alert("Added "+elementsAdded+" list elements");
1131             return list_id;
1132         }
1133     );
1139 function getData(id, selectText) {
1140     var divType = jQuery("#"+id).get(0).tagName;
1141     var data;
1143     if (divType == 'DIV' || divType =='SPAN' || divType === undefined) {
1144         data = jQuery('#'+id).html();
1145     }
1146     if (divType == 'SELECT' && selectText) {
1147         if (jQuery.browser.msie) {
1148             // Note: MS IE unfortunately removes all whitespace
1149             // in the jQuery().text() call. Program it out...
1150             //
1151             var selectbox = document.getElementById(id);
1152             var datalist = new Array();
1153             for (var n=0; n<selectbox.length; n++) {
1154                 if (selectbox.options[n].selected) {
1155                     var x=selectbox.options[n].text;
1156                     datalist.push(x);
1157                 }
1158             }
1159             data = datalist.join("\n");
1160             //alert("data:"+data);
1162         }
1163         else {
1164             data = jQuery('#'+id+" option:selected").text();
1165         }
1167     }
1168     if (divType == 'SELECT' && ! selectText) {
1169         var return_data = jQuery('#'+id).val();
1171         if (return_data instanceof Array) {
1172             data = return_data.join("\n");
1173         }
1174         else {
1175             data = return_data;
1176         }
1177     }
1178     if (divType == 'TEXTAREA') {
1179         data = jQuery('textarea#'+id).val();
1180     }
1181     return data;
1185 /* deprecated */
1186 function addTextToListMenu(div) {
1187     var lo = new CXGN.List();
1188     var html = lo.listSelect(div);
1189     html = html + '<input id="'+div+'_button" type="button" value="add to list" />';
1191     document.write(html);
1193     jQuery('#'+div+'_button').click(
1194         function() {
1195             var text = jQuery('textarea#div').val();
1196             var list_id = jQuery('#'+div+'_list_select').val();
1197             lo.addToList(list_id, text);
1198             lo.renderLists('list_dialog');
1199         }
1200     );
1203 /* deprecated */
1204 function addSelectToListMenu(div) {
1205     var lo = new CXGN.List();
1206     var html = lo.listSelect(div);
1207     html = html + '<input id="'+div+'_button" type="button" value="add to list" />';
1209     document.write(html);
1211     jQuery('#'+div+'_button').click(
1212         function() {
1213             var selected_items = jQuery('#'+div).val();
1214             var list_id = jQuery('#'+div+'_list_select').val();
1215             addArrayToList(selected_items, list_id);
1216             lo.renderLists('list_dialog');
1217         }
1218     );
1222 /* deprecated */
1223 // add the text in a div to a list
1224 function addDivToList(div_name) {
1225     var list_id = jQuery('#'+div_name+'_list_select').val();
1226     var lo = new CXGN.List();
1227     var list = jQuery('#'+div_name).val();
1228     var items = list.split("\n");
1230     for(var n=0; n<items.length; n++) {
1231         var added = lo.addItem(list_id, items[n]);
1232         if (added > 0) { }
1233     }
1236 /* deprecated */
1237 function addTextToList(div, list_id) {
1238     var lo = new CXGN.List();
1239     var item = jQuery('#'+div).val();
1240     var id = lo.addItem(list_id, item);
1241     if (id == 0) {
1242         alert('Item "'+item+'" was not added because it already exists');
1243     }
1244     lo.renderLists('list_dialog');
1247 /* deprecated */
1248 function addMultipleItemsToList(div, list_id) {
1249     var lo = new CXGN.List();
1250     var content = jQuery('#'+div).val();
1251     if (content == '') {
1252         alert("No items - Please enter items to add to the list.");
1253 return;
1254     }
1255 //    var items = content.split("\n");
1257   //  var duplicates = new Array();
1258     var items = content.split("\n");
1259     lo.addBulk(list_id, items);
1260    // for (var n=0; n<items.length; n++) {
1261 //      var id = lo.addItem(list_id, items[n]);
1262 //      if (id == 0) {
1263 //          duplicates.push(items[n]);
1264 //      }
1265   //  }
1266     //if (duplicates.length >0) {
1267 //      alert("The following items were not added because they are already in the list: "+ duplicates.join(", "));
1268   //  }
1269 //lo.renderLists('list_dialog');
1272 /* deprecated */
1273 function addArrayToList(items, list_id) {
1274 var lo = new CXGN.List();
1275    var duplicates = new Array();
1276     for (var n=0; n<items.length; n++) {
1277         var id = lo.addItem(list_id, items[n]);
1278         if (id == 0) {
1279             duplicates.push(items[n]);
1280         }
1281     }
1282     if (duplicates.length >0) {
1283         alert("The following items were not added because they are already in the list: "+ duplicates.join(", "));
1284     }
1287 function deleteList(list_id) {
1288     var lo = new CXGN.List();
1289     var list_name = lo.listNameById(list_id);
1290     if (confirm('Delete list "'+list_name+'"? (ID='+list_id+'). This cannot be undone.')) {
1291         lo.deleteList(list_id);
1292         lo.renderLists('list_dialog');
1293         alert('Deleted list '+list_name);
1294     }
1297 function togglePublicList(list_id) {
1298     jQuery.ajax({
1299         "url": "/list/public/toggle",
1300         "type": "POST",
1301         "data": {'list_id': list_id},
1302         success: function(r) {
1303             var lo = new CXGN.List();
1304             if (r.error) {
1305                 alert(r.error);
1306             } else if (r.r == 1) {
1307                 alert("List set to Private");
1308             } else if (r.r == 0) {
1309                 alert("List set to Public");
1310             }
1311             lo.renderLists('list_dialog');
1312         },
1313         error: function() {
1314             alert("Error Setting List to Public! List May Not Exist.");
1315         }
1316     });
1317     var lo = new CXGN.List();
1318     lo.renderLists('list_dialog');
1321 function makePublicList(list_id) {
1322     jQuery.ajax({
1323         "url": "/list/public/true",
1324         "type": "POST",
1325         "data": {'list_id': list_id},
1326         success: function(r) {
1327             var lo = new CXGN.List();
1328             if (r.error) {
1329                 alert(r.error);
1330             }
1331         },
1332         error: function() {
1333             alert("Error Setting List to Public! List May Not Exist.");
1334         }
1335     });
1338 function makePrivateList(list_id) {
1339     jQuery.ajax({
1340         "url": "/list/public/false",
1341         "type": "POST",
1342         "data": {'list_id': list_id},
1343         success: function(r) {
1344             var lo = new CXGN.List();
1345             if (r.error) {
1346                 alert(r.error);
1347             }
1348         },
1349         error: function() {
1350             alert("Error Setting List to Private! List May Not Exist.");
1351         }
1352     });
1355 function copyPublicList(list_id) {
1356     jQuery.ajax({
1357         "url": "/list/public/copy",
1358         "type": "POST",
1359         "data": {'list_id': list_id},
1360         success: function(r) {
1361             if (r.error) {
1362                 alert(r.error);
1363             } else if (r.success == 'true') {
1364                 alert("Public List Copied to Your Lists.");
1365             }
1366         },
1367         error: function() {
1368             alert("Error Copying Public List! List May Not Exist.");
1369         }
1370     });
1371     var lo = new CXGN.List();
1372     lo.renderLists('list_dialog');
1375 function deleteItemLink(list_item_id) {
1376     var lo = new CXGN.List();
1377     lo.deleteItem(list_item_id);
1378     lo.renderLists('list_dialog');
1381 function working_modal_show() {
1382     jQuery("#working_modal").modal('show');
1385 function working_modal_hide() {
1386     jQuery("#working_modal").modal('hide');
1389 function showListItems(div, list_id) {
1390     working_modal_show();
1391     var l = new CXGN.List();
1392     l.renderItems(div, list_id);
1393     jQuery('#'+div).modal("show");
1394     working_modal_hide();
1397 function showPublicListItems(div, list_id) {
1398     var l = new CXGN.List();
1399     jQuery('#'+div).modal("show");
1400     l.renderPublicItems(div, list_id);
1403 function addNewList(div_id) {
1404     var lo = new CXGN.List();
1405     var name = jQuery('#'+div_id).val();
1407     if (name == '') {
1408         alert("Please specify a name for the list.");
1409         return;
1410     }
1412     var list_id = lo.existsList(name);
1413     if (list_id > 0) {
1414         alert('The list '+name+' already exists. Please choose another name.');
1415         return;
1416     }
1417     lo.newList(name);
1418     lo.renderLists('list_item_dialog');
1421 function changeListType(html_select_id, list_id) {
1422     var type = jQuery('#'+html_select_id).val();
1423     var l = new CXGN.List();
1424     l.setListType(list_id, type);
1425     l.renderLists('list_dialog');
1429    validateList - check if all the elements in a list are of the correct type
1431    Parameters:
1432    * list_id: the id of the list
1433    * html_select_id: the id of the html select containing the type list
1437 function validateList(list_id, html_select_id) {
1438     var lo = new CXGN.List();
1439     var type = jQuery('#'+html_select_id).val();
1440     lo.validate(list_id, type);
1444    fuzzySearchList - perform a fuzzy search over the items in the list and return the match results of this search
1446    Parameters:
1447    * list_id: the id of the list
1448    * list_type: the type of the list
1452 function fuzzySearchList(list_id, list_type) {
1453     var lo = new CXGN.List();
1454     lo.fuzzySearch(list_id, list_type);
1457 function deleteSelectedListGroup(list_ids) {
1458     var arrayLength = list_ids.length;
1459     if (confirm('Delete the selected lists? This cannot be undone.')) {
1460         for (var i=0; i<arrayLength; i++) {
1461             var lo = new CXGN.List();
1462             lo.deleteList(list_ids[i]);
1463         }
1464         lo.renderLists('list_dialog');
1465     }
1468 function pasteTraitList(div_name) {
1469     var lo = new CXGN.List();
1470     var list_id = jQuery('#'+div_name+'_list_select').val();
1471   console.log(list_id);
1472     var list = lo.getList(list_id);
1473   console.log(list);
1475     var list_text = '<select class="form-control" id="select_traits_for_trait_file_2"  >';
1476     for (var n=0; n<list.length; n++) {
1477       list_text = list_text + '<option value="' + list[n] + '">' + list[n] + '</option>\n';
1478     }
1479     list_text = list_text + '</select>';
1480   console.log(list_text);
1481     jQuery('#'+div_name).html(list_text);
1482   }
1484 function makePublicSelectedListGroup(list_ids) {
1485     var arrayLength = list_ids.length;
1486     if (confirm('Make selected lists public?')) {
1487         for (var i=0; i<arrayLength; i++) {
1488             makePublicList(list_ids[i]);
1489         }
1490         var lo = new CXGN.List();
1491         lo.renderLists('list_dialog');
1492     }
1495 function makePrivateSelectedListGroup(list_ids) {
1496     var arrayLength = list_ids.length;
1497     if (confirm('Make selected lists private?')) {
1498         for (var i=0; i<arrayLength; i++) {
1499             makePrivateList(list_ids[i]);
1500         }
1501         var lo = new CXGN.List();
1502         lo.renderLists('list_dialog');
1503     }
1506 function combineSelectedListGroup(list_ids) {
1507     var arrayLength = list_ids.length;
1508     var list_name = jQuery('#new_combined_list_name').val();
1509     if (confirm('Combine selected lists into a new list called '+list_name+'?')) {
1510         var arrayItems = [];
1511         var lo = new CXGN.List();
1512         var first_list_type = lo.getListType(list_ids[0]);
1513         var same_list_types = true;
1514         for (var i=0; i<arrayLength; i++) {
1515             var list_type = lo.getListType(list_ids[i]);
1516             if (list_type != first_list_type) {
1517                 same_list_types = false;
1518                 if (!confirm('Are you sure you want to combine these list types: '+first_list_type+' and '+list_type)) {
1519                     return;
1520                 }
1521             }
1522         }
1523         var new_list_id = lo.newList(list_name);
1524         if (same_list_types == true) {
1525             lo.setListType(new_list_id, first_list_type);
1526         }
1527         for (var i=0; i<arrayLength; i++) {
1528             list = lo.getListData(list_ids[i]);
1529             var numElements = list.elements.length;
1530             for (var j=0; j<numElements; j++) {
1531                 arrayItems.push(list.elements[j][1]);
1532             }
1533         }
1534         lo.addBulk(new_list_id, arrayItems);
1535         lo.renderLists('list_dialog');
1536     }
1539 function downloadFuzzyResponse(){
1540     var f = document.getElementById('fuzzy_search_result_download');
1541     window.open('', 'TheWindow');
1542     f.submit();
1545   jQuery(document).ready(function() {
1546     jQuery("#list_item_dialog").draggable();
1547     jQuery("#list_dialog").draggable();
1548     jQuery("#public_list_dialog").draggable();