2a399cf9c25667374836901d6d6367a7d0fefe6c
larrym
  Mon Feb 7 17:31:17 2011 -0800
add zoomToCodon code (redmine# 2724); this is currently turned off via the supportZoomCodon variable
diff --git src/hg/js/hgTracks.js src/hg/js/hgTracks.js
index 0742fae..b964606 100644
--- src/hg/js/hgTracks.js
+++ src/hg/js/hgTracks.js
@@ -14,30 +14,31 @@
 var imageV2 = false;
 var imgBoxPortal = false;
 var blockUseMap = false;
 var mapItems;
 var trackImg;               // jQuery element for the track image
 var trackImgTbl;            // jQuery element used for image table under imageV2
 var imgAreaSelect;          // jQuery element used for imgAreaSelect
 var originalImgTitle;
 var autoHideSetting = true; // Current state of imgAreaSelect autoHide setting
 var selectedMenuItem;       // currently choosen context menu item (via context menu).
 var browser;                // browser ("msie", "safari" etc.)
 var mapIsUpdateable = true;
 var currentMapItem;
 var floatingMenuItem;
 var visibilityStrsOrder = new Array("hide", "dense", "full", "pack", "squish");     // map browser numeric visibility codes to strings
+var supportZoomCodon = false;
 
 function initVars(img)
 {
 // There are various entry points, so we call initVars in several places to make sure this variables get updated.
     if(!originalPosition) {
         // remember initial position and size so we can restore it if user cancels
         originalPosition = getOriginalPosition();
         originalSize = $('#size').text();
         originalCursor = jQuery('body').css('cursor');
     }
 }
 
 function selectStart(img, selection)
 {
     initVars();
@@ -1471,36 +1472,36 @@
     // XXXX Is rightclick logic necessary?
     var rightclick = e.which ? (e.which == 3) : (e.button == 2);
     if(rightclick)
     {
         return false;
     } else {
         var o = findMapItem(e);
         if(o) {
             // XXXX Why does href get changed to "about://" on IE?
             window.location = o.href;
         }
         return true;
     }
 }
 
-function contextMenuHit(menuItemClicked, menuObject, cmd)
+function contextMenuHit(menuItemClicked, menuObject, cmd, args)
 {
-    setTimeout(function() { contextMenuHitFinish(menuItemClicked, menuObject, cmd); }, 1);
+    setTimeout(function() { contextMenuHitFinish(menuItemClicked, menuObject, cmd, args); }, 1);
 }
 
-function contextMenuHitFinish(menuItemClicked, menuObject, cmd)
+function contextMenuHitFinish(menuItemClicked, menuObject, cmd, args)
 {
 // dispatcher for context menu hits
     var id = selectedMenuItem.id;
     if(menuObject.shown) {
         // showWarning("Spinning: menu is still shown");
         setTimeout(function() { contextMenuHitFinish(menuItemClicked, menuObject, cmd); }, 10);
         return;
     }
     if(cmd == 'selectWholeGene' || cmd == 'getDna') {
             // bring whole gene into view or redirect to DNA screen.
             var href = selectedMenuItem.href;
             var chromStart, chromEnd;
             var a = /hgg_chrom=(\w+)&/.exec(href);
             // Many links leave out the chrom (b/c it's in the server side cart as "c")
             var chrom = document.getElementById("hgt.chromName").value;
@@ -1550,30 +1551,53 @@
                         jQuery('body').css('cursor', '');
                         $.ajax({
                                    type: "GET",
                                    url: "../cgi-bin/hgTracks",
                                    data: "hgt.trackImgOnly=1&hgt.ideogramToo=1&position=" + newPosition + "&hgsid=" + getHgsid(),
                                    dataType: "html",
                                    trueSuccess: handleUpdateTrackMap,
                                    success: catchErrorOrDispatch,
                                    error: errorHandler,
                                    cmd: cmd,
                                    cache: false
                                });
                     }
                 }
             }
