details: http://www.bx.psu.edu/hg/galaxy/rev/52fadf5aabd9 changeset: 2896:52fadf5aabd9 user: Kanwei Li kanwei@gmail.com date: Tue Oct 20 16:46:12 2009 -0400 description: trackster: caching goes by zoom levels, greatly improving zooming performance. revamped UI
4 file(s) affected in this change:
static/scripts/packed/trackster.js static/scripts/trackster.js static/trackster.css templates/tracks/browser.mako
diffs (439 lines):
diff -r 61684a4d6b9e -r 52fadf5aabd9 static/scripts/packed/trackster.js --- a/static/scripts/packed/trackster.js Tue Oct 20 15:34:47 2009 -0400 +++ b/static/scripts/packed/trackster.js Tue Oct 20 16:46:12 2009 -0400 @@ -1,1 +1,1 @@ -var DENSITY=1000,DATA_ERROR="There was an error in indexing this dataset.",DATA_NONE="No data for this chrom/contig.",CACHED_TILES=200,CACHED_DATA=20;var View=function(a,b){this.chrom=a;this.tracks=[];this.max_low=0;this.max_high=b;this.low=this.max_low;this.high=this.max_high;this.length=this.max_high-this.max_low};$.extend(View.prototype,{add_track:function(a){a.view=this;this.tracks.push(a);if(a.init){a.init()}},redraw:function(){$("#overview-box").css({left:(this.low/this.length)*$("#overview-viewport").width(),width:Math.max(4,((this.high-this.low)/this.length)*$("#overview-viewport").width())}).show();$("#low").text(this.low);$("#high").text(this.high);for(var b=0,a=this.tracks.length;b<a;b++){this.tracks[b].draw()}$("#bottom-spacer").remove();$("#viewport").append('<div id="bottom-spacer" style="height: 200px;"></div>')},move:function(b,a){this.low=Math.max(this.max_low,Math.floor(b));this.high=Math.min(this.length,Math.ceil(a))},zoom_in:function(d,b){if(this.max_high ===0){return}var c=this.high-this.low;var e=c/d/2;var a;if(b===undefined){a=(this.low+this.high)/2}else{a=this.low+c*b/$(document).width()}this.low=Math.floor(a-e);this.high=Math.ceil(a+e);if(this.low<this.max_low){this.low=this.max_low;this.high=c/d}else{if(this.high>this.max_high){this.high=this.max_high;this.low=this.max_high-c/d}}if(this.high-this.low<1){this.high=this.low+1}},zoom_out:function(c){if(this.max_high===0){return}var a=(this.low+this.high)/2;var b=this.high-this.low;var d=b*c/2;this.low=Math.floor(Math.max(0,a-d));this.high=Math.ceil(Math.min(this.length,a+d))},left:function(b){var a=this.high-this.low;var c=Math.floor(a/b);if(this.low-c<0){this.low=0;this.high=this.low+a}else{this.low-=c;this.high-=c}},right:function(b){var a=this.high-this.low;var c=Math.floor(a/b);if(this.high+c>this.length){this.high=this.length;this.low=this.high-a}else{this.low+=c;this.high+=c}}});var Track=function(a,b){this.name=a;this.parent_element=b;this.make_container()};$.extend (Track.prototype,{make_container:function(){this.header_div=$("<div class='track-header'>").text(this.name);this.content_div=$("<div class='track-content'>");this.container_div=$("<div class='track'></div>").append(this.header_div).append(this.content_div);this.parent_element.append(this.container_div)}});var TiledTrack=function(){this.tile_cache=new Cache(CACHED_TILES)};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(){var i=this.view.low,c=this.view.high,e=c-i;var b=Math.pow(10,Math.ceil(Math.log(e/DENSITY)/Math.log(10)));b=Math.max(b,1);b=Math.min(b,100000);var l=$("<div style='position: relative;'></div>");this.content_div.children(":first").remove();this.content_div.append(l);var j=this.content_div.width(),d=this.content_div.height(),m=j/e;var g;var a=Math.floor(i/b/DENSITY);while((a*DENSITY*b)<c){var k=m+"_"+a;if(this.tile_cache[k]){g=this.tile_cache[k];var f=a*DENSITY*b;g.css({left:(f-this.view.low)*m});l.append(g)}else{g=this.draw_tile(b,a,l,m,d)}if(g){t his.tile_cache[k]=g}a+=1}}});var LabelTrack=function(a){Track.call(this,null,a);this.container_div.addClass("label-track")};$.extend(LabelTrack.prototype,Track.prototype,{draw:function(){var c=this.view,d=c.high-c.low,g=Math.floor(Math.pow(10,Math.floor(Math.log(d)/Math.log(10)))),a=Math.floor(c.low/g)*g,e=this.content_div.width(),b=$("<div style='position: relative; height: 1.3em;'></div>");while(a<c.high){var f=(a-c.low)/d*e;b.append($("<div class='label'>"+a+"</div>").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.content_div.append(b)}});var LineTrack=function(c,b,a){Track.call(this,c,$("#viewport"));TiledTrack.call(this);this.track_type="line";this.height_px=(a?a:100);this.container_div.addClass("line-track");this.dataset_id=b;this.cache=new Cache(CACHED_DATA)};$.extend(LineTrack.prototype,TiledTrack.prototype,{init:function(){var a=this;$.getJSON(data_url,{stats:true,track_type:a.track_type,chrom:a.view.chrom,low:null,high:n ull,dataset_id:a.dataset_id},function(b){if(!b||b=="error"){a.content_div.addClass("error").text(DATA_ERROR)}else{if(b=="no data"){a.content_div.addClass("nodata").text(DATA_NONE)}else{a.content_div.css("height",a.height_px+"px");a.min_value=b.min;a.max_value=b.max;a.vertical_range=a.max_value-a.min_value;a.view.redraw()}}})},get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;$.getJSON(data_url,{track_type:this.track_type,chrom:this.view.chrom,low:a,high:f,dataset_id:this.dataset_id},function(g){c.cache[e]=g;$(document).trigger("redraw")})},draw_tile:function(d,a,m,p,n){if(!this.vertical_range){return}var h=a*DENSITY*d,b=DENSITY*d,c=$("<canvas class='tile'></canvas>"),l=d+"_"+a;if(!this.cache[l]){this.get_data(d,a);return}var g=this.cache[l];c.css({position:"absolute",top:0,left:(h-this.view.low)*p});c.get(0).width=Math.ceil(b*p);c.get(0).height=this.height_px;var o=c.get(0).getContext("2d");var e=false;o.beginPath();for(var f=0;f<g.length-1;f++){var k=g[f][0]-h;var j=g[f][1];if(isNaN(j)){e=false}else{k=k*p;j=(j-this.min_value)/this.vertical_range*this.height_px;if(e){o.lineTo(k,j)}else{o.moveTo(k,j);e=true}}}o.stroke();m.append(c);return c}});var FeatureTrack=function(c,b,a){Track.call(this,c,$("#viewport"));TiledTrack.call(this);this.track_type="feature";this.height_px=(a?a:100);this.container_div.addClass("feature-track");this.dataset_id=b;this.zo_slots={};this.show_labels_scale=0.001;this.showing_labels=false;this.vertical_gap=10};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var a=this;$.getJSON(data_url,{track_type:a.track_type,low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom},function(b){if(b=="error"){a.content_div.addClass("error").text(DATA_ERROR)}else{if(b.length===0||b=="no data"){a.content_div.addClass("nodata").text(DATA_NONE)}else{a.content_div.css("height",a.height_px+"px");a.values=b;a.calc_slots();a.slots=a.zo_slots;a.draw()}}})},calc_slots:func tion(o){var c=[],b=this.container_div.width()/(this.view.high-this.view.low),g=this.show_labels_scale,a=this.view.max_high,e=this.view.max_low;if(o){this.zi_slots={}}var m=$("<canvas></canvas>").get(0).getContext("2d");for(var f=0,h=this.values.length;f<h;f++){var k,l,n=this.values[f];if(o){k=Math.floor(Math.max(e,(n.start-e)*g));k-=m.measureText(n.name).width;l=Math.ceil(Math.min(a,(n.end-e)*g))}else{k=Math.floor(Math.max(e,(n.start-e)*b));l=Math.ceil(Math.min(a,(n.end-e)*b))}var d=0;while(true){if(c[d]===undefined||c[d]<k){c[d]=l;if(o){this.zi_slots[n.name]=d}else{this.zo_slots[n.name]=d}break}d++}}this.height_px=c.length*this.vertical_gap+15;this.content_div.css("height",this.height_px+"px")},draw_tile:function(u,z,l,p,n){if(!this.values){return null}if(p>this.show_labels_scale&&!this.showing_labels){this.showing_labels=true;if(!this.zi_slots){this.calc_slots(true)}this.slots=this.zi_slots}else{if(p<=this.show_labels_scale&&this.showing_labels){this.showing_labels=false;t his.slots=this.zo_slots}}var A=z*DENSITY*u,c=(z+1)*DENSITY*u,b=DENSITY*u;var s=Math.ceil(b*p),r=this.height_px,q=$("<canvas class='tile'></canvas>");q.css({position:"absolute",top:0,left:(A-this.view.low)*p});q.get(0).width=s;q.get(0).height=r;var t=q.get(0).getContext("2d");t.fillStyle="#000";t.font="10px monospace";t.textAlign="right";var w=0;for(var x=0,y=this.values.length;x<y;x++){var h=this.values[x];if(h.start<=c&&h.end>=A){var f=Math.floor(Math.max(0,(h.start-A)*p)),g=Math.ceil(Math.min(s,(h.end-A)*p)),e=this.slots[h.name]*this.vertical_gap;t.fillRect(f,e+5,g-f,1);if(this.showing_labels&&t.fillText){t.fillText(h.name,f,e+8)}var d,E;if(h.exon_start&&h.exon_end){d=Math.floor(Math.max(0,(h.exon_start-A)*p));E=Math.ceil(Math.min(s,(h.exon_end-A)*p));t.fillRect(d,e+4,E-d,3)}if(h.blocks){for(var v=0,C=h.blocks.length;v<C;v++){var o=h.blocks[v],m=Math.floor(Math.max(0,(o[0]-A)*p)),B=Math.ceil(Math.min(s,(o[1]-A)*p));var a=3,D=4;if(d&&m>=d&&B<=E){a=5;D=3}t.fillRect(m,e+D,B-m ,a)}}w++}}l.append(q);return q}}); \ No newline at end of file +var DENSITY=1000,DATA_ERROR="There was an error in indexing this dataset.",DATA_NONE="No data for this chrom/contig.",CACHED_TILES=50,CACHED_DATA=20;function commatize(b){b+="";var a=/(\d+)(\d{3})/;while(a.test(b)){b=b.replace(a,"$1,$2")}return b}var View=function(b,a){this.chrom=b;this.tracks=[];this.max_low=0;this.max_high=a;this.center=(this.max_high-this.max_low)/2;this.span=this.max_high-this.max_low;this.zoom_factor=2;this.zoom_level=0};$.extend(View.prototype,{add_track:function(a){a.view=this;this.tracks.push(a);if(a.init){a.init()}},redraw:function(){var d=this.span/Math.pow(this.zoom_factor,this.zoom_level),b=this.center-(d/2),e=b+d;if(b<0){b=0;e=b+d}else{if(e>this.max_high){e=this.max_high;b=e-d}}this.low=Math.floor(b);this.high=Math.ceil(e);this.center=Math.round(this.low+(this.high-this.low)/2);$("#overview-box").css({left:(this.low/this.span)*$("#overview-viewport").width(),width:Math.max(12,((this.high-this.low)/this.span)*$("#overview-viewport").width())}).sh ow();$("#low").text(commatize(this.low));$("#high").text(commatize(this.high));for(var c=0,a=this.tracks.length;c<a;c++){this.tracks[c].draw()}$("#bottom-spacer").remove();$("#viewport").append('<div id="bottom-spacer" style="height: 200px;"></div>')},zoom_in:function(a){if(this.max_high===0||this.high-this.low<5){return}if(a){this.center=a/$(document).width()*(this.high-this.low)+this.low}this.zoom_level+=1},zoom_out:function(){if(this.max_high===0){return}if(this.zoom_level<=0){this.zoom_level=0;return}this.zoom_level-=1}});var Track=function(a,b){this.name=a;this.parent_element=b;this.make_container()};$.extend(Track.prototype,{make_container:function(){this.header_div=$("<div class='track-header'>").text(this.name);this.content_div=$("<div class='track-content'>");this.container_div=$("<div class='track'></div>").append(this.header_div).append(this.content_div);this.parent_element.append(this.container_div)}});var TiledTrack=function(){this.tile_cache=new Cache(CACHED_TI LES)};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(){var i=this.view.low,c=this.view.high,e=c-i;var b=Math.pow(10,Math.ceil(Math.log(e/DENSITY)/Math.log(10)));b=Math.max(b,1);b=Math.min(b,100000);var l=$("<div style='position: relative;'></div>");this.content_div.children(":first").remove();this.content_div.append(l);var j=this.content_div.width(),d=this.content_div.height(),m=j/e;var g;var a=Math.floor(i/b/DENSITY);while((a*DENSITY*b)<c){var k=this.view.zoom_level+"_"+a;if(this.tile_cache[k]){g=this.tile_cache[k];var f=a*DENSITY*b;g.css({left:(f-this.view.low)*m});l.append(g)}else{g=this.draw_tile(b,a,l,m,d)}if(g){this.tile_cache[k]=g}a+=1}}});var LabelTrack=function(a){Track.call(this,null,a);this.container_div.addClass("label-track")};$.extend(LabelTrack.prototype,Track.prototype,{draw:function(){var c=this.view,d=c.high-c.low,g=Math.floor(Math.pow(10,Math.floor(Math.log(d)/Math.log(10)))),a=Math.floor(c.low/g)*g,e=this.content_div.width(),b=$("<div style= 'position: relative; height: 1.3em;'></div>");while(a<c.high){var f=(a-c.low)/d*e;b.append($("<div class='label'>"+commatize(a)+"</div>").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.content_div.append(b)}});var LineTrack=function(c,b,a){Track.call(this,c,$("#viewport"));TiledTrack.call(this);this.track_type="line";this.height_px=(a?a:100);this.container_div.addClass("line-track");this.dataset_id=b;this.cache=new Cache(CACHED_DATA)};$.extend(LineTrack.prototype,TiledTrack.prototype,{init:function(){var a=this;$.getJSON(data_url,{stats:true,track_type:a.track_type,chrom:a.view.chrom,low:null,high:null,dataset_id:a.dataset_id},function(b){if(!b||b=="error"){a.content_div.addClass("error").text(DATA_ERROR)}else{if(b=="no data"){a.content_div.addClass("nodata").text(DATA_NONE)}else{a.content_div.css("height",a.height_px+"px");a.min_value=b.min;a.max_value=b.max;a.vertical_range=a.max_value-a.min_value;a.view.redraw()}}})},get_data:f unction(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;$.getJSON(data_url,{track_type:this.track_type,chrom:this.view.chrom,low:a,high:f,dataset_id:this.dataset_id},function(g){c.cache[e]=g;$(document).trigger("redraw")})},draw_tile:function(d,a,m,o){if(!this.vertical_range){return}var h=a*DENSITY*d,b=DENSITY*d,c=$("<canvas class='tile'></canvas>"),l=d+"_"+a;if(!this.cache[l]){this.get_data(d,a);return}var g=this.cache[l];c.css({position:"absolute",top:0,left:(h-this.view.low)*o});c.get(0).width=Math.ceil(b*o);c.get(0).height=this.height_px;var n=c.get(0).getContext("2d");var e=false;n.beginPath();for(var f=0;f<g.length-1;f++){var k=g[f][0]-h;var j=g[f][1];if(isNaN(j)){e=false}else{k=k*o;j=(j-this.min_value)/this.vertical_range*this.height_px;if(e){n.lineTo(k,j)}else{n.moveTo(k,j);e=true}}}n.stroke();m.append(c);return c}});var FeatureTrack=function(c,b,a){Track.call(this,c,$("#viewport"));TiledTrack.call(this);this.track_type="feature";this.height_px=(a?a:100);th is.container_div.addClass("feature-track");this.dataset_id=b;this.zo_slots={};this.show_labels_scale=0.001;this.showing_labels=false;this.vertical_gap=10};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var a=this;$.getJSON(data_url,{track_type:a.track_type,low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom},function(b){if(b=="error"){a.content_div.addClass("error").text(DATA_ERROR)}else{if(b.length===0||b=="no data"){a.content_div.addClass("nodata").text(DATA_NONE)}else{a.content_div.css("height",a.height_px+"px");a.values=b;a.calc_slots();a.slots=a.zo_slots;a.draw()}}})},calc_slots:function(o){var c=[],b=this.container_div.width()/(this.view.high-this.view.low),g=this.show_labels_scale,a=this.view.max_high,e=this.view.max_low;if(o){this.zi_slots={}}var m=$("<canvas></canvas>").get(0).getContext("2d");for(var f=0,h=this.values.length;f<h;f++){var k,l,n=this.values[f];if(o){k=Math.floor(Math.max(e,(n.start-e)*g));k-=m.mea sureText(n.name).width;l=Math.ceil(Math.min(a,(n.end-e)*g))}else{k=Math.floor(Math.max(e,(n.start-e)*b));l=Math.ceil(Math.min(a,(n.end-e)*b))}var d=0;while(true){if(c[d]===undefined||c[d]<k){c[d]=l;if(o){this.zi_slots[n.name]=d}else{this.zo_slots[n.name]=d}break}d++}}this.height_px=c.length*this.vertical_gap+15;this.content_div.css("height",this.height_px+"px")},draw_tile:function(t,y,g,n){if(!this.values){return null}if(n>this.show_labels_scale&&!this.showing_labels){this.showing_labels=true;if(!this.zi_slots){this.calc_slots(true)}this.slots=this.zi_slots}else{if(n<=this.show_labels_scale&&this.showing_labels){this.showing_labels=false;this.slots=this.zo_slots}}var z=y*DENSITY*t,b=(y+1)*DENSITY*t,o=DENSITY*t;var r=Math.ceil(o*n),q=this.height_px,p=$("<canvas class='tile'></canvas>");p.css({position:"absolute",top:0,left:(z-this.view.low)*n});p.get(0).width=r;p.get(0).height=q;var s=p.get(0).getContext("2d");s.fillStyle="#000";s.font="10px monospace";s.textAlign="right";var v=0;for(var w=0,x=this.values.length;w<x;w++){var f=this.values[w];if(f.start<=b&&f.end>=z){var e=Math.floor(Math.max(0,(f.start-z)*n)),h=Math.ceil(Math.min(r,(f.end-z)*n)),d=this.slots[f.name]*this.vertical_gap;s.fillRect(e,d+5,h-e,1);if(this.showing_labels&&s.fillText){s.fillText(f.name,e,d+8)}var c,D;if(f.exon_start&&f.exon_end){c=Math.floor(Math.max(0,(f.exon_start-z)*n));D=Math.ceil(Math.min(r,(f.exon_end-z)*n));s.fillRect(c,d+4,D-c,3)}if(f.blocks){for(var u=0,B=f.blocks.length;u<B;u++){var m=f.blocks[u],l=Math.floor(Math.max(0,(m[0]-z)*n)),A=Math.ceil(Math.min(r,(m[1]-z)*n));var a=3,C=4;if(c&&l>=c&&A<=D){a=5;C=3}s.fillRect(l,d+C,A-l,a)}}v++}}g.append(p);return p}}); \ No newline at end of file diff -r 61684a4d6b9e -r 52fadf5aabd9 static/scripts/trackster.js --- a/static/scripts/trackster.js Tue Oct 20 15:34:47 2009 -0400 +++ b/static/scripts/trackster.js Tue Oct 20 16:46:12 2009 -0400 @@ -5,17 +5,26 @@ var DENSITY = 1000, DATA_ERROR = "There was an error in indexing this dataset.", DATA_NONE = "No data for this chrom/contig.", - CACHED_TILES = 200, + CACHED_TILES = 50, CACHED_DATA = 20;
-var View = function( chrom, max_length ) { +function commatize( number ) { + number += ''; // Convert to string + var rgx = /(\d+)(\d{3})/; + while (rgx.test(number)) { + number = number.replace(rgx, '$1' + ',' + '$2'); + } + return number; +} +var View = function( chrom, max_high ) { this.chrom = chrom; this.tracks = []; this.max_low = 0; - this.max_high = max_length; - this.low = this.max_low; - this.high = this.max_high; - this.length = this.max_high - this.max_low; + this.max_high = max_high; + this.center = (this.max_high - this.max_low) / 2; + this.span = this.max_high - this.max_low; + this.zoom_factor = 2; + this.zoom_level = 0; }; $.extend( View.prototype, { add_track: function ( track ) { @@ -24,82 +33,55 @@ if (track.init) { track.init(); } }, redraw: function () { + var span = this.span / Math.pow(this.zoom_factor, this.zoom_level), + low = this.center - (span / 2), + high = low + span; + + if (low < 0) { + low = 0; + high = low + span; + + } else if (high > this.max_high) { + high = this.max_high; + low = high - span; + } + this.low = Math.floor(low); + this.high = Math.ceil(high); + this.center = Math.round( this.low + (this.high - this.low) / 2 ); + // Overview $("#overview-box").css( { - left: ( this.low / this.length ) * $("#overview-viewport").width(), - width: Math.max( 4, ( ( this.high - this.low ) / this.length ) * $("#overview-viewport").width() ) + left: ( this.low / this.span ) * $("#overview-viewport").width(), + // Minimum width for usability + width: Math.max( 12, ( ( this.high - this.low ) / this.span ) * $("#overview-viewport").width() ) }).show(); - $("#low").text( this.low ); - $("#high").text( this.high ); + $("#low").text( commatize(this.low) ); + $("#high").text( commatize(this.high) ); for ( var i = 0, len = this.tracks.length; i < len; i++ ) { this.tracks[i].draw(); } $("#bottom-spacer").remove(); $("#viewport").append('<div id="bottom-spacer" style="height: 200px;"></div>'); }, - move: function ( new_low, new_high ) { - this.low = Math.max( this.max_low, Math.floor( new_low ) ); - this.high = Math.min( this.length, Math.ceil( new_high ) ); + zoom_in: function ( point ) { + if (this.max_high === 0 || this.high - this.low < 5) { + return; + } + + if ( point ) { + this.center = point / $(document).width() * (this.high - this.low) + this.low; + } + this.zoom_level += 1; }, - zoom_in: function ( factor, point ) { + zoom_out: function () { if (this.max_high === 0) { return; } - - var range = this.high - this.low; - var diff = range / factor / 2; - var center; - - if (point === undefined) { - center = ( this.low + this.high ) / 2; - } else { - center = this.low + range * point / $(document).width(); + if (this.zoom_level <= 0) { + this.zoom_level = 0; + return; } - this.low = Math.floor( center - diff ); - this.high = Math.ceil( center + diff ); - if (this.low < this.max_low) { - this.low = this.max_low; - this.high = range / factor; - } else if (this.high > this.max_high) { - this.high = this.max_high; - this.low = this.max_high - range / factor; - // console.log(this.high, this.low); - } - if (this.high - this.low < 1 ) { - this.high = this.low + 1; - } - }, - zoom_out: function ( factor ) { - if (this.max_high === 0) { - return; - } - var center = ( this.low + this.high ) / 2; - var range = this.high - this.low; - var diff = range * factor / 2; - this.low = Math.floor( Math.max( 0, center - diff ) ); - this.high = Math.ceil( Math.min( this.length, center + diff ) ); - }, - left: function( factor ) { - var range = this.high - this.low; - var diff = Math.floor( range / factor ); - if ( this.low - diff < 0 ) { - this.low = 0; - this.high = this.low + range; - } else { - this.low -= diff; - this.high -= diff; - } - }, - right: function ( factor ) { - var range = this.high - this.low; - var diff = Math.floor( range / factor ); - if ( this.high + diff > this.length ) { - this.high = this.length; - this.low = this.high - range; - } else { - this.low += diff; - this.high += diff; - } + this.zoom_level -= 1; } });
@@ -143,7 +125,7 @@ var tile_index = Math.floor( low / resolution / DENSITY ); while ( ( tile_index * DENSITY * resolution ) < high ) { // Check in cache - var key = w_scale + "_" + tile_index; + var key = this.view.zoom_level + "_" + tile_index; if ( this.tile_cache[key] ) { // console.log("cached tile"); tile_element = this.tile_cache[key]; @@ -178,7 +160,7 @@ new_div = $("<div style='position: relative; height: 1.3em;'></div>"); while ( position < view.high ) { var screenPosition = ( position - view.low ) / range * width; - new_div.append( $("<div class='label'>" + position + "</div>").css( { + new_div.append( $("<div class='label'>" + commatize( position ) + "</div>").css( { position: "absolute", // Reduce by one to account for border left: screenPosition - 1 @@ -231,7 +213,7 @@ $(document).trigger( "redraw" ); }); }, - draw_tile: function( resolution, tile_index, parent_element, w_scale, h_scale ) { + draw_tile: function( resolution, tile_index, parent_element, w_scale ) { if (!this.vertical_range) { // We don't have the necessary information yet return; } @@ -354,11 +336,11 @@ this.height_px = end_ary.length * this.vertical_gap + 15; this.content_div.css( "height", this.height_px + "px" ); }, - draw_tile: function( resolution, tile_index, parent_element, w_scale, h_scale ) { + draw_tile: function( resolution, tile_index, parent_element, w_scale ) { if (!this.values) { // Still loading return null; } - // Once we zoom in enough, show name labels + // Once we zoom in enough, show name labels if (w_scale > this.show_labels_scale && !this.showing_labels) { this.showing_labels = true; if (!this.zi_slots) { @@ -373,9 +355,9 @@
var tile_low = tile_index * DENSITY * resolution, tile_high = ( tile_index + 1 ) * DENSITY * resolution, - tile_length = DENSITY * resolution; + tile_span = DENSITY * resolution; // console.log(tile_low, tile_high, tile_length, w_scale); - var width = Math.ceil( tile_length * w_scale ), + var width = Math.ceil( tile_span * w_scale ), height = this.height_px, new_canvas = $("<canvas class='tile'></canvas>");
diff -r 61684a4d6b9e -r 52fadf5aabd9 static/trackster.css --- a/static/trackster.css Tue Oct 20 15:34:47 2009 -0400 +++ b/static/trackster.css Tue Oct 20 16:46:12 2009 -0400 @@ -2,16 +2,17 @@ margin: 0 0; padding: 0; font-family: verdana; - font-size: 75%; + font-size: 12px; overflow-y: hidden; }
#content { width: 100%; + height: 100%; }
-#center { - overflow: auto; +#center { + overflow: auto; }
#nav { @@ -36,26 +37,35 @@ -webkit-border-radius: 1em; -moz-border-radius: 1em; } +#low { + margin-left: 0.1em; + float: left; +} +#high { + margin-right: 0.1em; + float: right; +}
#overview { width: 100%; - padding: 10px 0 0 0; margin: 0px; background: #333; color: white; - font-weight: bold; }
#overview-viewport { - height: 10px; - border-top: solid #666 1px; - border-bottom: solid #666 1px; + height: 20px; +/* border-top: solid #666 1px;*/ +/* border-bottom: solid #aaa 1px;*/ background: #888; } #overview-box { position: absolute; - height: 10px; - background: #ddd; + margin-top: 1px; + height: 16px; + background: #ddd url(/static/images/draggable_horizontal.png) center center no-repeat; + border-style: outset; + border-width: 1px; }
#viewport { @@ -100,6 +110,12 @@ min-height: 100px; }
+.label-track { + font-weight: bold; + font-size: 10px; + background-color: #333; + color: white; +} .label-track .label { border-left: solid gray 1px; padding-left: 2px; diff -r 61684a4d6b9e -r 52fadf5aabd9 templates/tracks/browser.mako --- a/templates/tracks/browser.mako Tue Oct 20 15:34:47 2009 -0400 +++ b/templates/tracks/browser.mako Tue Oct 20 16:46:12 2009 -0400 @@ -16,7 +16,7 @@
$(function() {
- view.add_track( new LabelTrack( $("#overview" ) ) ); + view.add_track( new LabelTrack( $("#viewport" ) ) ); view.add_track( new LabelTrack( $("#nav-labeltrack" ) ) );
%for track in tracks: @@ -27,41 +27,35 @@ view.redraw(); });
- $(document).bind("mousewheel", function(e, delta) { + $(document).bind("mousewheel", function( e, delta ) { if (delta > 0) { - view.zoom_in(2, e.pageX); + view.zoom_in(e.pageX); view.redraw(); } else { - view.zoom_out(2); + view.zoom_out(); view.redraw(); } });
- $(document).bind("dblclick", function(e) { - view.zoom_in(2, e.pageX); + $(document).bind("dblclick", function( e ) { + view.zoom_in(e.pageX); view.redraw(); });
- $("#overview-box").bind("dragstart", function(e) { + // To let the overview box be draggable + $("#overview-box").bind("dragstart", function( e ) { this.current_x = e.offsetX; - }).bind("drag", function(e) { + }).bind("drag", function( e ) { var delta = e.offsetX - this.current_x; this.current_x = e.offsetX;
- var delta_chrom = Math.round(delta / $(document).width() * (view.max_high - view.max_low)); - var view_range = view.high - view.low; - - var new_low = view.low += delta_chrom; - var new_high = view.high += delta_chrom; - if (new_low < view.max_low) { - new_low = 0; - new_high = view_range; - } else if (new_high > view.max_high) { - new_high = view.max_high; - new_low = view.max_high - view_range; + var delta_chrom = Math.round(delta / $(document).width() * view.span); + view.center += delta_chrom; + if (view.center < 0) { + view.center = 0; + } else if (view.center > view.max_high) { + view.center = view.max_high; } - view.low = new_low; - view.high = new_high; view.redraw(); });
@@ -70,11 +64,12 @@ view.redraw(); });
- $("#viewport").bind( "dragstart", function ( e ) { + $("#viewport").bind( "dragstart", function( e ) { this.original_low = view.low; this.current_height = e.clientY; + this.current_x = e.offsetX; }).bind( "drag", function( e ) { - var move_amount = ( e.offsetX - this.offsetLeft ) / this.offsetWidth; + var delta = e.offsetX - this.current_x; var new_scroll = $(this).scrollTop() - (e.clientY - this.current_height);
if ( new_scroll < $(this).get(0).scrollHeight - $(this).height() - 200) { @@ -82,19 +77,10 @@
} this.current_height = e.clientY; - var range = view.high - view.low; - var move_bases = Math.round( range * move_amount ); - var new_low = this.original_low - move_bases; - if ( new_low < 0 ) { - new_low = 0; - } - var new_high = new_low + range; - if ( new_high > view.length ) { - new_high = view.length; - new_low = new_high - range; - } - view.low = new_low; - view.high = new_high; + this.current_x = e.offsetX; + + var delta_chrom = Math.round(delta / $(document).width() * (view.max_high - view.max_low)); + view.center += delta_chrom; view.redraw(); }); (function () { @@ -122,28 +108,25 @@ </%def>
<div id="content"> + <div id="viewport"></div> +</div> +<div id="nav"> + <div id="nav-labeltrack"></div> <div id="overview"> <div id="overview-viewport"> <div id="overview-box"></div> </div> </div> - <div id="viewport"></div> -</div> -<div id="nav"> - <div id="nav-labeltrack"></div> + <span id="low"></span> + <span id="high"></span> <div id="nav-controls"> <form name="chr" id="chr" method="get"> <select id="chrom" name="chrom"> <option value="">Loading</option> </select> <input type="hidden" name="dataset_ids" value="${dataset_ids}" /> - <a href="#" onclick="javascript:view.left(5);view.redraw();"><<</a> - <a href="#" onclick="javascript:view.left(2);view.redraw();"><</a> - <span id="low">0</span>—<span id="high">${LEN}</span> - <a href="#" onclick="javascript:view.zoom_in(2);view.redraw();">+</a> - <a href="#" onclick="javascript:view.zoom_out(2);view.redraw();">-</a> - <a href="#" onclick="javascript:view.right(2);view.redraw();">></a> - <a href="#" onclick="javascript:view.right(5);view.redraw();">>></a> + <a href="#" onclick="javascript:view.zoom_in();view.redraw();">+</a> + <a href="#" onclick="javascript:view.zoom_out();view.redraw();">-</a> </form> </div> </div>
galaxy-dev@lists.galaxyproject.org