1882b8518123019af079080747fa712cd0a75d65 chmalee Fri Jan 27 10:48:29 2023 -0800 Add zoom to exon/codon feature to hgTracks right click menu, refs #2724 diff --git src/hg/js/hgTracks.js src/hg/js/hgTracks.js index b7cb4db..cd11a07 100644 --- src/hg/js/hgTracks.js +++ src/hg/js/hgTracks.js @@ -2138,31 +2138,31 @@ } } } }; /////////////////////////////////////// //// rightClick (aka context menu) //// /////////////////////////////////////// var rightClick = { menu: null, selectedMenuItem: null, // currently choosen context menu item (via context menu). floatingMenuItem: null, currentMapItem: null, - supportZoomCodon: false, // turns on experimental feature (currently only in larry's tree). + supportZoomCodon: true, // add zoom to exon and zoom to codon to right click menu clickedHighlightIdx : null, // the index (0,1,...) of the highlight item that overlaps the last right-click makeMapItem: function (id) { // Create a dummy mapItem on the fly // (for objects that don't have corresponding entry in the map). if (id && id.length > 0 && hgTracks.trackDb) { var title; var rec = hgTracks.trackDb[id]; if (rec) { title = rec.shortLabel; } else { title = id; } return {id: id, title: "configure " + title}; } else { @@ -2189,35 +2189,31 @@ } return null; }, windowOpenFailedMsg: function () { warn("Your web browser prevented us from opening a new window.\n\n" + "Please change your browser settings to allow pop-up windows from " + document.domain + "."); }, handleZoomCodon: function (response, status) { var json = JSON.parse(response); if (json.pos) { - genomePos.set(json.pos, 3); - if (document.TrackForm) - document.TrackForm.submit(); - else - document.TrackHeaderForm.submit(); + imageV2.navigateInPlace("position="+json.pos); } else { alert(json.error); } }, handleViewImg: function (response, status) { // handles view image response, which must get new image without imageV2 gimmickery jQuery('body').css('cursor', ''); var str = "]*SRC='([^']+)'"; var reg = new RegExp(str); var a = reg.exec(response); if (a && a[1]) { if ( ! window.open(a[1]) ) { rightClick.windowOpenFailedMsg(); } @@ -2784,30 +2780,31 @@ o[str] = { onclick: rightClick.makeHitCallback(visStrings[i]) }; menu.push(o); } } done = true; } } } if (done) { o = {}; var any = false; var title = rightClick.selectedMenuItem.title || "feature"; + var exonNum = 0; var maxLength = 60; if (title.length > maxLength) { title = title.substring(0, maxLength) + "..."; } if ((isGene || isHgc || id === "wikiTrack") && href.indexOf("i=mergedItem") === -1) { // Add "Open details..." item var displayItemFunctions = false; if (rec) { if (rec.type.indexOf("wig") === 0 || rec.type.indexOf("bigWig") === 0 || id === "wikiTrack") { displayItemFunctions = false; } else if (rec.type.indexOf("expRatio") === 0) { displayItemFunctions = title !== "zoomInMore"; @@ -2817,30 +2814,34 @@ // For barChart mouseovers, replace title (which may be a category // name+value) with item name if (rec.type.indexOf("barChart") === 0 || rec.type.indexOf("bigBarChart") === 0) { a = /i=([^&]+)/.exec(href); if (a && a[1]) { title = a[1]; } } } // when "exonNumbers on", the mouse over text is not a good item description for the right-click menu // "exonNumbers on" is the default for genePred/bigGenePred tracks but can also be actived for bigBed and others // We don't have the value of "exonNumbers" here, so just use a heuristic to see if it's on if (title.search(/, strand [+-], (Intron|Exon) /)!==-1) { + re = /(Exon) ([1-9]+) of/; + matches = re.exec(title); + if (matches !== null && matches[2].length > 0) + exonNum = matches[2]; title = title.split(",")[0]; } else if (isHgc && ( href.indexOf('g=gtexGene')!== -1 || href.indexOf('g=unip') !== -1 || href.indexOf('g=knownGene') !== -1 )) { // For GTEx gene and UniProt mouseovers, replace title (which may be a tissue name) with // item (gene) name. Also need to unescape the urlencoded characters and the + sign. a = /i=([^&]+)/.exec(href); if (a && a[1]) { title = decodeURIComponent(a[1].replace(/\+/g, " ")); } } if (displayItemFunctions) { @@ -2879,39 +2880,49 @@ reg = new RegExp("g=([^&]+)"); a = reg.exec(href); if (a && a[1]) { table = a[1]; } } } if (name && table) { o[rightClick.makeImgTag("magnify.png")+" Zoom to codon"] = { onclick: function(menuItemClicked, menuObject) { rightClick.hit(menuItemClicked, menuObject, "zoomCodon", {name: name, table: table}); return true;} }; + if (exonNum > 0) { o[rightClick.makeImgTag("magnify.png")+" Zoom to exon"] = { onclick: function(menuItemClicked, menuObject) { - rightClick.hit(menuItemClicked, menuObject, - "zoomExon", - {name: name, table: table}); + $.ajax({ + type: "GET", + url: "../cgi-bin/hgApi", + data: cart.varsToUrlData({ 'db': getDb(), + 'cmd': "exonToPos", 'num': exonNum, + 'table': table, 'name': name}), + trueSuccess: rightClick.handleZoomCodon, + success: catchErrorOrDispatch, + error: errorHandler, + cache: true + }); return true; } }; } } + } o[rightClick.makeImgTag("dnaIcon.png")+" Get DNA for "+title] = { onclick: function(menuItemClicked, menuObject) { rightClick.hit(menuItemClicked, menuObject, "getDna"); return true; } }; } o[rightClick.makeImgTag("bookOut.png")+ " Open details page in new window..."] = { onclick: function(menuItemClicked, menuObject) { rightClick.hit(menuItemClicked, menuObject, "openLink"); return true; } }; any = true; } if (href && href.length > 0 && href.indexOf("i=mergedItem") === -1) {