3d283800e2d599f69c0d16fd6015620f7d27f5a1 tdreszer Fri May 9 13:42:40 2014 -0700 Replaced Object.keys() which may not be supported by some browsers and moved three utility type scripts from cart to utils.js. Redmine 13164. diff --git src/hg/js/hgTracks.js src/hg/js/hgTracks.js index adbb3dc..69e6f62 100644 --- src/hg/js/hgTracks.js +++ src/hg/js/hgTracks.js @@ -460,124 +460,115 @@ } ///////////////////////// //// cart updating ///// /////////////////////// var cart = { // Controls queuing and ultimately updating cart variables vis ajax or submit. Queued vars // are held in an object with unique keys preventing duplicate updates and ensuring last update // takes precedence. WARNING: be careful creating an object with variables on the fly: // cart.setVarsObj({track: vis}) is invalid but cart.setVarsObj({'knownGene': vis}) is ok! updateQueue: {}, updatesWaiting: function () { // returns TRUE if updates are waiting. - return (Object.keys(cart.updateQueue).length !== 0); + return objNotEmpty(cart.updateQueue); }, addUpdatesToUrl: function (url) { // adds any outstanding cart updates to the url, then clears the queue if (cart.updatesWaiting()) { - //console.log('cart.addUpdatesToUrl: '+Object.keys(cart.updateQueue).length+' vars'); + //console.log('cart.addUpdatesToUrl: '+objKeyCount(cart.updateQueue)+' vars'); var updates = cart.varsToUrlData(); // clears the queue if (typeof url === 'undefined' || url.length === 0) return updates; if (updates.length > 0) { var dataOnly = (url.indexOf("cgi-bin") === -1); // all urls should be to our cgis if (!dataOnly && url.lastIndexOf("?") === -1) url += "?" + updates; else url += '&' + updates; } } return url; }, beforeUnload: function () { // named function that can be bound and unbound to beforeunload event // Makes sure any outstanding queued updates are sent before leaving the page. - //console.log('cart.beforeUnload: '+Object.keys(cart.updateQueue).length+' vars'); + //console.log('cart.beforeUnload: '+objKeyCount(cart.updateQueue)+' vars'); cart.setVarsObj( {}, null, false ); // synchronous }, varsToUrlData: function (varsObj) { // creates a url data (var1=val1&var2=val2...) string from vars object and queue // The queue will be emptied by this call. cart.queueVarsObj(varsObj); // lay ontop of queue, to give new values precedence // Now convert to url data and clear queue var urlData = ''; if (cart.updatesWaiting()) { - //console.log('cart.varsToUrlData: '+Object.keys(cart.updateQueue).length+' vars'); + //console.log('cart.varsToUrlData: '+objKeyCount(cart.updateQueue)+' vars'); urlData = varHashToQueryString(cart.updateQueue); cart.updateQueue = {}; } return urlData; }, setVarsObj: function (varsObj, errFunc, async) { // Set all vars in a var hash, appending any queued updates - //console.log('cart.setVarsObj: were:'+Object.keys(cart.updateQueue).length + - // ' new:'+Object.keys(varsObj).length); + //console.log('cart.setVarsObj: were:'+objKeyCount(cart.updateQueue) + + // ' new:'+objKeyCount(varsObj); cart.queueVarsObj(varsObj); // lay ontop of queue, to give new values precedence // Now ajax update all in queue and clear queue if (cart.updatesWaiting()) { setVarsFromHash(cart.updateQueue, errFunc, async); cart.updateQueue = {}; } }, - arysToObj: function (names,values) - { // Make hash type obj with two parallel arrays. (should be moved to utils.js). - var obj = {}; - for(var ix=0; ix<names.length; ix++) { - obj[names[ix]] = values[ix]; - } - return obj; - }, - setVars: function (names, values, errFunc, async) { // ajax updates the cart, and includes any queued updates. - cart.setVarsObj(cart.arysToObj(names, values), errFunc, async); + cart.setVarsObj(arysToObj(names, values), errFunc, async); }, queueVarsObj: function (varsObj) { // Add object worth of cart updates to the 'to be updated' queue, so they can be sent to // the server later. Note: hash allows overwriting previous updates to the same variable. - if (typeof varsObj !== 'undefined' && Object.keys(varsObj).length !== 0) { - //console.log('cart.queueVarsObj: were:'+Object.keys(cart.updateQueue).length + - // ' new:'+Object.keys(varsObj).length); + if (typeof varsObj !== 'undefined' && objNotEmpty(varsObj)) { + //console.log('cart.queueVarsObj: were:'+objKeyCount(cart.updateQueue) + + // ' new:'+objKeyCount(varsObj)); for (var name in varsObj) { cart.updateQueue[name] = varsObj[name]; // NOTE: could update in background, however, failing to hit "refresh" is a user choice // first in queue, schedule background update - if (Object.keys(cart.updateQueue).length === 1) { + if (objKeyCount(cart.updateQueue) === 1) { // By unbind/bind, we assure that there is only one instance bound $(window).unbind('beforeunload', cart.beforeUnload); $(window).bind( 'beforeunload', cart.beforeUnload); } } } }, addVarsToQueue: function (names,values) { // creates a string of updates to save for ajax batch or a submit - cart.queueVarsObj(cart.arysToObj(names,values)); + cart.queueVarsObj(arysToObj(names,values)); }, } /////////////////////////////////////////////// //// visibility (mixed with group toggle) ///// /////////////////////////////////////////////// var vis = { enumOrder: new Array("hide", "dense", "full", "pack", "squish"), // map cgi enum visibility codes to strings update: function (track, visibility) { // Updates visibility state in hgTracks.trackDb and any visible elements on the page. // returns true if we modify at least one select in the group list var rec = hgTracks.trackDb[track]; @@ -1199,31 +1190,31 @@ /////////////////////////// //// Drag Reorder Code //// /////////////////////////// var dragReorder = { setOrder: function (table) { // Sets the 'order' value for the image table after a drag reorder var varsToUpdate = {}; $("tr.imgOrd").each(function (i) { if ($(this).attr('abbr') != $(this).attr('rowIndex').toString()) { $(this).attr('abbr',$(this).attr('rowIndex').toString()); var name = this.id.substring('tr_'.length) + '_imgOrd'; varsToUpdate[name] = $(this).attr('abbr'); } }); - if (Object.keys(varsToUpdate).length !== 0) { + if (objNotEmpty(varsToUpdate)) { cart.setVarsObj(varsToUpdate); imageV2.markAsDirtyPage(); } }, sort: function (table) { // Sets the table row order to match the order of the abbr attribute. // This is needed for back-button, and for visBox changes combined with refresh. var tbody = $(table).find('tbody')[0]; if(tbody == undefined) tbody = table; // Do we need to sort? var trs = tbody.rows; var needToSort = false; @@ -2194,31 +2185,31 @@ rightClick.reloadFloatingItem(); imageV2.requestImgUpdate(id, "hgt.transparentImage=0", ""); } } else if (cmd == 'hideSet') { var row = $( 'tr#tr_' + id ); var rows = dragReorder.getContiguousRowSet(row); if (rows && rows.length > 0) { var varsToUpdate = {}; for (var ix=rows.length - 1; ix >= 0; ix--) { // from bottom, just in case remove screws with us var rowId = $(rows[ix]).attr('id').substring('tr_'.length); // Remove subtrack level vis and explicitly uncheck. varsToUpdate[rowId] = '[]'; varsToUpdate[rowId+'_sel'] = 0; $(rows[ix]).remove(); } - if (Object.keys(varsToUpdate).length !== 0) { + if (objNotEmpty(varsToUpdate)) { cart.setVarsObj(varsToUpdate); } imageV2.afterImgChange(true); } } else if (cmd == 'hideComposite') { var rec = hgTracks.trackDb[id]; if (tdbIsSubtrack(rec)) { var row = $( 'tr#tr_' + id ); var rows = dragReorder.getCompositeSet(row); if (rows && rows.length > 0) { for (var ix=rows.length - 1; ix >= 0; ix--) { // from bottom, just in case remove screws with us $(rows[ix]).remove(); } var selectUpdated = vis.update(rec.parentTrack, 'hide'); cart.setVars( [rec.parentTrack], ['hide']); @@ -2696,46 +2687,46 @@ hgTrackUi: function (trackName,descriptionOnly) { waitOnFunction( popUp._uiDialigRequest, trackName, descriptionOnly ); // Launches the popup but shields the ajax with a waitOnFunction }, uiDialogOk: function (popObj, trackName) { // When hgTrackUi Cfg popup closes with ok, then update cart and refresh parts of page var rec = hgTracks.trackDb[trackName]; var subtrack = tdbIsSubtrack(rec) ? trackName :undefined; // If subtrack then vis rules differ var allVars = getAllVars($('#hgTrackUiDialog'), subtrack );// For unknown reasons IE8 fails to find $('#pop'), occasionally var changedVars = varHashChanges(allVars,popUp.saveAllVars); //warn("cfgVars:"+varHashToQueryString(changedVars)); var newVis = changedVars[trackName]; var hide = (newVis != null && (newVis == 'hide' || newVis == '[]')); // subtracks do not have "hide", thus '[]' if($('#imgTbl') == undefined) { // On findTracks or config page - if (Object.keys(changedVars).length !== 0) + if (objNotEmpty(changedVars)) cart.setVarsObj(changedVars); //if(hide) // TODO: When findTracks or config page has cfg popup, then vis change needs to be handled in page here } else { // On image page if(hide) { - if (Object.keys(changedVars).length !== 0) + if (objNotEmpty(changedVars)) cart.setVarsObj(changedVars); $(document.getElementById('tr_' + trackName)).remove(); imageV2.afterImgChange(true); } else { // Keep local state in sync if user changed visibility if(newVis != null) { vis.update(trackName, newVis); } - if (Object.keys(changedVars).length !== 0) { + if (objNotEmpty(changedVars)) { var urlData = cart.varsToUrlData(changedVars); if(imageV2.mapIsUpdateable) { imageV2.requestImgUpdate(trackName,urlData,""); } else { window.location = "../cgi-bin/hgTracks?" + urlData + "&hgsid=" + getHgsid(); } } } } }, uiDialog: function (response, status) { // Take html from hgTrackUi and put it up as a modal dialog.