6 CXGN.List - a javascript library to implement the lists on the SGN platform
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.
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)
41 Lukas Mueller <lam87@cornell.edu>
47 //JSAN.use('jqueryui');
49 if (!CXGN) CXGN = function () { };
51 CXGN.List = function () {
56 CXGN.List.prototype = {
58 // Return the data as a straight list
60 getList: function(list_id) {
64 url: '/list/contents/'+list_id,
66 success: function(response) {
68 //document.write(response.error);
74 error: function(response) {
75 alert("An error occurred.");
83 // this function also returns some metadata about
84 // list, namely its type.
86 getListData: function(list_id) {
92 data: { 'list_id': list_id },
93 success: function(response) {
95 alert(response.error);
106 getListType: function(list_id) {
110 url: '/list/type/'+list_id,
112 success: function(response) {
113 if (response.error) {
114 alert(response.error);
117 type = response.list_type;
122 alert('An error occurred. Cannot determine type. ');
129 setListType: function(list_id, type) {
132 url: '/list/type/'+list_id+'/'+type,
134 success: function(response) {
135 if (response.error) {
136 alert(response.error);
139 //alert('Type of list '+list_id+' set to '+type);
146 allListTypes: function() {
149 url: '/list/alltypes',
151 success: function(response) {
152 if (response.error) {
153 alert(response.error);
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" ';
173 html += '<option name="'+types[i][1]+'"'+selected_html+'>'+types[i][1]+'</option>';
179 newList: function(name) {
180 var oldListId = this.existsList(name);
184 alert('Please provide a name for the new list.');
188 if (oldListId === null) {
192 data: { 'name': name },
193 success: function(response) {
194 if (response.error) {
195 alert(response.error);
198 newListId=response.list_id;
205 alert('A list with name "'+ name + '" already exists. Please choose another list name.');
208 alert("An error occurred. Cannot create new list right now.");
212 availableLists: function(list_type) {
215 url: '/list/available',
216 data: { 'type': list_type },
218 success: function(response) {
219 if (response.error) {
220 //alert(response.error); //do not alert here
224 error: function(response) {
225 alert("An error occurred");
231 publicLists: function(list_type) {
234 url: '/list/available_public',
235 data: { 'type': list_type },
237 success: function(response) {
238 if (response.error) {
239 //alert(response.error); //do not alert here
243 error: function(response) {
244 alert("An error occurred");
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 ) {
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);
266 var new_list_item_id = this.existsItem(list_id,item);
267 return new_list_item_id;
272 addBulk: function(list_id, items) {
273 var elements = items.join("\t");
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);
286 if (response.duplicates) {
287 alert("The following items are already in the list and were not added: "+response.duplicates.join(", "));
289 count = response.success;
292 error: function(response) {
293 alert("ERROR: "+response);
299 removeItem: function(list_id, item_id) {
302 url: '/list/item/remove',
303 data: { 'list_id': list_id, 'item_id': item_id }
307 updateItem: function(list_id, item_id, content) {
308 var trimmed_content = content.trim();
311 url: '/list/item/update',
312 data: { 'list_id': list_id, 'item_id': item_id, 'content': trimmed_content }
316 deleteList: function(list_id) {
320 data: { 'list_id': list_id }
324 renderLists: function(div) {
325 var lists = this.availableLists();
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);
334 html += '<table class="table table-hover table-condensed">';
335 html += '<thead><tr><th> </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>';
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();
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');
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='';
374 list_group_select_action_html += '';
377 jQuery("input[name='list_select_checkbox']:checked").each(function() {
378 selected.push(jQuery(this).attr('value'));
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">';
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> <a id="make_public_selected_list_group" class="btn btn-primary btn-sm" style="color:white" href="javascript:makePublicSelectedListGroup(['+selected+'])">Make Public</a> <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> <a id="make_public_selected_list_group" class="btn btn-primary btn-sm" style="color:white" href="javascript:makePublicSelectedListGroup(['+selected+'])">Make Public</a> <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>';
387 list_group_select_action_html += '</div></div>';
389 jQuery("#list_group_select_action").html(list_group_select_action_html);
393 renderPublicLists: function(div) {
394 var lists = this.publicLists();
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> </th><th> </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>';
407 html = html + '</tbody></table>';
409 jQuery('#'+div).html(html);
411 jQuery('#public_list_data_table').DataTable({
413 "columnDefs": [ { "orderable": false, "targets": [3,4,5] } ]
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]; }
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]; }
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);
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> </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>';
450 html += '</tbody></table>';
452 jQuery('#'+div+'_div').html(html);
454 jQuery('#list_item_dialog_datatable').DataTable({
457 scrollCollapse: true,
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>');
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>');
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>');
473 jQuery('#fuzzySearchAccessionListDiv').html('');
474 jQuery('#availableSeedlotButtonDiv').html('')
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>');
479 jQuery('#synonymListButtonDiv').html('');
483 for (var n=0; n<items.length; n++) {
484 var list_item_id = items[n][0];
486 jQuery('#'+items[n][0]).click(
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');
497 jQuery('#dialog_add_list_item_button').click(
499 addMultipleItemsToList('dialog_add_list_item', list_id);
500 var lo = new CXGN.List();
501 lo.renderItems(div, list_id);
505 jQuery('#updateNameButton').click(
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);
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);
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);
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);
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>';
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>';
548 html += '</tbody></table>';
550 jQuery('#'+div+'_div').html(html);
552 jQuery('#public_list_item_dialog_datatable').DataTable({
555 scrollCollapse: true,
560 existsList: function(name) {
565 data: { 'name': name },
566 success: function(response) {
567 list_id = response.list_id;
573 existsItem: function(list_id, name) {
576 url: '/list/exists_item',
578 data: { 'list_id' : list_id, 'name':name },
579 success: function(response) {
580 list_item_id = response.list_item_id;
586 addToList: function(list_id, text) {
590 var list = text.split("\n");
593 var info = this.addBulk(list_id, list);
599 addCrossProgenyToList: function(list_id, text) {
603 var list = text.split("\n");
604 list = list.filter(function(n){ return n != '' });
608 url: '/list/add_cross_progeny',
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;
616 //var info = this.addBulk(list_id, list);
621 /* listSelect: Creates an html select with lists of requested types.
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
630 listSelect: function(div_name, types, empty_element, refresh) {
631 var lists = new Array();
632 var public_lists = new Array();
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]);
639 for (var i=0; i<more.length; i++) {
643 if (more_public_lists) {
644 for (var i=0; i<more_public_lists.length; i++) {
645 public_lists.push(more_public_lists[i]);
651 lists = this.availableLists();
652 public_lists = this.publicLists();
655 var html = '<select class="form-control input-sm" id="'+div_name+'_list_select" name="'+div_name+'_list_select" >';
657 html += '<option value="" >'+empty_element+'</option>\n';
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>';
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>';
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>';
674 html = html + '</select>';
679 updateName: function(list_id, new_name) {
681 url: '/list/name/update',
683 data: { 'name' : new_name, 'list_id' : list_id },
684 success: function(response) {
685 if (response.error) {
686 alert(response.error);
690 alert("The name of the list was changed to "+new_name);
693 error: function(response) { alert("An error occurred."); }
695 this.renderLists('list_dialog');
698 validate: function(list_id, type, non_interactive) {
699 var missing = new Array();
702 url: '/list/validate/'+list_id+'/'+type,
704 success: function(response) {
705 //console.log(response);
706 if (response.error) {
707 alert(response.error);
709 missing = response.missing;
712 error: function(response) {
713 alert("An error occurred while validating the list "+list_id);
718 if (error === 1 ) { return; }
720 if (missing.length==0) {
721 if (!non_interactive) { alert("This list passed validation."); }
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';
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', {
744 listType: 'accessions'
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(","));
753 alert('List did not pass validation because of these items: '+missing.join(", "));
758 seedlotSearch: function(list_id){
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);
765 throw "avalilible_seedlots.mas not included";
767 jQuery('#new-list-from-seedlots').unbind('submit');
768 jQuery("#new-list-from-seedlots").submit(function(){
769 jQuery('#working_modal').modal('show');
771 var form = jQuery(this).serializeArray().reduce(function(map,obj){
772 map[obj.name] = obj.value;
776 var list = new CXGN.List();
777 var names = window.available_seedlots.get_selected().map(function(d){
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');
790 setTimeout(function(){throw err;});
793 jQuery('#working_modal').modal('hide');
798 synonymSearch: function(list_id){
801 url: '/list/desynonymize?list_id='+list_id,
803 beforeSend: function(){
804 jQuery('#working_modal').modal('show');
806 success: function(response) {
807 jQuery('#working_modal').modal('hide');
808 console.log(response);
809 if (response.success) {
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>↔ "+response.previous_list[i]+"</td></tr>";
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){
822 html+="<tr><td><span style='color:blue'>"+response.previous_list[i]+"</span></td>";
823 html+="<td><span style='color:blue'>→ "+uniquename+"</span></td></tr>";
828 html+="<tr><td><span style='color:red'>"+response.previous_list[i]+"</span></td>";
829 html+="<td><span style='color:red'>× Not a Name or Synonym</span></td></tr>";
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');
839 var form = jQuery(this).serializeArray().reduce(function(map,obj){
840 map[obj.name] = obj.value;
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');
855 setTimeout(function(){throw err;});
858 jQuery('#working_modal').modal('hide');
863 alert("An error occurred while desynonymizing list ID:"+list_id);
866 error: function(response) {
867 alert("An error occurred while desynonymizing list ID:"+list_id);
868 jQuery('#working_modal').modal('hide');
873 fuzzySearch: function(list_id, list_type) {
876 url: '/list/fuzzysearch/'+list_id+'/'+list_type,
878 beforeSend: function(){
879 jQuery('#working_modal').modal('show');
881 success: function(response) {
882 jQuery('#working_modal').modal('hide');
883 //console.log(response);
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>";
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>";
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>";
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>";
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');
914 alert("An error occurred while fuzzy searching list "+list_id);
917 error: function(response) {
918 alert("An error occurred while validating the list "+list_id);
923 if (error === 1 ) { return; }
926 transform: function(list_id, transform_name) {
927 var transformed = new CXGN.List();
928 var ajaxResponse = [];
930 url: '/list/transform/'+list_id+'/'+transform_name,
932 success: function(response) {
933 if (response.error) {
934 alert(response.error);
937 ajaxResponse = response;
938 //console.log("transformed="+ajaxResponse);
941 error: function(response) { alert("An error occurred while validating the list "+list_id); }
943 return ajaxResponse.transform;
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;
955 new_type = 'traits_2_trait_ids';
958 new_type = 'locations_2_location_ids';
961 case "breeding_programs":
962 new_type = 'projects_2_project_ids';
965 new_type = 'accessions_2_accession_ids';
968 new_type = 'plots_2_plot_ids';
971 return { 'error' : "cannot convert the list because of unknown type" };
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));
981 function setUpLists() {
982 jQuery("button[name='lists_link']").click(
983 function() { show_lists(); }
988 function show_lists() {
989 jQuery('#list_dialog').modal("show");
991 var l = new CXGN.List();
992 l.renderLists('list_dialog');
996 function pasteListMenu (div_name, menu_div, button_name, list_type) {
997 var lo = new CXGN.List();
1001 if (button_name === undefined) {
1002 button_name = 'paste';
1005 html = lo.listSelect(div_name, [list_type]);
1007 html = lo.listSelect(div_name);
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);
1022 for (var n=0; n<list.length; n++) {
1023 list_text = list_text + list[n]+"\r\n";
1025 console.log(list_text);
1026 jQuery('#'+div_name).val(list_text);
1029 /* refreshListSelect: refreshes an html select with lists of requested types.
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
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!");
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();
1066 var list_name_value = "";
1069 if (options.selectText) {
1070 selectText = options.selectText;
1072 if (options.typeSourceDiv) {
1073 var sourcetype = getData(options.typeSourceDiv, selectText);
1075 type = sourcetype.replace(/(\n|\r)+$/, '');
1078 if (options.listType) {
1079 type = options.listType;
1081 if (options.additionType) {
1082 addition_type = options.additionType;
1084 if (options.listName){
1085 list_name_value = options.listName;
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);
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);
1111 if (addition_type == 'cross_progeny') {
1112 elementsAdded = lo.addCrossProgenyToList(list_id, data);
1114 elementsAdded = lo.addToList(list_id, data);
1117 lo.setListType(list_id, type);
1119 alert("Added "+elementsAdded+" list elements to list "+new_name+" and set type to "+type);
1123 jQuery('#'+dataDiv+'_button').click(
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");
1139 function getData(id, selectText) {
1140 var divType = jQuery("#"+id).get(0).tagName;
1143 if (divType == 'DIV' || divType =='SPAN' || divType === undefined) {
1144 data = jQuery('#'+id).html();
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...
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;
1159 data = datalist.join("\n");
1160 //alert("data:"+data);
1164 data = jQuery('#'+id+" option:selected").text();
1168 if (divType == 'SELECT' && ! selectText) {
1169 var return_data = jQuery('#'+id).val();
1171 if (return_data instanceof Array) {
1172 data = return_data.join("\n");
1178 if (divType == 'TEXTAREA') {
1179 data = jQuery('textarea#'+id).val();
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(
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');
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(
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');
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]);
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);
1242 alert('Item "'+item+'" was not added because it already exists');
1244 lo.renderLists('list_dialog');
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.");
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]);
1263 // duplicates.push(items[n]);
1266 //if (duplicates.length >0) {
1267 // alert("The following items were not added because they are already in the list: "+ duplicates.join(", "));
1269 //lo.renderLists('list_dialog');
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]);
1279 duplicates.push(items[n]);
1282 if (duplicates.length >0) {
1283 alert("The following items were not added because they are already in the list: "+ duplicates.join(", "));
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);
1297 function togglePublicList(list_id) {
1299 "url": "/list/public/toggle",
1301 "data": {'list_id': list_id},
1302 success: function(r) {
1303 var lo = new CXGN.List();
1306 } else if (r.r == 1) {
1307 alert("List set to Private");
1308 } else if (r.r == 0) {
1309 alert("List set to Public");
1311 lo.renderLists('list_dialog');
1314 alert("Error Setting List to Public! List May Not Exist.");
1317 var lo = new CXGN.List();
1318 lo.renderLists('list_dialog');
1321 function makePublicList(list_id) {
1323 "url": "/list/public/true",
1325 "data": {'list_id': list_id},
1326 success: function(r) {
1327 var lo = new CXGN.List();
1333 alert("Error Setting List to Public! List May Not Exist.");
1338 function makePrivateList(list_id) {
1340 "url": "/list/public/false",
1342 "data": {'list_id': list_id},
1343 success: function(r) {
1344 var lo = new CXGN.List();
1350 alert("Error Setting List to Private! List May Not Exist.");
1355 function copyPublicList(list_id) {
1357 "url": "/list/public/copy",
1359 "data": {'list_id': list_id},
1360 success: function(r) {
1363 } else if (r.success == 'true') {
1364 alert("Public List Copied to Your Lists.");
1368 alert("Error Copying Public List! List May Not Exist.");
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();
1408 alert("Please specify a name for the list.");
1412 var list_id = lo.existsList(name);
1414 alert('The list '+name+' already exists. Please choose another 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
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
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]);
1464 lo.renderLists('list_dialog');
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);
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';
1479 list_text = list_text + '</select>';
1480 console.log(list_text);
1481 jQuery('#'+div_name).html(list_text);
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]);
1490 var lo = new CXGN.List();
1491 lo.renderLists('list_dialog');
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]);
1501 var lo = new CXGN.List();
1502 lo.renderLists('list_dialog');
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)) {
1523 var new_list_id = lo.newList(list_name);
1524 if (same_list_types == true) {
1525 lo.setListType(new_list_id, first_list_type);
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]);
1534 lo.addBulk(new_list_id, arrayItems);
1535 lo.renderLists('list_dialog');
1539 function downloadFuzzyResponse(){
1540 var f = document.getElementById('fuzzy_search_result_download');
1541 window.open('', 'TheWindow');
1545 jQuery(document).ready(function() {
1546 jQuery("#list_item_dialog").draggable();
1547 jQuery("#list_dialog").draggable();
1548 jQuery("#public_list_dialog").draggable();