+    } else if (cmd == 'zoomCodon' || cmd == 'zoomExon') {
+        var num, ajaxCmd, errorMsg;
+        if(cmd == 'zoomCodon') {
+            num = prompt("Please enter the codon number to jump to:");
+            ajaxCmd = 'codonPos';
+            errorMsg = num + " is an invalid codon for this gene";
+        } else {
+            num = prompt("Please enter the exon number to jump to:");
+            ajaxCmd = 'exonPos';
+            errorMsg = num + " is an invalid exon number for this gene";
+        }
+        if(num) {
+            $.ajax({
+                       type: "GET",
+                       url: "../cgi-bin/hgApi",
+                       data: "db=" + getDb() +  "&cmd=" + ajaxCmd + "&num=" + num + "&table=" + args.table + "&name=" + args.name,
+                       trueSuccess: handleZoomCodon,
+                       success: catchErrorOrDispatch,
+                       error: errorHandler,
+                       errorMsg: errorMsg,
+                       cache: true
+                   });
+        }
     } else if (cmd == 'hgTrackUi_popup') {
 
         hgTrackUiPopUp( selectedMenuItem.id, false );  // Launches the popup but shields the ajax with a waitOnFunction
 
     } else if (cmd == 'hgTrackUi_follow') {
 
         var url = "hgTrackUi?hgsid=" + getHgsid() + "&g=";
         var rec = trackDbJson[id];
         if (tdbHasParent(rec) && tdbIsLeaf(rec))
             url += rec.parentTrack
         else {
             var link = $( 'td#td_btn_'+ selectedMenuItem.id ).children('a'); // The button already has the ref
             if( $(link) != undefined)
                 url = $(link).attr('href');
             else
@@ -1775,30 +1799,61 @@
                         var title = selectedMenuItem.title || "feature";
                     if(isGene || isHgc || id == "wikiTrack") {
                         // 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";
                             } else {
                                 displayItemFunctions = true;
                             }
                         }
                         if(displayItemFunctions) {
                             o[makeImgTag("magnify.png") + " Zoom to " +  title] = {onclick: function(menuItemClicked, menuObject) { contextMenuHit(menuItemClicked, menuObject, "selectWholeGene"); return true; }};
+                            if(supportZoomCodon && rec.type.indexOf("genePred") != -1) {
+                                // http://hgwdev-larrym.cse.ucsc.edu/cgi-bin/hgGene?hgg_gene=uc003tqk.2&hgg_prot=P00533&hgg_chrom=chr7&hgg_start=55086724&hgg_end=55275030&hgg_type=knownGene&db=hg19&c=chr7
+                                var name, table;
+                                var reg = new RegExp("hgg_gene=([^&]+)");
+                                var a = reg.exec(href);
+                                if(a && a[1]) {
+                                    name = a[1];
+                                    reg = new RegExp("hgg_type=([^&]+)");
+                                    a = reg.exec(href);
+                                    if(a && a[1]) {
+                                        table = a[1];
+                                    }
+                                } else {
+                                    // http://hgwdev-larrym.cse.ucsc.edu/cgi-bin/hgc?o=55086724&t=55275031&g=refGene&i=NM_005228&c=chr7
+                                    // http://hgwdev-larrym.cse.ucsc.edu/cgi-bin/hgc?o=55086713&t=55270769&g=wgEncodeGencodeManualV4&i=ENST00000455089&c=chr7
+                                    var reg = new RegExp("i=([^&]+)");
+                                    var a = reg.exec(href);
+                                    if(a && a[1]) {
+                                        name = a[1];
+                                        reg = new RegExp("g=([^&]+)");
+                                        a = reg.exec(href);
+                                        if(a && a[1]) {
+                                            table = a[1];
+                                        }
+                                    }
+                                }
+                                if(name && table) {
+                                    o[makeImgTag("magnify.png") + " Zoom to codon"] = {onclick: function(menuItemClicked, menuObject) { contextMenuHit(menuItemClicked, menuObject, "zoomCodon", {name: name, table: table}); return true; }};
+                                    o[makeImgTag("magnify.png") + " Zoom to exon"] = {onclick: function(menuItemClicked, menuObject) { contextMenuHit(menuItemClicked, menuObject, "zoomExon", {name: name, table: table}); return true; }};
+                                }
+                            }
                             o[makeImgTag("dnaIcon.png") + " Get DNA for " +  title] = {onclick: function(menuItemClicked, menuObject) { contextMenuHit(menuItemClicked, menuObject, "getDna"); return true; }};
                         }
                         o[makeImgTag("bookOut.png") + " Open details page in new window..."] = {onclick: function(menuItemClicked, menuObject) { contextMenuHit(menuItemClicked, menuObject, "openLink"); return true; }};
                         any = true;
                     }
                     if(href != undefined && href.length  > 0) {
                         // Add "Show details..." item
                         if(title.indexOf("Click to alter ") == 0) {
                             ; // suppress the "Click to alter..." items
                         } else if(selectedMenuItem.href.indexOf("cgi-bin/hgTracks") != -1) {
                             ; // suppress menu items for hgTracks links (e.g. Next/Prev map items).
                         } else {
                             var item;
                             if(title == "zoomInMore")
                                 // avoid showing menu item that says "Show details for zoomInMore..." (redmine 2447)
@@ -2710,15 +2765,29 @@
                                           selectUpdated = true;
                                       });
     if(rec) {
         rec.localVisibility = visibility;
     }
     return selectUpdated;
 }
 
 function reloadFloatingItem()
 {
 // currently dead (experimental code)
     if(floatingMenuItem) {
         $('#img_data_' + floatingMenuItem).parent().makeFloat({x:"current",y:"current", speed: 'fast', alwaysVisible: true, alwaysTop: true});
     }
 }
+
+function handleZoomCodon(response, status)
+{
+    // XXXX use formal json interface
+    if(response.length > 1) {
+        setPosition(response, 3);
+        if(document.TrackForm)
+            document.TrackForm.submit();
+        else
+            document.TrackHeaderForm.submit();
+    } else {
+        alert(this.errorMsg);
+    }
+}