8ed2d68b3774dcfe96b43cb0d60ed36ca84009bd tdreszer Fri Jul 29 14:59:06 2011 -0700 Integrate my dragScroll with Larry's new json hash code. diff --git src/hg/js/hgTracks.js src/hg/js/hgTracks.js index 7d1c735..bfa9e9d 100644 --- src/hg/js/hgTracks.js +++ src/hg/js/hgTracks.js @@ -1,25 +1,24 @@ // Javascript for use in hgTracks CGI var debug = false; var originalPosition; var originalSize; var originalCursor; var originalMouseOffset = {x:0, y:0}; var startDragZoom = null; 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; // turn on experimental zoom-to-codon functionality (currently only on in larrym's tree). var inPlaceUpdate = false; // modified based on value of hgTracks.inPlaceUpdate @@ -272,31 +271,31 @@ if(trackImg && jQuery.fn.contextMenu) { $('#hgTrackUiDialog').hide(); if(imageV2) { $("map[name!=ideoMap]").each( function(t) { parseMap($(this,false));}); } else { // XXXX still under debate whether we have to remove the map parseMap($('#map'),true); $('#map').empty(); } originalImgTitle = trackImg.attr("title"); if(imageV2) { loadContextMenu(trackImgTbl); //$(".trDraggable,.nodrop").each( function(t) { loadContextMenu($(this)); }); // FIXME: why isn't rightClick for sideLabel working??? Probably because there is no link! - if(inPlaceUpdate) { + if(inPlaceUpdate && !hgTracks.imgBoxPortal) { // Larry's experimental version of 1x panning (aka cheap panning). var originalLeft; var originalClientX; var withinTrackImgTbl; var last; trackImgTbl.mousedown( function (e) { originalClientX = e.clientX; withinTrackImgTbl = true; last = new Date(); jQuery('body').css('cursor', 'w-resize'); $("img.dataImg").each( function(index, ele) { var left = $(ele).css('left'); originalLeft = left.substring(0, left.length - 2) // we only need to look at one element, so bail out now. @@ -995,31 +994,32 @@ $( btns ).removeClass('btnBlue'); $( btns ).addClass('btnGrey'); if (jQuery.tableDnD != undefined) { var rows = imgTblContiguousRowSet($(this).parents('tr.trDraggable')[0]); if (rows) $( rows ).removeClass("trDrag"); } } ///////////////////////////////////////////////////// // Drag Scroll code jQuery.fn.panImages = function(imgOffset,imgBoxLeftOffset){ // globals across all panImages var leftLimit = imgBoxLeftOffset*-1; - var rightLimit = (imgBoxPortalWidth - imgBoxWidth + leftLimit); + var rightLimit = (hgTracks.imgBoxPortalWidth - hgTracks.imgBoxWidth + leftLimit); + var only1xScrolling = (hgTracks.imgBoxPortalOffsetX == 0); var prevX = (imgOffset + imgBoxLeftOffset)*-1; var portalWidth = 0; panAdjustHeight(prevX); this.each(function(){ var pic; var pan; if ( $(this).is("img") ) { pan = $(this).parent("div"); pic = $(this); } else if ( $(this).is("div.scroller") ) { pan = $(this); @@ -1080,84 +1080,81 @@ } else if ( newX < rightLimit ) { // scrolled all the way to the right if(atEdge) { // Do not drag straight off edge. Force second drag beyondImage = true; newX = rightLimit - (rightLimit - newX)/decelerator;// slower if( newX < rightLimit - wingSize) // Don't go too far over the edge! newX = rightLimit - wingSize; } else newX = rightLimit; } else if(newX >= rightLimit && newX < leftLimit) beyondImage = false; // could have scrolled back without mouse up var nowPos = newX.toString() + "px"; $(".panImg").css( {'left': nowPos }); $('.tdData').css( {'backgroundPosition': nowPos } ); + if (!only1xScrolling) + panAdjustHeight(newX); // NOTE: This will dynamically resize image while scrolling. Do we want to? panUpdatePosition(newX,false); } } } function panMouseUp(e) { // Must be a separate function instead of pan.mouseup event. //if(!e) e = window.event; if(mouseIsDown) { $(document).unbind('mousemove',panner); $(document).unbind('mouseup',panMouseUp); mouseIsDown = false; // Talk to tim about this. if(beyondImage) { - // FIXME: - // 1) When dragging beyondImage, side label is seen. Only solution may be 2 images! - // NOTE: tried clip:rect() but this only works with position:absolute! - // 2) Would be nice to support drag within AND beyond image: - // a) Within stops at border, and then second drag needed to go beyond - // b) Within needs support for next/prev arrows - // 3) AJAX does not work on full image. Larry's callback routine needs extension beyond songle track - //$.ajax({type: "GET", url: "../cgi-bin/hgTracks", - // data: "hgt.trackImgOnly=1&hgsid=" + getHgsid(), dataType: "html", - // trueSuccess: handleUpdateTrackMap, success: catchErrorOrDispatch, - // cmd: "wholeImage", cache: false }); + if(inPlaceUpdate) { + var pos = parsePosition(getPosition()); + navigateInPlace("position=" + encodeURIComponent(pos.chrom + ":" + pos.start + "-" + pos.end)); + } else { document.TrackHeaderForm.submit(); + } return true; // Make sure the setTimeout below is not called. } if(prevX != newX) { - panAdjustHeight(newX); + //if (!only1xScrolling) + // panAdjustHeight(newX); // NOTE: This will resize image after scrolling. Do we want to while scrolling? prevX = newX; } setTimeout('blockUseMap=false;',50); // Necessary incase the selectEnd was over a map item. select takes precedence. } } -}); + }); // end of this.each(function(){ function panUpdatePosition(newOffsetX,bounded) { // Updates the 'position/search" display with change due to panning - var portalWidthBases = imgBoxPortalEnd - imgBoxPortalStart; - var portalScrolledX = (imgBoxPortalOffsetX+imgBoxLeftLabel) + newOffsetX; + var portalWidthBases = hgTracks.imgBoxPortalEnd - hgTracks.imgBoxPortalStart; + var portalScrolledX = (hgTracks.imgBoxPortalOffsetX+hgTracks.imgBoxLeftLabel) + newOffsetX; - var newPortalStart = imgBoxPortalStart - Math.round(portalScrolledX*imgBoxBasesPerPixel); // As offset goes down, bases seen goes up! - if( newPortalStart < imgBoxChromStart && bounded) // Stay within bounds - newPortalStart = imgBoxChromStart; + var newPortalStart = hgTracks.imgBoxPortalStart - Math.round(portalScrolledX*hgTracks.imgBoxBasesPerPixel); // As offset goes down, bases seen goes up! + if( newPortalStart < hgTracks.imgBoxChromStart && bounded) // Stay within bounds + newPortalStart = hgTracks.imgBoxChromStart; var newPortalEnd = newPortalStart + portalWidthBases; - if( newPortalEnd > imgBoxChromEnd && bounded) { - newPortalEnd = imgBoxChromEnd; + if( newPortalEnd > hgTracks.imgBoxChromEnd && bounded) { + newPortalEnd = hgTracks.imgBoxChromEnd; newPortalStart = newPortalEnd - portalWidthBases; } if(newPortalStart > 0) { - // XXXX ? imgBoxPortalStart = newPortalStart; - // XXXX ? imgBoxPortalEnd = newPortalEnd; + // XXXX ? hgTracks.imgBoxPortalStart = newPortalStart; + // XXXX ? hgTracks.imgBoxPortalEnd = newPortalEnd; var newPos = hgTracks.chromName + ":" + commify(newPortalStart) + "-" + commify(newPortalEnd); setPosition(newPos, (newPortalEnd - newPortalStart + 1)); } return true; } function mapTopAndBottom(mapName,left,right) { // Find the top and bottom px given left and right boundaries var span = { top: -10, bottom: -10 }; var items = $("map[name='"+mapName+"']").children(); if($(items).length>0) { $(items).each(function(t) { var loc = this.coords.split(","); var aleft = parseInt(loc[0]); var aright = parseInt(loc[2]); @@ -1168,30 +1165,35 @@ span.top = atop; span.bottom = abottom; } else if(span.top > atop) { span.top = atop; } else if(span.bottom < abottom) { span.bottom = abottom; } } }); } return span; } function panAdjustHeight(newOffsetX) { // Adjust the height of the track data images so that bed items scrolled off screen // do not waste vertical real estate + + // Is the > 1x? + if (only1xScrolling) + return; + var left = newOffsetX * -1; var right = left + portalWidth; $(".panImg").each(function(t) { var mapid = "map_" + this.id.substring(4); var hDiv = $(this).parent(); var top = parseInt($(this).css("top")) * -1; var bottom = top + $(hDiv).height(); var span = mapTopAndBottom(mapid,left,right); if(span.top > 0) { var topdif = Math.abs(span.top - top); var botdif = Math.abs(span.bottom - bottom); if(topdif > 2 || botdif > 2) { $(hDiv).height( span.bottom - span.top ); top = span.top * -1; @@ -1419,35 +1421,33 @@ if (compositeSet && compositeSet.length > 0) $( compositeSet ).find('p.btn').removeClass('blueButtons'); // blue persists if($(row).attr('rowIndex') != dragStartIndex) { // NOTE Even if dragging a contiguous set of rows, // still only need to check the one under the cursor. if(imgTblSetOrder) { imgTblSetOrder(table); } imgTblZipButtons( table ); } $(document).unbind('mousemove',blockTheMapOnMouseMove); setTimeout('blockUseMap=false;',50); // Necessary incase the onDrop was over a map item. onDrop takes precedence. } }); } - if(imgBoxPortal) { - //warn("imgBox("+imgBoxChromStart+"-"+imgBoxChromEnd+","+imgBoxWidth+") bases/pix:"+imgBoxBasesPerPixel+"\nportal("+imgBoxPortalStart+"-"+imgBoxPortalEnd+","+imgBoxPortalWidth+") offset:"+imgBoxPortalOffsetX); - + if(hgTracks.imgBoxPortal) { // Turn on drag scrolling. - $("div.scroller").panImages(imgBoxPortalOffsetX,imgBoxLeftLabel); + $("div.scroller").panImages(hgTracks.imgBoxPortalOffsetX,hgTracks.imgBoxLeftLabel); } //$("#zoomSlider").slider({ min: -4, max: 3, step: 1 });//, handle: '.ui-slider-handle' }); // Temporary warning while new imageV2 code is being worked through if($('#map').children("AREA").length > 0) { warn('Using imageV2, but old map is not empty!'); } // Retrieve tracks via AJAX that may take too long to draw initialliy (i.e. a remote bigWig) var retrievables = $('#imgTbl').find("tr.mustRetrieve") if($(retrievables).length > 0) { $(retrievables).each( function (i) { var trackName = $(this).attr('id').substring(3); updateTrackImg(trackName,"",""); }); @@ -2491,30 +2491,33 @@ } } function afterImgTblReload() { // Reload various UI widgets after updating imgTbl map. parseMap(null, true); $("map[name!=ideoMap]").each( function(t) { parseMap($(this, false));}); initImgTblButtons(); loadImgAreaSelect(false); // Do NOT reload context menu (otherwise we get the "context menu sticks" problem). // loadContextMenu($('#tr_' + id)); if(trackImgTbl.tableDnDUpdate) trackImgTbl.tableDnDUpdate(); reloadFloatingItem(); + // Turn on drag scrolling. + if(hgTracks.imgBoxPortal) { + $("div.scroller").panImages(hgTracks.imgBoxPortalOffsetX,hgTracks.imgBoxLeftLabel); } function updateTrackImgForId(html, id) { // update row in imgTbl for given id. // return true if we successfully pull slice for id and update it in imgTrack. var str = "<TR id='tr_" + id + "'[^>]*>([\\s\\S]+?)</TR>"; var reg = new RegExp(str); var a = reg.exec(html); if(a && a[1]) { $('#tr_' + id).html(a[1]); // NOTE: Want to examine the png? Uncomment: //var img = $('#tr_' + id).find("img[id^='img_data_']").attr('src'); //warn("Just parsed image:<BR>"+img); return true;