49bbb7e972e5b5cde64576177920bc3e3c0dedf1 tdreszer Tue Jun 3 13:06:53 2014 -0700 Changes at Angie's suggestion during pre-code-review. Redmine #13255. diff --git src/hg/js/utils.js src/hg/js/utils.js index e6ac827..748f690 100644 --- src/hg/js/utils.js +++ src/hg/js/utils.js @@ -86,30 +86,31 @@ } } } else { // NS 4.x - I gave up trying to get this to work. if (debugLevel>2) alert("arrayOfInputsThatMatch is unimplemented for this browser"); } return found; } function normed(thing) { // RETURNS undefined, the lone member of the set or the full set if more than one member. // Used for normalizing returns from jquery DOM selects (e.g. $('tr.track').children('td.data')) // jquery returns an "array like 'object'" with 0 or more entries. + // May be used on non-jquery objects and will reduce single element arrays to the element. // Use this to treat 0 entries the same as undefined and 1 entry as the item itself if (thing === undefined || thing === null || (thing.length !== undefined && thing.length === 0) // Empty array (or 'array like object') || ($.isPlainObject(thing) && $.isEmptyObject(thing))) // Empty simple object return undefined; if (thing.length && thing.length === 1 && jQuery.type(thing) !== 'string') // string is overkill return thing[0]; // Container of one item should return the item itself. return thing; } function waitCursor(obj) // DEAD CODE? { //document.body.style.cursor="wait" obj.style.cursor="wait"; } @@ -189,45 +190,45 @@ aValue = extra.substring(extraIx+1,endIx); extra = extra.substring(endIx+1); } else { aValue = extra.substring(extraIx+1); extra = ""; } if (aName.length > 0 && aValue.length > 0) updateOrMakeNamedVariable(theForm,aName,aValue); } } return url; } function postTheForm(formName,href) { // posts the form with a passed in href - var goodForm=$("form[name='"+formName+"']"); - if (goodForm.length === 1) { + var goodForm = normed($("form[name='"+formName+"']")); + if (goodForm) { if (href && href.length > 0) { $(goodForm).attr('action',href); // just attach the straight href } $(goodForm).attr('method','POST'); $(goodForm).submit(); } return false; // Meaning do not continue with anything else } function setVarAndPostForm(aName,aValue,formName) { // Sets a specific variable then posts - var goodForm=$("form[name='"+formName+"']"); - if (goodForm.length === 1) { + var goodForm = normed($("form[name='"+formName+"']")); + if (goodForm) { updateOrMakeNamedVariable(goodForm,aName,aValue); } return postTheForm(formName,window.location.href); } // json help routines function tdbGetJsonRecord(trackName) { return hgTracks.trackDb[trackName]; } // NOTE: These must jive with tdbKindOfParent() and tdbKindOfChild() in trackDb.h function tdbIsFolder(tdb) { return (tdb.kindOfParent === 1); } function tdbIsComposite(tdb) { return (tdb.kindOfParent === 2); } function tdbIsMultiTrack(tdb) { return (tdb.kindOfParent === 3); } function tdbIsView(tdb) { return (tdb.kindOfParent === 4); } // Don't expect to use function tdbIsContainer(tdb) { return (tdb.kindOfParent === 2 || tdb.kindOfParent === 3); } function tdbIsLeaf(tdb) { return (tdb.kindOfParent === 0); } function tdbIsFolderContent(tdb) { return (tdb.kindOfChild === 1); } @@ -290,31 +291,31 @@ } function isFloat(s) { return (!isNaN(parseFloat(s)) && isFinite(s)); } function validateInt(obj,min,max) { // validates an integer which may be restricted to a range (if min and/or max are numbers) var title = obj.title; var rangeMin=parseInt(min); var rangeMax=parseInt(max); if (title.length === 0) title = "Value"; var popup=( $.browser.msie === false ); for (;;) { - if ((obj.value === undefined || obj.value === null || obj.value === "") + if ((!obj.value || obj.value === "") && isInteger(obj.defaultValue)) obj.value = obj.defaultValue; if (!isInteger(obj.value)) { if (popup) { obj.value = prompt(title +" is invalid.\nMust be an integer.",obj.value); continue; } else { alert(title +" of '"+obj.value +"' is invalid.\nMust be an integer."); obj.value = obj.defaultValue; return false; } } var val = parseInt(obj.value); if (isInteger(min) && isInteger(max)) { if (val < rangeMin || val > rangeMax) { @@ -357,31 +358,31 @@ } } return true; } } function validateFloat(obj,min,max) { // validates an float which may be restricted to a range (if min and/or max are numbers) var title = obj.title; var rangeMin=parseFloat(min); var rangeMax=parseFloat(max); if (title.length === 0) title = "Value"; var popup=( $.browser.msie === false ); for (;;) { - if ((obj.value === undefined || obj.value === null || obj.value === "") + if ((!obj.value || obj.value === "") && isFloat(obj.defaultValue)) obj.value = obj.defaultValue; if (!isFloat(obj.value)) { if (popup) { obj.value = prompt(title +" is invalid.\nMust be a number.",obj.value); continue; } else { alert(title +" of '"+obj.value +"' is invalid.\nMust be a number."); // try a prompt box! obj.value = obj.defaultValue; return false; } } var val = parseFloat(obj.value); if (isFloat(min) && isFloat(max)) { if (val < rangeMin || val > rangeMax) { @@ -848,73 +849,73 @@ } function getHgsid() {// return current session id // .first() because hgTracks turned up 3 of these! var hgsid = normed($("input[name='hgsid']").first()); if (hgsid) return hgsid.value; hgsid = getURLParam(window.location.href, "hgsid"); if (hgsid.length > 0) return hgsid; // This may be moved to 1st position as the most likely source - if (typeof(common) !== "undefined" && common.hgsid !== undefined && common.hgsid !== null) + if (common && common.hgsid !== undefined && common.hgsid !== null) return common.hgsid; hgsid = normed($("input#hgsid").first()); if (hgsid) return hgsid.value; return ""; } function getDb() { var db = normed($("input[name='db']").first()); if (db) return db.value; db = getURLParam(window.location.href, "db"); if (db.length > 0) return db; // This may be moved to 1st position as the most likely source - if (typeof(common) !== "undefined" && common.db !== undefined && common.db !== null) + if (common && common.db) return common.db; db = normed($("input#db").first()); if (db) return db.value; return ""; } function getTrack() { var track = normed($("input[name='g']").first()); if (track) return track.value; track = getURLParam(window.location.href, "g"); if (track.length > 0) return track; // This may be moved to 1st position as the most likely source - if (typeof(common) !== "undefined" && common.track !== undefined && common.track !== null) + if (common && common.track) return common.track; track = normed($("input#g").first()); if (track) return track.value; return ""; } function Rectangle() // DEAD CODE? { // Rectangle object constructor: // calling syntax: // // new Rectangle(startX, endX, startY, endY) @@ -1048,80 +1049,61 @@ setTimeout(waitMaskClear,timeOutInMs); // Just in case return waitMask; // The caller could add css if they wanted. } function _launchWaitOnFunction() { // should ONLY be called by waitOnFunction() // Launches the saved function var func = gWaitFunc; gWaitFunc = null; var funcArgs = gWaitFuncArgs; gWaitFuncArgs = []; if (!func || !jQuery.isFunction(func)) warn("_launchWaitOnFunction called without a function"); - else { - if (funcArgs.length === 0) - func(); - else if (funcArgs.length === 1) - func(funcArgs[0]); - else if (funcArgs.length === 2) - func(funcArgs[0],funcArgs[1]); - else if (funcArgs.length === 3) - func(funcArgs[0],funcArgs[1],funcArgs[2]); - else if (funcArgs.length === 4) - func(funcArgs[0],funcArgs[1],funcArgs[2],funcArgs[3]); - else if (funcArgs.length === 5) - func(funcArgs[0],funcArgs[1],funcArgs[2],funcArgs[3],funcArgs[4]); else - warn("_launchWaitOnFunction called with " + funcArgs.length + - " arguments. Only 5 are supported."); - } + func.apply(this, funcArgs); + // Special if the first var is a button that can visually be inset if (funcArgs.length > 0 && funcArgs[0].type) { if (funcArgs[0].type === 'button' && $(funcArgs[0]).hasClass('inOutButton')) { $(funcArgs[0]).css('borderStyle',"outset"); } } // Now we can get rid of the wait cursor waitMaskClear(); } function waitOnFunction(func) { // sets the waitMask (wait cursor and no clicking), // then launches the function with up to 5 arguments if (!jQuery.isFunction(func)) { warn("waitOnFunction called without a function"); return false; } if (gWaitFunc) { if (gWaitFunc === func) // already called (sometimes hapens when onchange event is triggered return true; // by js (rather than direct user action). Happens in IE8 warn("waitOnFunction called but already waiting on a function"); return false; } - if (arguments.length > 6) { - warn("waitOnFunction called with " + arguments.length - 1 + - " arguments. Only 5 are supported."); - return false; - } waitMaskSetup(0); // Find or create waitMask (which masks whole page) but gives up after 5sec // Special if the first var is a button that can visually be inset - if (arguments.length > 1 && arguments[1].type !== undefined && arguments[1].type !== null) { + if (arguments.length > 1 && arguments[1].type) { if (arguments[1].type === 'button' && $(arguments[1]).hasClass('inOutButton')) { $(arguments[1]).css( 'borderStyle',"inset"); } } // Build up the aruments array for (var aIx=1; aIx < arguments.length; aIx++) { gWaitFuncArgs.push(arguments[aIx]); } gWaitFunc = func; setTimeout(_launchWaitOnFunction,10); } @@ -1819,52 +1801,52 @@ this.reverse = []; var fields = sortOrder.split(" "); // sortOrder looks like: "cell=+ factor=+ view=+" while (fields.length > 0) { var pair = fields.shift().split("="); // Take first and split into if (pair.length === 2) { this.tags.push(pair[0]); this.reverse.push(pair[1] !== '+'); } } }, columnsFromTr: function (tr,silent) { // Creates a sortColumns struct from entries in the 'tr.sortable' heading row of the table this.inheritFrom = sortTable.columnsFromSortOrder; var sortOrder = sortTable.orderFromTr(tr); - if (sortOrder.length === 0 && (silent === undefined || silent === null)) { + if (sortOrder.length === 0 && !silent) { // developer needs to know something is wrong warn("Unable to obtain sortOrder from sortable table."); return; } this.inheritFrom(sortOrder); // Add two additional arrays this.cellIxs = []; this.useAbbr = []; var ths = $(tr).find('th.sortable'); for (var tIx=0; tIx < this.tags.length; tIx++) { for (ix=0; ix < ths.length; ix++) { if ((ths[ix].id && ths[ix].id === this.tags[tIx]) || (ths[ix].cellIndex === parseInt(this.tags[tIx]))) { this.cellIxs[tIx] = ths[ix].cellIndex; this.useAbbr[tIx] = (ths[ix].abbr.length > 0); } } } - if (this.cellIxs.length === 0 && (silent === undefined || silent === null)) { + if (this.cellIxs.length === 0 && !silent) { warn("Unable to find any sortOrder.cells for sortable table. ths.length:"+ths.length + " tags.length:"+this.tags.length + " sortOrder:["+sortOrder+"]"); return; } }, columnsFromTable: function (table) {// Creates a sortColumns struct from the contents of a 'table.sortable' this.inheritNow = sortTable.columnsFromTr; var tr = $(table).find('tr.sortable')[0]; this.inheritNow(tr); }, _sortOnButtonPress: function (anchor) { // Updates the sortColumns struct and sorts the table when a column header has been pressed @@ -2060,31 +2042,31 @@ } if ($(thead).hasClass('sortable') === false) { $(thead).addClass('sortable'); //warn('Added sortable class to thead'); } var sortColumns = new sortTable.columnsFromTr(tr,"silent"); if (!sortColumns || sortColumns.cellIxs.length === 0) { // could mark all columns as sortable! $(tr).find('th').each(function (ix) { $(this).addClass('sortable'); $(this).addClass('sort'+(ix+1)); //warn("Added class='sortable sort"+(ix+1)+"' to th:"+this.innerHTML); }); sortColumns = new sortTable.columnsFromTr(tr,"silent"); - if (sortColumns === undefined || sortColumns.cellIxs.length === 0) { + if (!sortColumns || sortColumns.cellIxs.length === 0) { warn("sortable table's header row contains no sort columns."); return; } } // Can wrap all columnn headers with link $(tr).find("th.sortable").each(function (ix) { if ( ! $(this).attr('onclick') ) { $(this).click( function () { sortTable.sortOnButtonPress(this);} ); } if ($.browser.msie) { // Special case for IE since CSS :hover doesn't work $(this).hover( function () { $(this).css( { backgroundColor: '#CCFFCC', cursor: 'hand' } ); }, function () { $(this).css( { backgroundColor: '#FCECC0', cursor: '' } ); } ); }