src/hg/js/hgTracks.js 1.40
1.40 2009/09/15 00:21:53 tdreszer
Make the chrom image draggable. Note click gives new position, same window size. Ctrl- gives cytoBand.
Index: src/hg/js/hgTracks.js
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/js/hgTracks.js,v
retrieving revision 1.39
retrieving revision 1.40
diff -b -B -U 4 -r1.39 -r1.40
--- src/hg/js/hgTracks.js 13 Sep 2009 21:05:49 -0000 1.39
+++ src/hg/js/hgTracks.js 15 Sep 2009 00:21:53 -0000 1.40
@@ -333,8 +333,279 @@
});
}
/////////////////////////////////////////////////////
+jQuery.fn.chromIdeo = function(){
+this.each(function(){
+ // Plan:
+ // mouseDown: determine where in map: convert to img location: pxDown
+ // mouseMove: flag drag
+ // mouseUp: if no drag, then create href centered on bpDown loc with current span
+ // if drag, then create href from bpDown to bpUp
+ // if ctrlKey then expand selection to containing cytoBand(s)
+ var pxTop = -1; // Top of cytobands
+ var pxBottom = -1; // Bottom of cytobands
+ var pxLeft = -1; // Beginning location of first cytoBand
+ var pxRight = -1; // End location of last cytoband
+ var pxImg = { top: -1, height: -1, left: -1, width: -1 }; // Image dimensions
+ var chrDef = { name: "", beg: -1, end: -1 }; // Dimenaions of chrom in bases
+ var pxDown = 0; // pix X location of mouseDown
+ var chrImg = $(this);
+ var mouseIsDown = false;
+ var mouseHasMoved = false;
+ var hilite = jQuery('<div></div>');
+
+ initialize();
+
+ function initialize(){
+
+ findDimensions();
+
+ if(pxTop == -1)
+ alert("chromIdeo(): failed to register "+this.id);
+ else {
+ hiliteSetup();
+
+ $('.cytoBand').mousedown( function(e) {
+ updateImgOffsets();
+ pxDown = e.clientX - pxImg.left;
+ var pxY = e.clientY - pxImg.top;
+ if(mouseIsDown == false
+ && pxDown >= pxLeft
+ && pxDown <= pxRight
+ && pxY >= pxTop
+ && pxY <= pxBottom) {
+ mouseIsDown = true;
+ mouseHasMoved = false;
+
+ $(document).bind('mousemove',chromMove);
+ $(document).bind( 'mouseup', chromUp);
+ hiliteShow(pxDown,pxDown);
+ return false;
+ }
+ //else alert("out fo range pxY:"+pxY+" = (e.clientY:"+e.clientY+" - pxImg.top:"+pxImg.top+") body.scrollTop():"+$("body").scrollTop()+" range:"+pxTop+"-"+pxBottom);
+ });
+ }
+ }
+
+ function chromMove(e) {
+ if ( mouseIsDown ) {
+ var pxX = e.clientX - pxImg.left;
+ //if(pxX >= -10 && pxX <= pxImg.width) {
+ var relativeX = (pxX - pxDown);
+ if(mouseHasMoved || (mouseHasMoved == false && Math.abs(relativeX) > 2)) {
+ mouseHasMoved = true;
+ if(pxX >= pxLeft && pxX <= pxRight)
+ hiliteShow(pxDown,pxX);
+ else if(pxX < pxLeft)
+ hiliteShow(pxDown,pxLeft);
+ else
+ hiliteShow(pxDown,pxRight);
+ }
+ //}
+ }
+ }
+ function chromUp(e) { // Must be a separate function instead of pan.mouseup event.
+ chromMove(e); // Just in case
+ if(mouseIsDown) {
+ updateImgOffsets();
+ var pxUp = e.clientX - pxImg.left;
+ var pxY = e.clientY - pxImg.top;
+ //alert("chromIdeo("+chrDef.name+") selected range (pix):"+pxDown+"-"+pxUp+" chrom range (pix):"+pxLeft+"-"+pxRight+" chrom range (bp):"+chrDef.name+":"+chrDef.beg+"-"+chrDef.end);
+ if(e.ctrlKey) {
+ var band = findCytoBand(pxDown,pxUp);
+ if(band.left > -1 && band.right > -1) {
+ pxDown = band.left;
+ pxUp = band.right;
+ mouseHasMoved = true;
+ hiliteShow(pxDown,pxUp);
+ }
+ }
+ if(pxY >= 0 && pxY <= pxImg.height) { // within vertical range or else cancel
+ var selRange = { beg: -1, end: -1, width: -1 };
+ var dontAsk = true;
+
+ if(mouseHasMoved) {
+ // bounded by chrom dimensions: but must remain within image!
+ if( pxUp < pxLeft && pxUp >= -20 )
+ pxUp = pxLeft;
+ if( pxUp > pxRight && pxUp <= pxRight + 30)
+ pxUp = pxRight;
+
+ if( pxLeft <= pxUp && pxUp <= pxRight ) {// Within horizontal (chrom) range
+
+ var offset = (pxDown - pxLeft)/(pxRight - pxLeft);
+ selRange.beg = Math.round(offset * (chrDef.end - chrDef.beg));
+ offset = (pxUp - pxLeft)/(pxRight - pxLeft);
+ selRange.end = Math.round(offset * (chrDef.end - chrDef.beg));
+
+ if(Math.abs(selRange.end - selRange.beg) < 20)
+ mouseHasMoved = false; // Drag so small: treat as simple click
+ else
+ dontAsk = false;
+ }
+ //else alert("chromIdeo("+chrDef.name+") NOT WITHIN HORIZONTAL RANGE\n selected range (pix):"+pxDown+"-"+pxUp+" chrom range (pix):"+pxLeft+"-"+pxRight);
+ }
+ if(mouseHasMoved == false) { // Not else because small drag turns this off
+
+ hiliteShow(pxUp,pxUp);
+ var curBeg = parseInt($("#hgt\\.winStart").val()); // Note the escaped '.'
+ var curEnd = parseInt($("#hgt\\.winEnd").val());
+ var curWidth = curEnd - curBeg;
+ var offset = (pxUp - pxLeft)/(pxRight - pxLeft);
+ selRange.beg = Math.round(offset * (chrDef.end - chrDef.beg)) - Math.round(curWidth/2); // Notice that beg is based upon up position
+ selRange.end = selRange.beg + curWidth;
+ }
+ if(selRange.end > -1) {
+ // prompt, then submit for new position
+ selRange = rangeNormaizeToChrom(selRange,chrDef);
+ if(mouseHasMoved == false) { // Update highlight by converting bp back to pix
+ var offset = selRange.beg/chrDef.end;
+ pxDown = Math.round(offset * (pxRight - pxLeft)) + pxLeft;
+ offset = selRange.end/chrDef.end;
+ pxUp = Math.round(offset * (pxRight - pxLeft)) + pxLeft;
+ hiliteShow(pxDown,pxUp);
+ }
+ if(dontAsk || confirm("Jump to new position:\n\n"+chrDef.name+":"+commify(selRange.beg)+"-"+commify(selRange.end)+" size:"+commify(selRange.width))) {
+ setPositionByCoordinates(chrDef.name, selRange.beg, selRange.end)
+ document.TrackHeaderForm.submit();
+ }
+ }
+ }
+ //else alert("chromIdeo("+chrDef.name+") NOT WITHIN VERTICAL RANGE\n selected range (pix):"+pxDown+"-"+pxUp+" chrom range (pix):"+pxLeft+"-"+pxRight+"\n cytoTop-Bottom:"+pxTop +"-"+pxBottom);
+ hiliteCancel();
+ $(document).unbind('mousemove',chromMove);
+ $(document).unbind('mouseup',chromUp);
+ setTimeout('blockUseMap=false;',50);
+ }
+ mouseIsDown = false;
+ mouseHasMoved = false;
+ }
+
+ function findDimensions()
+ {
+ $('.cytoBand').each(function(t) {
+ var loc = this.coords.split(",");
+ if(loc.length == 4) {
+ if( pxTop == -1) {
+ pxLeft = parseInt(loc[0]);
+ pxRight = parseInt(loc[2]);
+ pxTop = parseInt(loc[1]);
+ pxBottom = parseInt(loc[3]);
+ } else {
+ if( pxLeft > parseInt(loc[0]))
+ pxLeft = parseInt(loc[0]);
+ if( pxRight < parseInt(loc[2]))
+ pxRight = parseInt(loc[2]);
+ }
+
+ var range = this.title.substr(this.title.lastIndexOf(':')+1)
+ var pos = range.split('-');
+ if(pos.length == 2) {
+ if( chrDef.name.length == 0) {
+ chrDef.beg = parseInt(pos[0]);
+ chrDef.end = parseInt(pos[1]);
+ chrDef.name = this.title.substring(this.title.lastIndexOf(' ')+1,this.title.lastIndexOf(':'))
+ } else {
+ if( chrDef.beg > parseInt(pos[0]))
+ chrDef.beg = parseInt(pos[0]);
+ if( chrDef.end < parseInt(pos[1]))
+ chrDef.end = parseInt(pos[1]);
+ }
+ }
+ $(this).css( 'cursor', 'text');
+ $(this).attr("href","");
+ }
+ });
+ }
+
+ function findCytoBand(pxDown,pxUp) {
+ var cyto = { left: -1, right: -1 };
+ $('.cytoBand').each(function(t) {
+ var loc = this.coords.split(",");
+ if(loc.length == 4) {
+ if(cyto.left == -1 || cyto.left > parseInt(loc[0])) {
+ if((parseInt(loc[0]) <= pxDown && pxDown < parseInt(loc[2]))
+ || (parseInt(loc[0]) <= pxUp && pxUp < parseInt(loc[2])))
+ cyto.left = parseInt(loc[0]);
+ }
+ if(cyto.right == -1 || cyto.right < parseInt(loc[2])) {
+ if((parseInt(loc[0]) <= pxDown && pxDown < parseInt(loc[2]))
+ || (parseInt(loc[0]) <= pxUp && pxUp < parseInt(loc[2])))
+ cyto.right = parseInt(loc[2]);
+ }
+ }
+ });
+ return cyto;
+ }
+ function rangeNormaizeToChrom(selection,chrom)
+ {
+ if(selection.end < selection.beg) {
+ var tmp = selection.end;
+ selection.end = selection.beg;
+ selection.beg = tmp;
+ }
+ selection.width = (selection.end - selection.beg);
+ selection.beg += 1;
+ if( selection.beg < chrom.beg) {
+ selection.beg = chrom.beg;
+ selection.end = chrom.beg + selection.width;
+ }
+ if( selection.end > chrom.end) {
+ selection.end = chrom.end;
+ selection.beg = chrom.end - selection.width;
+ if( selection.beg < chrom.beg) { // spans whole chrom
+ selection.width = (selection.end - chrom.beg);
+ selection.beg = chrom.beg + 1;
+ }
+ }
+ return selection;
+ }
+
+ function hiliteShow(down,cur)
+ {
+ var topY = pxImg.top;
+ var high = pxImg.height;
+ var begX = -1;
+ var wide = -1;
+ if(cur < down) {
+ begX = cur + pxImg.left;
+ wide = (down - cur);
+ } else {
+ begX = down + pxImg.left;
+ wide = (cur - down);
+ }
+ $(hilite).css({ left: begX + 'px', width: wide + 'px', top: topY + 'px', height: high + 'px', display:'' });
+ $(hilite).show();
+ }
+ function hiliteCancel(left,width,top,height)
+ {
+ $(hilite).hide();
+ $(hilite).css({ left: '0px', width: '0px', top: '0px', height: '0px' });
+ }
+
+ function hiliteSetup()
+ {
+ $(hilite).css({ backgroundColor: 'green', opacity: 0.4, borderStyle: 'solid', borderWidth: '1px', bordercolor: '#0000FF' });
+ $p = $(chrImg);
+
+ $(hilite).css({ display: 'none', position: 'absolute', overflow: 'hidden', zIndex: 1 });
+ jQuery($(chrImg).parents('body')).append($(hilite));
+ return hilite;
+ }
+
+ function updateImgOffsets()
+ {
+ var offs = $(chrImg).offset();
+ pxImg.top = Math.round(offs.top - $("body").scrollTop() );
+ pxImg.left = Math.round(offs.left - $("body").scrollLeft() );
+ pxImg.height = parseInt($(chrImg).css("height"));
+ pxImg.width = parseInt($(chrImg).css("height"));
+ return pxImg;
+ }
+});
+}
+/////////////////////////////////////////////////////
jQuery.fn.panImages = function(imgOffset,imgBoxLeftOffset){
this.each(function(){
var pic;
@@ -577,8 +848,14 @@
if($('#map').children("AREA").length > 0) {
alert('Using imageV2, but old map is not empty!');
}
}
+ if($('img#chrom').length == 1) {
+ if($('.cytoBand').length > 1) {
+ $('img#chrom').chromIdeo();
+ }
+ }
+
});
function rulerModeToggle (ele)
{