e0c9cb5c5b9536dc3771e3fe09f3afb6ad5ad9ff
tdreszer
Tue Jul 5 18:32:21 2011 -0700
Major performance improvements for IE javascript. parent() and add() both dragged the JSript engine to it's knees. Debug code is being checked in but not called.
diff --git src/hg/js/utils.js src/hg/js/utils.js
index a594c63..0882f5a 100644
--- src/hg/js/utils.js
+++ src/hg/js/utils.js
@@ -538,30 +538,43 @@
if( warnList == undefined || $(warnList).length == 0 ) {
warnBoxJsSetup();
warnList = $('#warnList');
}
if( $(warnList).length == 0 )
alert(msg);
else {
$( warnList ).append('
'+msg+'');
if(showWarnBox != undefined)
showWarnBox();
else
alert(msg);
}
}
+var gWarnSinceMSecs = 0;
+function warnSince(msg)
+{ // Warn messages with msecs since last warnSince msg
+ // This is necessary because IE Developer tools are hanging
+ var now = new Date();
+ var msecs = now.getTime();
+ var since = 0;
+ if (gWarnSinceMSecs > 0)
+ since = msecs - gWarnSinceMSecs;
+ gWarnSinceMSecs = msecs;
+ warn('['+since+'] '+msg);
+}
+
function cgiBooleanShadowPrefix()
// Prefix for shadow variable set with boolean variables.
// Exact copy of code in cheapcgi.c
{
return "boolshad.";
}
function getAllVars(obj,subtrackName)
{
// Returns a hash for all inputs and selects in an obj.
// If obj is undefined then obj is document!
var urlData = new Object();
if($(obj) == undefined)
obj = $('document');
var inp = $(obj).find('input');
@@ -915,39 +928,40 @@
{ // Clears the waitMask
var waitMask = $('#waitMask');
if( waitMask != undefined )
$(waitMask).hide();
}
function waitMaskSetup(timeOutInMs)
{ // Sets up the waitMask to block page manipulation until cleared
// Find or create the waitMask (which masks the whole page)
var waitMask = $('#waitMask');
if( waitMask == undefined || waitMask.length != 1) {
// create the waitMask
$("body").append("");
waitMask = $('#waitMask');
- // Special for IE
+ // Special for IE, since it takes so long, make mask obvious
if ($.browser.msie)
- $(waitMask).css('filter','alpha(opacity= 0)');
+ $(waitMask).css({opacity:0.4,backgroundColor:'gray'});
}
$(waitMask).css('display','block');
// Things could fail, so always have a timeout.
if(timeOutInMs == undefined || timeOutInMs <=0)
- timeOutInMs = 5000; // Don't ever leave this as infinite
+ timeOutInMs = 30000; // IE can take forever!
+
setTimeout('waitMaskClear();',timeOutInMs); // Just in case
}
function _launchWaitOnFunction()
{ // should ONLY be called by waitOnFunction()
// Launches the saved function
var func = gWaitFunc;
gWaitFunc = null;
var funcArgs = gWaitFuncArgs;
gWaitFuncArgs = [];
if(func == undefined || !jQuery.isFunction(func))
warn("_launchWaitOnFunction called without a function");
else {
if(funcArgs.length == 0)
@@ -993,30 +1007,61 @@
if(arguments[1].type == 'button' && $(arguments[1]).hasClass('inOutButton')) {
$(arguments[1]).css( 'borderStyle',"inset");
}
}
// Build up the aruments array
for(var aIx=1;aIx 0)
+ ro.step(msecs,args); // recursion
+ else if (msecs == 0)
+ continuingFunc(args); // completion
+ // else (msec < 0) // abandon
+ });
+ ro.step(1,args); // kick-off
+}
+
function showLoadingImage(id)
{
// Show a loading image above the given id; return's id of div added (so it can be removed when loading is finished).
// This code was mostly directly copied from hgHeatmap.js, except I also added the "overlay.appendTo("body");"
var loadingId = id + "LoadingOverlay";
var overlay = $("").attr("id", loadingId).css("position", "absolute");
overlay.appendTo("body");
overlay.css("top", $('#'+ id).position().top);
var divLeft = $('#'+ id).position().left + 2;
overlay.css("left",divLeft);
var width = $('#'+ id).width() - 5;
var height = $('#'+ id).height();
overlay.width(width);
overlay.height(height);
overlay.css("background", "white");
@@ -2240,120 +2285,285 @@
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");
if (classes.length > 1 ) {
warn('Too many classes for filterBy: ' + classes);
return undefined;
}
return classes.pop();
}
-function filterTablesTrsSurviving(filterClass)
-// returns a list of trs that satisfy all filters
-// If defined, will exclude filter identified by filterClass
-{
- // find all filterable table rows
- var showTrs = $('tr.filterable'); // Default all
- if (showTrs.length == 0)
- return undefined;
+function _filterTableByClassesIterative(args)
+{ // Applies a single class filter to a filterTable TRs
+ // Called via yieldingIterator
+ if (args.curIx >= args.classes.length)
+ return 0;
- // Find all filters
- var filters = $("select.filterBy");
- if (filters.length == 0)
- return undefined;
+ var tds = $(args.tdsRemaining).filter('.' + args.classes[args.curIx]);
+ if (tds.length > 0) {
+ if (args.tdsFiltered == null)
+ args.tdsFiltered = tds;
+ else
+ args.tdsFiltered = jQuery.merge( args.tdsFiltered, tds ); // This one takes too long in IE!
+ }
+ //warnSince("Iterating class:"+args.curIx);
+ args.curIx++;
+ if (args.curIx >= args.classes.length)
+ return 0;
+ return 1;
+}
- // Exclude one if requested.
- if (filterClass != undefined && filterClass.length > 0)
- filters = $(filters).not('.' + filterClass);
+function _filterTableByClassesComplete(args)
+{ // Continues after filterTableByClassesIterative
+ // Called via yieldingIterator
+ var filtersStruct = args.filtersStruct;
- // For each filter, filter the list of trs that matches that filter
- $(filters).each(function (i) {
- var val = $(this).val();
- if (val == null || val.length == 0)
- return;
- val = val.join();
- if(val.indexOf("All") == 0)
- return;
+ //warnSince("Completing classes...");
+ if (args.tdsFiltered == null)
+ filtersStruct.trsRemaining = null;
+ else {
+ //filtersStruct.trsRemaining = $(args.tdsFiltered).parent(); // Very slow in IE!!!
+ var tds = args.tdsFiltered;
+ var trs = [];
+ $(tds).each(function (ix) {
+ trs[ix] = this.parentNode;
+ });
+ filtersStruct.trsRemaining = trs;
+ }
+ //warnSince("Mostly complete classes...");
+ filtersStruct.curIx++;
+ yieldingIterator(_filterTableIterative,_filterTableComplete,filtersStruct);
+ //warnSince("Really complete classes.");
+}
- // Get the filter variable
- var filterVar = filterTableFilterVar(this);
- if (filterVar == undefined)
- return;
+function _filterTableIterative(args)
+{ // Applies a single filter to a filterTable TRs
+ // Called via yieldingIterator
- // Get the selected values for this filter
- var classes = $(this).val();
- if (classes.length == 0)
- return;
+ //warnSince("Filter "+args.curIx+" iterating...");
+ if (args.curIx >= args.filters.length)
+ return 0;
- var varTds = $(showTrs).children('td.' + filterVar);
- var filteredTrs = new Array;
- var ix =0;
- for(;ix 0) {
- if (filteredTrs.length == 0)
- filteredTrs = $(tds).parent('tr').get();
+ var trs = [];
+ $(tds).each(function (ix) {
+ trs[ix] = this.parentNode;
+ });
+ if (filteredTrs == null)
+ filteredTrs = trs; // $(tds).parent('tr'); // parent() takes too long in IE
else
- filteredTrs = filteredTrs.concat( $(tds).parent('tr').get() );
+ filteredTrs = jQuery.merge( filteredTrs, trs );// $(tds).parent() ); // takes too long in IE!
+ }
}
+ args.trsRemaining = filteredTrs;
+ //}
+ }
+ }
+ args.curIx++;
+ if (args.curIx >= args.filters.length)
+ return 0;
+ return 1;
}
- // The following tighter code may take too long
- //var filterVals = 'td.'+filterVar+'.' + classes.join(',td.'+filterVar+'.'); // "td.cell.GM12878,td.cell.K562,td.cell.H1-hESC"
- //var filteredTrs = $(showTrs).filter(":has(" + filterVals + ")");
- if (filteredTrs.length > 0)
- showTrs = filteredTrs;
- });
- return showTrs;
+function _filterTableComplete(args)
+{ // Continuation after all the filters have been applied
+ // Called via yieldingIterator
+
+ //warnSince("Completing...");
+ //$('tr.filterable').hide(); // <========= This is what is taking so long!
+ $('tr.filterable').css('display', 'none');
+
+ if (args.trsRemaining != null) {
+ //$(args.trsRemaining).show();
+ $(args.trsRemaining).css('display', '');
+
+ // Update count
+ var counter = $('.filesCount');
+ if(counter != undefined)
+ $(counter).text($(args.trsRemaining).length + " / ");
+ } else {
+ var counter = $('.filesCount');
+ if(counter != undefined)
+ $(counter).text(0 + " / ");
}
-function _filterTable()
+ var tbody = $( $('tr.filterable')[0] ).parent('tbody.sorting');
+ if (tbody != undefined)
+ $(tbody).removeClass('sorting');
+ //warnSince("Really complete.");
+}
+
+function _filterTableOld()
{ // Called by filter onchange event. Will show/hide trs based upon all filters
var showTrs = filterTablesTrsSurviving();
- if (showTrs == undefined)
- return;
//$('tr.filterable').hide(); // <========= This is what is taking so long!
$('tr.filterable').css('display', 'none')
- $(showTrs).show();
+ if (showTrs != undefined && showTrs.length > 0) {
+ //$(showTrs).show();
+ $(showTrs).css('display', '');
// Update count
var counter = $('.filesCount');
if(counter != undefined)
$(counter).text($(showTrs).length + " / ");
+ } else {
+ var counter = $('.filesCount');
+ if(counter != undefined)
+ $(counter).text(0 + " / ");
+ }
var tbody = $( $('tr.filterable')[0] ).parent('tbody.sorting');
if (tbody != undefined)
$(tbody).removeClass('sorting');
}
+function _filterTable()
+{ // Called by filter onchange event. Will show/hide trs based upon all filters
+ var trsAll = $('tr.filterable'); // Default all
+ if (trsAll.length == 0)
+ return undefined;
+
+ // Find all filters
+ var filters = $("select.filterBy");
+ if (filters.length == 0)
+ return undefined;
+
+ var filtersStruct = new Object;
+ filtersStruct.filters = filters;
+ filtersStruct.curIx = 0;
+ filtersStruct.trsRemaining = trsAll;
+
+ yieldingIterator(_filterTableIterative,_filterTableComplete,filtersStruct);
+}
+
+
+function filterTablesApplyOneFilter(filter,remainingTrs)
+{ // Applies a single filter to a filterTables TRs
+ var classes = $(filter).val();
+ if (classes == null || classes.length == 0)
+ return null; // Nothing selected so exclude all rows
+
+ if(classes[0] == 'All')
+ return remainingTrs; // nothing excluded by this filter
+
+ // Get the filter variable
+ var filterVar = filterTableFilterVar(filter);
+ if (filterVar == undefined)
+ return null;
+
+ var varTds = $(remainingTrs).children('td.' + filterVar);
+ var filteredTrs = null;
+ var ix =0;
+ for(;ix 0) {
+ var trs = [];
+ $(tds).each(function (ix) {
+ trs[ix] = this.parentNode;
+ });
+
+ if (filteredTrs == null)
+ filteredTrs = trs;
+ else
+ filteredTrs = jQuery.merge( filteredTrs, trs ); // This one takes too long in IE!
+ }
+ }
+ return filteredTrs;
+}
+
+function filterTablesTrsSurviving(filterClass)
+// returns a list of trs that satisfy all filters
+// If defined, will exclude filter identified by filterClass
+{
+ // find all filterable table rows
+ var showTrs = $('tr.filterable'); // Default all
+ if (showTrs.length == 0)
+ return undefined;
+
+ // Find all filters
+ var filters = $("select.filterBy");
+ if (filters.length == 0)
+ return undefined;
+
+ // Exclude one if requested.
+ if (filterClass != undefined && filterClass.length > 0)
+ filters = $(filters).not('.' + filterClass);
+
+ for(var ix =0;showTrs != null && ix < filters.length;ix++) {
+ showTrs = filterTablesApplyOneFilter(filters[ix],showTrs)
+ }
+ return showTrs;
+}
+
function filterTableTrigger()
{ // Called by filter onchange event. Will show/hide trs based upon all filters
var tbody = $( $('tr.filterable')[0] ).parent('tbody');
if (tbody != undefined)
$(tbody).addClass('sorting');
- setTimeout('_filterTable();',10); // Just in case
+ setTimeout('_filterTableOld();',2); // Just in case
+}
+
+function filterTableDone(event)
+{ // Called by custom 'done' event
+ event.stopImmediatePropagation();
+ $(this).unbind( event );
+ waitOnFunction(filterTableTrigger);
}
-function filterTable()
+function filterTable(selector)
{ // Called by filter onchange event. Will show/hide trs based upon all filters
+ // IE takes tooo long, so this should be called only when leaving the filterBy box
+ if ( $('tr.filterable').length > 300) {
+ //if ($.browser.msie) { // IE takes tooo long, so this should be called only when leaving the filterBy box
+ $(selector).one('done',filterTableDone);
+ return;
+ //}
+ } else
waitOnFunction(filterTableTrigger );
}
function filterTableExcludeOptions(filter)
{ // bound to 'click' event inside ui.dorpdownchecklist.js.
// Will mark all options in one filterBy box that are inconsistent with the current
// selections in other filterBy boxes. Mark with class ".excluded"
// Find the var for this filter
var filterVar = filterTableFilterVar(filter);
if (filterVar == undefined)
return false;
// Look at list of visible trs.
var visibleTrs = filterTablesTrsSurviving(filterVar);
@@ -2526,30 +2736,33 @@
});
}
var msg = ddclTextOfCurrentSelections(selector.options);
var control = this.controlWrapper;
if (control == null || control == undefined) { // caller is not constant
control = $('#ddcl-' + id);
}
var newColor = '';
if ($(selector).find('option:selected').length == 0)
newColor = '#AA0000'; // red
//else if (msg.search(/color:/i) == -1)
// newColor = 'black';
ddclLabelSet(control,msg,newColor,'Click to select...');
+
+ // Notice special handling for a custom event
+ $(selector).trigger('done',selector);
}
function ddclReinit(filterBys,force)
{ // ReInitialize the DDCLs (drop-down checkbox-list)
// This is done when the track search with tabs gets switched to advanced tab
// because the DDCLs were setup on hidden filterBys and dimensiuons are wrong.
// if not force, then only reinit when the dimensions are suspect
if (filterBys.length < 1)
return;
$(filterBys).each( function(i) { // Do this by 'each' to set noneIsAll individually
if (!force) { // condition on bad dimensions
var id = $(this).attr('id');
control = $('#ddcl-' + id);