d3ed4e62c1515da4f6c9417545b657a412a8d0df tdreszer Fri Feb 25 12:05:08 2011 -0800 Moved code from 'hgTracks.js' to common 'utils.js' and added support for multi-selects in file and track search diff --git src/hg/js/utils.js src/hg/js/utils.js index 869d6ba..e6a7efe 100644 --- src/hg/js/utils.js +++ src/hg/js/utils.js @@ -1658,15 +1658,481 @@ // return appropriate width for hgTracks image given users current window width return $(window).width() - 20; } function hgTracksSetWidth() { var winWidth = calculateHgTracksWidth(); if($("#imgTbl").length == 0) { // XXXX what's this code for? $("#TrackForm").append(''); //$("#TrackForm").submit(); } else { $("input[name=pix]").val(winWidth); } } + +///////////////////////////////////////////////////// +// findTracks functions + +function updateMetaDataHelpLinks(index) +{ +// update the metadata help links based on currently selected values. +// If index == 0 we update all help items, otherwise we only update the one == index. + var db = getDb(); + var disabled = { // blackList + 'accession': 1, 'dataType': 1, 'dataVersion': 1, 'geoSample': 1, 'grant': 1, + 'lab': 1, 'labExpId': 1, 'labVersion': 1, 'origAssembly': 1, 'replicate': 1, + 'setType': 1, 'softwareVersion': 1, 'subId': 1, 'view': 1 + } + var expected = $('tr.mdbSelect').length; + var ix=1; + if (index!=0) { + ix=index; + expected=index; + } + for(;ix <= expected;ix++) { + var helpLink = $("span#helpLink" + ix); + if (helpLink.length > 0) { + var val = $("select[name='hgt_mdbVar" + ix + "']").val(); // NOTE must match METADATA_NAME_PREFIX in hg/hgTracks/searchTracks.c + var text = $("select[name='hgt_mdbVar" + ix + "'] option:selected").text(); + helpLink.html(" "); // Do not want this with length == 0 later! + if (typeof(disabled[val]) == 'undefined') { + var str; + if (val == 'cell') { + if (db.substr(0, 2) == "mm") { + str = "../ENCODE/cellTypesMouse.html"; + } else { + str = "../ENCODE/cellTypes.html"; + } + } else if (val.toLowerCase() == 'antibody') { + str = "../ENCODE/antibodies.html"; + } else { + str = "../ENCODE/otherTerms.html#" + val; + } + helpLink.html("" + text + ""); + } + } + } +} + +function findTracksMdbVarChanged(obj) +{ // Ajax call to repopulate a metadata vals select when mdb var changes + // This handles the currnet case when 2 vars have the same name (e.g. advanced, files tabs) + + findTracksClearFound(); // Changing values so abandon what has been found + + var newVar = $(obj).val(); + var a = /hgt_mdbVar(\d+)/.exec(obj.name); // NOTE must match METADATA_NAME_PREFIX in hg/hgTracks/searchTracks.c + if(newVar != undefined && a && a[1]) { + var num = a[1]; + if ($('#advancedTab').length == 1 && $('#filesTab').length == 1) { + $("select.mdbVar[name='hgt_mdbVar"+num+"'][value!='"+newVar+"']").val(newVar); + } + $.ajax({ + type: "GET", + url: "../cgi-bin/hgApi", + data: "db=" + getDb() + "&cmd=hgt_mdbVal" + num + "&var=" + newVar, + trueSuccess: findTracksHandleNewMdbVals, + success: catchErrorOrDispatch, + error: errorHandler, + cache: true, + cmd: "hgt_mdbVal" + num, // NOTE must match METADATA_VALUE_PREFIX in hg/hgTracks/searchTracks.c + num: num + }); + } + //findTracksSearchButtonsEnable(true); +} + +function findTracksHandleNewMdbVals(response, status) +{ // Handle ajax response (repopulate a metadata val select) + // This handles the currnet case when 2 vars have the same name (e.g. advanced, files tabs) + + var td = $('td#' + this.cmd ); + if (td != undefined) { + var usesFilterBy = ($("select.mdbVar[name='hgt_mdbVar"+this.num+"']").hasClass('noMulti') == false); + td.empty(); + td.append(response); + var inp = $(td).find('.mdbVal'); + var tdIsLike = $('td#isLike'+this.num); + if (inp != undefined && tdIsLike != undefined) { + if ($(inp).hasClass('freeText')) { + $(tdIsLike).text('contains'); + } else if (usesFilterBy && $(inp).hasClass('filterBy')) { + $(tdIsLike).text('is (any of)'); + } else { + $(tdIsLike).text('is'); + } + } + $(td).find('.filterBy').each( function(i) { // Do this by 'each' to set noneIsAll individually + if (usesFilterBy) { + $(this).dropdownchecklist({ firstItemChecksAll: true, noneIsAll: true }); + } else { + $(this).attr("multiple",false); + $(this).removeClass('filterBy'); + $(this).show(); + } + }); + } + updateMetaDataHelpLinks(this.num); +} + +function findTracksMdbValChanged(obj) +{ // Keep all tabs with same selects in sync TODO: Change from name to id based identification and only have one set of inputs in form + // This handles the currnet case when 2 vars have the same name (e.g. advanced, files tabs) + + findTracksClearFound(); // Changing values so abandon what has been found + + if ($('#advancedTab').length == 1 && $('#filesTab').length == 1) { + var newVal = $(obj).val(); + var a = /hgt_mdbVal(\d+)/.exec(obj.name); // NOTE must match METADATA_NAME_PREFIX in hg/hgTracks/searchTracks.c + if(newVal != undefined && a && a[1]) { + var num = a[1]; + $("input.mdbVal[name='hgt_mdbVal"+num+"'][value!='"+newVal+"']").val(newVal); + $("select.mdbVal[name='hgt_mdbVal"+num+"'][value!='"+newVal+"']").each( function (i) { + $(this).val(newVal); + if ($(this).hasClass('filterBy')) { + //$(this).dropdownchecklist("refresh"); // requires v1.1 + $(this).dropdownchecklist("destroy"); + $(this).dropdownchecklist({ firstItemChecksAll: true, noneIsAll: true }); + } + }); + } + } + //findTracksSearchButtonsEnable(true); +} + +function findTracksChangeVis(seenVis) +{ // called by onchange of vis + var visName = $(seenVis).attr('id'); + var trackName = visName.substring(0,visName.length - "_id".length) + var hiddenVis = $("input[name='"+trackName+"']"); + var tdb = tdbGetJsonRecord(trackName); + if($(seenVis).val() != "hide") + $(hiddenVis).val($(seenVis).val()); + else { + var selCb = $("input#"+trackName+"_sel_id"); + $(selCb).attr('checked',false); // Can't set it to [] because that means default setting is used. However, we are explicitly hiding this! + $(seenVis).attr('disabled',true); // Can't set it to [] because that means default setting is used. However, we are explicitly hiding this! + var needSel = (tdb.parentTrack != undefined); + if (needSel) { + var hiddenSel = $("input[name='"+trackName+"_sel']"); + $(hiddenSel).val('0'); // Can't set it to [] because that means default setting is used. However, we are explicitly hiding this! + $(hiddenSel).attr('disabled',false); + } + if(tdbIsSubtrack(tdb)) + $(hiddenVis).val("[]"); + else + $(hiddenVis).val("hide"); + } + $(hiddenVis).attr('disabled',false); + + $('input.viewBtn').val('View in Browser'); + //warn("Changed "+trackName+" to "+$(hiddenVis).val()) +} + +function findTracksClickedOne(selCb,justClicked) +{ // called by on click of CB and findTracksCheckAll() + var selName = $(selCb).attr('id'); + var trackName = selName.substring(0,selName.length - "_sel_id".length) + var hiddenSel = $("input[name='"+trackName+"_sel']"); + var seenVis = $('select#' + trackName + "_id"); + var hiddenVis = $("input[name='"+trackName+"']"); + var tr = $(selCb).parents('tr.found'); + var tdb = tdbGetJsonRecord(trackName); + var needSel = (tdb.parentTrack != undefined); + var shouldPack = tdb.canPack && tdb.kindOfParent == 0; // If parent then not pack but full + if (shouldPack && tdb.shouldPack != undefined && !tdb.shouldPack) + shouldPack = false; + var checked = $(selCb).attr('checked'); + //warn(trackName +" selName:"+selName +" justClicked:"+justClicked +" hiddenSel:"+$(hiddenSel).attr('name') +" seenVis:"+$(seenVis).attr('id') +" hiddenVis:"+$(hiddenVis).attr('name') +" needSel:"+needSel +" shouldPack:"+shouldPack); + + // First deal with seenVis control + if(checked) { + $(seenVis).attr('disabled', false); + if($(seenVis).attr('selectedIndex') == 0) { + if(shouldPack) + $(seenVis).attr('selectedIndex',3); // packed + else + $(seenVis).attr('selectedIndex',$(seenVis).attr('length') - 1); + } + } else { + $(seenVis).attr('selectedIndex',0); // hide + $(seenVis).attr('disabled', true ); + } + + // Deal with hiddenSel and hiddenVis so that submit does the right thing + // Setting these requires justClicked OR seen vs. hidden to be different + var setHiddenInputs = justClicked; + if(!justClicked) { + if(needSel) + setHiddenInputs = (checked != ($(hiddenSel).val() == '1')); + else if (checked) + setHiddenInputs = ($(seenVis).val() != $(hiddenVis).val()); + else + setHiddenInputs = ($(hiddenVis).val() != "hide" && $(hiddenVis).val() != "[]"); + } + if(setHiddenInputs) { + if(checked) + $(hiddenVis).val($(seenVis).val()); + else if(tdbIsSubtrack(tdb)) + $(hiddenVis).val("[]"); + else + $(hiddenVis).val("hide"); + $(hiddenVis).attr('disabled',false); + + if(needSel) { + if(checked) + $(hiddenSel).val('1'); + else + $(hiddenSel).val('0'); // Can't set it to [] because that means default setting is used. However, we are explicitly hiding this! + $(hiddenSel).attr('disabled',false); + } + } + + // The "view in browser" button should be enabled/disabled + if(justClicked) { + $('input.viewBtn').val('View in Browser'); + findTracksCounts(); + } +} + + +function findTracksNormalize() +{ // Normalize the page based upon current state of all found tracks + $('div#found').show() + var selCbs = $('input.selCb'); + + // All should have their vis enabled/disabled appropriately (false means don't update cart) + $(selCbs).each( function(i) { findTracksClickedOne(this,false); }); + + findTracksCounts(); +} + +function findTracksNormalizeWaitOn() +{ // Put up wait mask then Normalize the page based upon current state of all found tracks + waitOnFunction( findTracksNormalize ); +} + +function findTracksCheckAll(check) +{ // Checks/unchecks all found tracks. + var selCbs = $('input.selCb'); + $(selCbs).attr('checked',check); + + // All should have their vis enabled/disabled appropriately (false means don't update cart) + $(selCbs).each( function(i) { findTracksClickedOne(this,false); }); + + $('input.viewBtn').val('View in Browser'); + findTracksCounts(); + return false; // Pressing button does nothing more +} + +function findTracksCheckAllWithWait(check) +{ + waitOnFunction( findTracksCheckAll, check); +} + +function findTracksSearchButtonsEnable(enable) +{ // Displays visible and checked track count + var searchButton = $('input[name="hgt_tSearch"]'); // NOTE: must match TRACK_SEARCH in hg/inc/searchTracks.h + var clearButton = $('input.clear'); + if(enable) { + $(searchButton).attr('disabled',false); + $(clearButton).attr('disabled',false); + } else { + $(searchButton).attr('disabled',true); + $(clearButton).attr('disabled',true); + } +} + +function findTracksCounts() +{// Displays visible and checked track count + var counter = $('.selCbCount'); + if(counter != undefined) { + var selCbs = $("input.selCb"); + $(counter).text("("+$(selCbs).filter(":enabled:checked").length + " of " +$(selCbs).length+ " selected)"); + } +} + +function findTracksClearFound() +{// Clear found tracks and all input controls + var found = $('div#found'); + if(found != undefined) + $(found).remove(); + found = $('div#filesFound'); + if(found != undefined) + $(found).remove(); + return false; +} + +function findTracksClear() +{// Clear found tracks and all input controls + findTracksClearFound(); + $('input[type="text"]').val(''); // This will always be found + //$('select.mdbVar').attr('selectedIndex',0); // Do we want to set the first two to cell/antibody? + $('select.mdbVal').attr('selectedIndex',0); // Should be 'Any' + $('select.filterBy').each( function(i) { // Do this by 'each' to set noneIsAll individually + //$(this).dropdownchecklist("refresh"); // requires v1.1 + $(this).dropdownchecklist("destroy"); + $(this).dropdownchecklist({ firstItemChecksAll: true, noneIsAll: true }); + }); + + $('select.groupSearch').attr('selectedIndex',0); + $('select.typeSearch').attr('selectedIndex',0); + //findTracksSearchButtonsEnable(false); + return false; +} + +function findTracksSortNow(obj) +{// Called by radio button to sort tracks + if( $('#sortIt').length == 0 ) + $('form#trackSearch').append(""); + else + $('#sortIt').val($(obj).val()); + + // How to hold onto selected tracks? + // There are 2 separate forms. Scrape named inputs from searchResults form and dup them on trackSearch? + var inp = $('form#searchResults').find('input:hidden').not(':disabled').not("[name='hgsid']"); + if($(inp).length > 0) { + $(inp).appendTo('form#trackSearch'); + $('form#trackSearch').attr('method','POST'); // Must be post to avoid url too long NOTE: probably needs to be post anyway + } + + $('#searchSubmit').click(); + return true; +} + +function findTracksPage(pageVar,startAt) +{// Called by radio button to sort tracks + var pager = $("input[name='"+pageVar+"']"); + if( $(pager).length == 1) + $(pager).val(startAt); + + // How to hold onto selected tracks? + // There are 2 separate forms. Scrape named inputs from searchResults form and dup them on trackSearch? + var inp = $('form#searchResults').find('input:hidden').not(':disabled').not("[name='hgsid']"); + if($(inp).length > 0) { + $(inp).appendTo('form#trackSearch'); + $('form#trackSearch').attr('method','POST'); // Must be post to avoid url too long NOTE: probably needs to be post anyway + } + + $('#searchSubmit').click(); + return false; +} + +function findTracksConfigureSet(name) +{// Called when configuring a composite or superTrack + var thisForm = $('form#searchResults'); + $(thisForm).attr('action',"../cgi-bin/hgTrackUi?hgt_tSearch=Search&g="+name); + $(thisForm).find('input.viewBtn').click(); +} + +function findTracksMdbSelectPlusMinus(obj, rowNum) +{ // Now [+][-] mdb var rows with javascript rather than cgi roundtrip + // Will remove row or clone new one. Complication is that 'advanced' and 'files' tab duplicate the tables! + + var objId = $(obj).attr('id'); + rowNum = objId.substring(objId.length - 1); + if ($(obj).val() == '+') { + var buttons = $("input#plusButton"+rowNum); // Two tabs may have the exact same buttons! + if (buttons.length > 0) { + $(buttons).each(function (i) { + var tr = $(this).parents('tr.mdbSelect')[0]; + if (tr != undefined) + $(tr).after( $(tr).clone() ); + findTracksMdbSelectRowsNormalize($(tr).parents('table')[0]); // magic is in this function + }); + return false; + } + } else { // == '-' + var buttons = $("input#minusButton"+rowNum); // Two tabs may have the exact same buttons! + if (buttons.length > 0) { + var remaining = 0; + $(buttons).each(function (i) { + var tr = $(this).parents('tr')[0]; + var table = $(tr).parents('table')[0]; + if (tr != undefined) + $(tr).remove(); + remaining = findTracksMdbSelectRowsNormalize(table); // Must renormalize since 2nd of 3 rows may have been removed + }); + if (remaining > 0) { + removeNum = remaining + 1; // Got to remove the cart vars, though it doesn't matter which as count must not be too many. + setCartVars( [ "hgt_mdbVar"+removeNum, "hgt_mdbVal"+removeNum ], [ "[]","[]" ] ); + } + + findTracksClearFound(); // Changing values so abandon what has been found + return false; + } + } + return true; +} + +function findTracksMdbSelectRowsNormalize(table) +{ // Called when [-][+] buttons changed the number of mdbSelects in findTracks\ + // Will walk through each row and get the numberings of addressable elements correct. + if (table != undefined) { + var mdbSelectRows = $(table).find('tr.mdbSelect'); + var needMinus = (mdbSelectRows.length > 2); + $(table).find('tr.mdbSelect').each( function (ix) { + var rowNum = ix + 1; // Each [-][+] and mdb var=val pair of selects must be numbered + + // First the [-][+] buttons + var plusButton = $(this).find("input[value='+']")[0]; + if (plusButton != undefined) { + $(plusButton).attr('id',"plusButton"+rowNum); + $(plusButton).unbind('click') + $(plusButton).click(function() { return findTracksMdbSelectPlusMinus($(plusButton), rowNum); }); + var minusButton = $(this).find("input[value='-']")[0]; + if (needMinus) { + if (minusButton == undefined) { + $(plusButton).before(""); + minusButton = $(this).find("input[value='-']")[0]; + } else { + $(minusButton).attr('id',"minusButton"+rowNum); + $(minusButton).unbind('click'); + $(minusButton).click(function() { return findTracksMdbSelectPlusMinus($(minusButton), rowNum); }); + } + } else if (minusButton != undefined) + $(minusButton).remove(); + } + // Now the mdb var=val pair of selects + var element = $(this).find("select[name^='hgt_mdbVar']")[0]; + if (element != undefined) + $(element).attr('name','hgt_mdbVar' + rowNum); + + element = $(this).find("select[name^='hgt_mdbVal']")[0]; + if (element != undefined) + $(element).attr('name','hgt_mdbVal' + rowNum); + + // A couple more things + element = $(this).find("td[id^='isLike']")[0]; + if (element != undefined) + $(element).attr('id','isLike' + rowNum); + element = $(this).find("td[id^='hgt_mdbVal']")[0]; + if (element != undefined) + $(element).attr('id','hgt_mdbVal' + rowNum); + }); + return mdbSelectRows.length; + } + return 0; +} + +function findTracksSwitchTabs(ui) +{ // switching tabs on findTracks page + + if( ui.panel.id == 'simpleTab' && $('div#found').length < 1) { + setTimeout("$('input#simpleSearch').focus();",20); // delay necessary, since select event not afterSelect event + } + if( $('div#filesFound').length == 1) { + if( ui.panel.id == 'filesTab') + $('div#filesFound').show(); + else + $('div#filesFound').hide(); + } + if( $('div#found').length == 1) { + if( ui.panel.id != 'filesTab') + $('div#found').show(); + else + $('div#found').hide(); + } +} +