e8e125d39087195e7dad2f615255294838b7cdbd tdreszer Fri Oct 21 12:42:28 2011 -0700 Objectified the js for findTracks. Also fixed redmine 5692 diff --git src/hg/js/utils.js src/hg/js/utils.js index 1cbb476..aa521ad 100644 --- src/hg/js/utils.js +++ src/hg/js/utils.js @@ -1743,34 +1743,61 @@ return $(window).width() - 20; } function hgTracksSetWidth() { var winWidth = calculateHgTracksWidth(); if($("#imgTbl").length == 0) { // XXXX what's this code for? $("#TrackForm").append('<input type="hidden" name="pix" value="' + winWidth + '"/>'); //$("#TrackForm").submit(); } else { $("input[name=pix]").val(winWidth); } } -///////////////////////////////////////////////////// -// findTracks functions +function filterByMaxHeight(multiSel) +{ // Setting a max height to scroll dropdownchecklists but + // multiSel is hidden when this is done, so it's position and height must be estimated. + var pos = $(multiSel).closest(':visible').offset().top + 30; + if (pos <= 0) + pos = 260; + + // Special mess since the filterBy's on non-current tabs will calculate pos badly. + var tabbed = $('input#currentTab'); + if (tabbed != undefined) { + var tabDiv = $(multiSel).parents('div#'+ $(tabbed).attr('value')); + if (tabDiv == null || tabDiv == undefined || $(tabDiv).length == 0) { + pos = 360; + } + } + var maxHeight = $(window).height() - pos; + var selHeight = $(multiSel).children().length * 21; + if (maxHeight > selHeight) + maxHeight = null; + //else if($.browser.msie && maxHeight > 500) // DDCL bug on IE only. + // maxHeight = 500; // Seems to be solved by disbling DDCL's window.resize event for IE + + return maxHeight; +} -function updateMetaDataHelpLinks(index) + ////////////////////////////// +//// findTracks functions //// +///////////////////////////// +var findTracks = { + + updateMdbHelp: function (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; } @@ -1785,164 +1812,158 @@ 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("<a target='_blank' title='detailed descriptions of terms' href='" + str + "'>" + text + "</a>"); } } } -} + }, -function findTracksMdbVarChanged(obj) + mdbVarChanged: function (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 + findTracks.clearFound(); // 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); } var cgiVars = "db=" + getDb() + "&cmd=hgt_mdbVal" + num + "&var=" + newVar; if (document.URL.search('hgFileSearch') != -1) cgiVars += "&fileSearch=1"; else cgiVars += "&fileSearch=0"; $.ajax({ type: "GET", url: "../cgi-bin/hgApi", data: cgiVars, dataType: 'html', - trueSuccess: findTracksHandleNewMdbVals, + trueSuccess: findTracks.handleNewMdbVals, success: catchErrorOrDispatch, error: errorHandler, cache: true, cmd: "hgt_mdbVal" + num, // NOTE must match METADATA_VALUE_PREFIX in hg/hgTracks/searchTracks.c num: num }); } // NOTE: with newJquery, the response is getting a new error (missing ; before statement) // There were also several XML parsing errors. // This error is fixed with the addition of "dataType: 'html'," above. -} + }, -function findTracksHandleNewMdbVals(response, status) + handleNewMdbVals: function (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 ($(inp).hasClass('wildList') || (usesFilterBy && $(inp).hasClass('filterBy'))) { $(tdIsLike).text('is among'); } else { $(tdIsLike).text('is'); } } $(td).find('.filterBy').each( function(i) { // Do this by 'each' to set noneIsAll individually if (usesFilterBy) { - if (newJQuery) ddcl.setup(this,'noneIsAll'); - else - $(this).dropdownchecklist({ firstItemChecksAll: true, noneIsAll: true, maxDropHeight: filterByMaxHeight(this) }); } else { $(this).attr("multiple",false); $(this).removeClass('filterBy'); $(this).show(); } }); } - updateMetaDataHelpLinks(this.num); -} + findTracks.updateMdbHelp(this.num); + }, -function findTracksMdbValChanged(obj) + mdbValChanged: function (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 + findTracks.clearFound(); // 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("destroy"); - if (newJQuery) ddcl.setup(this,'noneIsAll'); - else - $(this).dropdownchecklist({ firstItemChecksAll: true, noneIsAll: true, maxDropHeight: filterByMaxHeight(this) }); } }); } } - //findTracksSearchButtonsEnable(true); -} + //findTracks.searchButtonsEnable(true); + }, -function findTracksChangeVis(seenVis) + changeVis: function (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() + clickedOne: function (selCb,justClicked) + { // called by on click of CB and findTracks.checkAll() 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 @@ -1979,326 +2000,295 @@ $(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(); - } + findTracks.counts(); } + }, -function findTracksNormalize() + normalize: function () { // 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); }); + $(selCbs).each( function(i) { findTracks.clickedOne(this,false); }); - findTracksCounts(); -} + findTracks.counts(); + }, -function findTracksNormalizeWaitOn() + normalizeWaitOn: function () // UNUSED ? { // Put up wait mask then Normalize the page based upon current state of all found tracks - waitOnFunction( findTracksNormalize ); -} + waitOnFunction( findTracks.normalize ); + }, -function findTracksCheckAll(check) + checkAll: function (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); }); + $(selCbs).each( function(i) { findTracks.clickedOne(this,false); }); $('input.viewBtn').val('View in Browser'); - findTracksCounts(); + findTracks.counts(); return false; // Pressing button does nothing more -} + }, -function findTracksCheckAllWithWait(check) + checkAll: function (check) { - waitOnFunction( findTracksCheckAll, check); -} + waitOnFunction( findTracks.checkAll, check); + }, -function findTracksSearchButtonsEnable(enable) + searchButtonsEnable: function (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() + counts: function () {// 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() + clearFound: function () {// 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 filterByMaxHeight(multiSel) -{ // Setting a max hieght to scroll dropdownchecklists but - // multiSel is hidden when this is done, so it's position and height must be estimated. - var pos = $(multiSel).closest(':visible').offset().top + 30; - if (pos <= 0) - pos = 260; - - // Special mess since the filterBy's on non-current tabs will calculate pos badly. - var tabbed = $('input#currentTab'); - if (tabbed != undefined) { - var tabDiv = $(multiSel).parents('div#'+ $(tabbed).attr('value')); - if (tabDiv == null || tabDiv == undefined || $(tabDiv).length == 0) { - pos = 360; - } - } - var maxHeight = $(window).height() - pos; - var selHeight = $(multiSel).children().length * 21; - if (maxHeight > selHeight) - maxHeight = null; - //else if($.browser.msie && maxHeight > 500) // DDCL bug on IE only. - // maxHeight = 500; // Seems to be solved by disbling DDCL's window.resize event for IE - - return maxHeight; -} + }, -function findTracksClear() + clear: function () {// Clear found tracks and all input controls - findTracksClearFound(); + findTracks.clearFound(); $('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).show(); - if (newJQuery) ddcl.setup(this,'noneIsAll'); - else - $(this).dropdownchecklist({ firstItemChecksAll: true, noneIsAll: true, maxDropHeight: filterByMaxHeight(this) }); }); $('select.groupSearch').attr('selectedIndex',0); $('select.typeSearch').attr('selectedIndex',0); - //findTracksSearchButtonsEnable(false); + //findTracks.searchButtonsEnable(false); return false; -} + }, -function findTracksSortNow(obj) + sortNow: function (obj) {// Called by radio button to sort tracks if( $('#sortIt').length == 0 ) $('form#trackSearch').append("<input TYPE=HIDDEN id='sortIt' name='"+$(obj).attr('name')+"' value='"+$(obj).val()+"'>"); 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) + page: function (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) + configSet: function (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) + mdbSelectPlusMinus: function (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) { var table = null; $(buttons).each(function (i) { var tr = $(this).parents('tr.mdbSelect')[0]; if (tr != undefined) { table = $(tr).parents('table')[0]; - if(newJQuery) { var newTr = $(tr).clone(); - var element = $(newTr).find("select.mdbVar")[0]; - if (element != undefined) - $(element).attr('selectedIndex',-1); - - element = $(newTr).find("td[id^='hgt_mdbVal']")[0]; + var element = $(newTr).find("td[id^='hgt_mdbVal']")[0]; if (element != undefined) $(element).empty(); element = $(newTr).find("td[id^='isLike']")[0]; if (element != undefined) $(element).empty(); $(tr).after( newTr ); - } else - $(tr).after( $(tr).clone() ); + element = $(newTr).find("select.mdbVar")[0]; + if (element != undefined) + $(element).attr('selectedIndex',-1); // chrome needs this after 'after' } }); if (table) - findTracksMdbSelectRowsNormalize(table); // magic is in this function + findTracks.mdbSelectRowsNormalize(table); // 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 + remaining = findTracks.mdbSelectRowsNormalize(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 + findTracks.clearFound(); // Changing values so abandon what has been found return false; } } return true; -} + }, -function findTracksMdbSelectRowsNormalize(table) + mdbSelectRowsNormalize: function (table) { // Called when [-][+] buttons changed the number of mdbSelects in findTracks\ // Will walk through each row and get the numberings of addressable elements correct. //var table = $('table#'+tableId); 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); // rebinding click appears to be not needed and screws up IE as well. //$(plusButton).unbind('click') - //$(plusButton).click(function() { return findTracksMdbSelectPlusMinus($(plusButton), rowNum); }); + //$(plusButton).click(function() { return findTracks.mdbSelectPlusMinus($(plusButton), rowNum); }); var minusButton = $(this).find("input[value='-']")[0]; if (needMinus) { if (minusButton == undefined) { - $(plusButton).before("<input type='button' id='minusButton"+rowNum+"' value='-' style='font-size:.7em;' title='delete this row' onclick='return findTracksMdbSelectPlusMinus(this,"+rowNum+");'>"); + $(plusButton).before("<input type='button' id='minusButton"+rowNum+"' value='-' style='font-size:.7em;' title='delete this row' onclick='return findTracks.mdbSelectPlusMinus(this,"+rowNum+");'>"); minusButton = $(this).find("input[value='-']")[0]; } else { $(minusButton).attr('id',"minusButton"+rowNum); $(minusButton).unbind('click'); - $(minusButton).click(function() { return findTracksMdbSelectPlusMinus($(minusButton), rowNum); }); + $(minusButton).click(function() { return findTracks.mdbSelectPlusMinus($(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) + switchTabs: function (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 } else if( ui.panel.id == 'advancedTab') { // Advanced tab has DDCL wigets which were sized badly because the hidden width was unknown // delay necessary, since select event not afterSelect event setTimeout("ddcl.reinit($('div#advancedTab').find('select.filterBy'),false);",20); } 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(); } } +} ///////////////////////////////////////////////////// // filterTable functions function filterTableFilterVar(filter) { // returns the var associated with a fileFilter if($(filter).hasClass('filterBy') == false) return undefined; if($(filter).hasClass('filterTable') == false) return undefined; // Find the var for this filter var classes = $(filter).attr("class").split(' '); classes = aryRemove(classes,"filterBy","filterTable","noneIsAll");