commit/galaxy-central: jgoecks: Implement a data manager for trackster. Convert DataCache into a DataManager and use jQuery Deferred objects to move data management from the tile level to the track level. Implications of these changes include (a) callbacks are no longer needed when drawing tiles; (a) data is fetched before a tile is drawn; and (c) tile drawing is completely tracked so that actions can be taken after a track has been drawn.
1 new changeset in galaxy-central: http://bitbucket.org/galaxy/galaxy-central/changeset/e37ad896e5fd/ changeset: r5269:e37ad896e5fd user: jgoecks date: 2011-03-24 20:05:28 summary: Implement a data manager for trackster. Convert DataCache into a DataManager and use jQuery Deferred objects to move data management from the tile level to the track level. Implications of these changes include (a) callbacks are no longer needed when drawing tiles; (a) data is fetched before a tile is drawn; and (c) tile drawing is completely tracked so that actions can be taken after a track has been drawn. affected #: 4 files (1.4 KB) --- a/lib/galaxy/web/controllers/tracks.py Thu Mar 24 15:03:12 2011 -0400 +++ b/lib/galaxy/web/controllers/tracks.py Thu Mar 24 15:05:28 2011 -0400 @@ -741,9 +741,9 @@ # try: subset_job, subset_job_outputs = tool.execute( trans, incoming=tool_params, history=original_dataset.history ) - except e: + except Exception, e: # Lots of things can go wrong when trying to execute tool. - return to_json_string( { "error" : True, "message" : e.str() } ) + return to_json_string( { "error" : True, "message" : e.__class__.__name__ + ": " + str(e) } ) for output in subset_job_outputs.values(): output.visible = False trans.sa_session.flush() @@ -760,12 +760,6 @@ return self.add_track_async( trans, output_dataset.id ) - @web.expose - def woot( self, trans, ldda_id, target_type ): - ldda = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get( trans.security.decode_id( ldda_id ) ) - converted_dataset = ldda.get_converted_dataset( trans, target_type ) - raise converted_dataset - # # Helper methods. # --- a/static/scripts/packed/jquery.event.drag.js Thu Mar 24 15:03:12 2011 -0400 +++ b/static/scripts/packed/jquery.event.drag.js Thu Mar 24 15:05:28 2011 -0400 @@ -1,6 +1,6 @@ /* - * jquery.event.drag - v 2.0.0 + * jquery.event.drag - v 2.1.0 * Copyright (c) 2010 Three Dub Media - http://threedubmedia.com * Open Source MIT License - http://threedubmedia.com/code/license */ -(function(d){d.fn.drag=function(i,e,h){var g=typeof i=="string"?i:"",f=d.isFunction(i)?i:d.isFunction(e)?e:null;if(g.indexOf("drag")!==0){g="drag"+g}h=(i==f?e:h)||{};return f?this.bind(g,h,f):this.trigger(g)};var b=d.event,a=b.special,c=a.drag={defaults:{which:1,distance:0,not:":input",handle:null,relative:false,drop:true,click:false},datakey:"dragdata",livekey:"livedrag",add:function(g){var f=d.data(this,c.datakey),e=g.data||{};f.related+=1;if(!f.live&&g.selector){f.live=true;b.add(this,"draginit."+c.livekey,c.delegate)}d.each(c.defaults,function(h,i){if(e[h]!==undefined){f[h]=e[h]}})},remove:function(){d.data(this,c.datakey).related-=1},setup:function(){if(d.data(this,c.datakey)){return}var e=d.extend({related:0},c.defaults);d.data(this,c.datakey,e);b.add(this,"mousedown",c.init,e);if(this.attachEvent){this.attachEvent("ondragstart",c.dontstart)}},teardown:function(){if(d.data(this,c.datakey).related){return}d.removeData(this,c.datakey);b.remove(this,"mousedown",c.init);b.remove(this,"draginit",c.delegate);c.textselect(true);if(this.detachEvent){this.detachEvent("ondragstart",c.dontstart)}},init:function(g){var e=g.data,f;if(e.which>0&&g.which!=e.which){return}if(d(g.target).is(e.not)){return}if(e.handle&&!d(g.target).closest(e.handle,g.currentTarget).length){return}e.propagates=1;e.interactions=[c.interaction(this,e)];e.target=g.target;e.pageX=g.pageX;e.pageY=g.pageY;e.dragging=null;f=c.hijack(g,"draginit",e);if(!e.propagates){return}f=c.flatten(f);if(f&&f.length){e.interactions=[];d.each(f,function(){e.interactions.push(c.interaction(this,e))})}e.propagates=e.interactions.length;if(e.drop!==false&&a.drop){a.drop.handler(g,e)}c.textselect(false);b.add(document,"mousemove mouseup",c.handler,e);return false},interaction:function(f,e){return{drag:f,callback:new c.callback(),droppable:[],offset:d(f)[e.relative?"position":"offset"]()||{top:0,left:0}}},handler:function(f){var e=f.data;switch(f.type){case !e.dragging&&"mousemove":if(Math.pow(f.pageX-e.pageX,2)+Math.pow(f.pageY-e.pageY,2)<Math.pow(e.distance,2)){break}f.target=e.target;c.hijack(f,"dragstart",e);if(e.propagates){e.dragging=true}case"mousemove":if(e.dragging){c.hijack(f,"drag",e);if(e.propagates){if(e.drop!==false&&a.drop){a.drop.handler(f,e)}break}f.type="mouseup"}case"mouseup":b.remove(document,"mousemove mouseup",c.handler);if(e.dragging){if(e.drop!==false&&a.drop){a.drop.handler(f,e)}c.hijack(f,"dragend",e)}else{c.hijack(f,"dragclickonly",e)}c.textselect(true);if(e.click===false&&e.dragging){jQuery.event.triggered=true;setTimeout(function(){jQuery.event.triggered=false},20);e.dragging=false}break}},delegate:function(g){var e=[],h,f=d.data(this,"events")||{};d.each(f.live||[],function(j,k){if(k.preType.indexOf("drag")!==0){return}h=d(g.target).closest(k.selector,g.currentTarget)[0];if(!h){return}b.add(h,k.origType+"."+c.livekey,k.origHandler,k.data);if(d.inArray(h,e)<0){e.push(h)}});if(!e.length){return false}return d(e).bind("dragend."+c.livekey,function(){b.remove(this,"."+c.livekey)})},hijack:function(f,m,p,n,h){if(!p){return}var o={event:f.originalEvent,type:f.type},k=m.indexOf("drop")?"drag":"drop",r,j=n||0,g,e,q,l=!isNaN(n)?n:p.interactions.length;f.type=m;f.originalEvent=null;p.results=[];do{if(g=p.interactions[j]){if(m!=="dragend"&&g.cancelled){continue}q=c.properties(f,p,g);g.results=[];d(h||g[k]||p.droppable).each(function(s,i){q.target=i;r=i?b.handle.call(i,f,q):null;if(r===false){if(k=="drag"){g.cancelled=true;p.propagates-=1}if(m=="drop"){g[k][s]=null}}else{if(m=="dropinit"){g.droppable.push(c.element(r)||i)}}if(m=="dragstart"){g.proxy=d(c.element(r)||g.drag)[0]}g.results.push(r);delete f.result;if(m!=="dropinit"){return r}});p.results[j]=c.flatten(g.results);if(m=="dropinit"){g.droppable=c.flatten(g.droppable)}if(m=="dragstart"&&!g.cancelled){q.update()}}}while(++j<l);f.type=o.type;f.originalEvent=o.event;return c.flatten(p.results)},properties:function(g,e,f){var h=f.callback;h.drag=f.drag;h.proxy=f.proxy||f.drag;h.startX=e.pageX;h.startY=e.pageY;h.deltaX=g.pageX-e.pageX;h.deltaY=g.pageY-e.pageY;h.originalX=f.offset.left;h.originalY=f.offset.top;h.offsetX=g.pageX-(e.pageX-h.originalX);h.offsetY=g.pageY-(e.pageY-h.originalY);h.drop=c.flatten((f.drop||[]).slice());h.available=c.flatten((f.droppable||[]).slice());return h},element:function(e){if(e&&(e.jquery||e.nodeType==1)){return e}},flatten:function(e){return d.map(e,function(f){return f&&f.jquery?d.makeArray(f):f&&f.length?c.flatten(f):f})},textselect:function(e){d(document)[e?"unbind":"bind"]("selectstart",c.dontstart).attr("unselectable",e?"off":"on").css("MozUserSelect",e?"":"none")},dontstart:function(){return false},callback:function(){}};c.callback.prototype={update:function(){if(a.drop&&this.available.length){d.each(this.available,function(e){a.drop.locate(this,e)})}}};a.draginit=a.dragstart=a.dragend=c})(jQuery); \ No newline at end of file +(function(d){d.fn.drag=function(j,f,i){var h=typeof j=="string"?j:"",g=d.isFunction(j)?j:d.isFunction(f)?f:null;if(h.indexOf("drag")!==0){h="drag"+h}i=(j==g?f:i)||{};return g?this.bind(h,i,g):this.trigger(h)};var b=d.event,a=b.special,c=a.drag={defaults:{which:1,distance:0,not:":input",handle:null,relative:false,drop:true,click:false},datakey:"dragdata",add:function(h){var g=d.data(this,c.datakey),f=h.data||{};g.related+=1;d.each(c.defaults,function(i,j){if(f[i]!==undefined){g[i]=f[i]}})},remove:function(){d.data(this,c.datakey).related-=1},setup:function(){if(d.data(this,c.datakey)){return}var f=d.extend({related:0},c.defaults);d.data(this,c.datakey,f);b.add(this,"touchstart mousedown",c.init,f);if(this.attachEvent){this.attachEvent("ondragstart",c.dontstart)}},teardown:function(){var f=d.data(this,c.datakey)||{};if(f.related){return}d.removeData(this,c.datakey);b.remove(this,"touchstart mousedown",c.init);c.textselect(true);if(this.detachEvent){this.detachEvent("ondragstart",c.dontstart)}},init:function(h){if(c.touched){return}var f=h.data,g;if(h.which!=0&&f.which>0&&h.which!=f.which){return}if(d(h.target).is(f.not)){return}if(f.handle&&!d(h.target).closest(f.handle,h.currentTarget).length){return}if(h.type=="touchstart"){c.touched=this;c.touchFix(h,f)}f.propagates=1;f.mousedown=this;f.interactions=[c.interaction(this,f)];f.target=h.target;f.pageX=h.pageX;f.pageY=h.pageY;f.dragging=null;g=c.hijack(h,"draginit",f);if(!f.propagates){return}g=c.flatten(g);if(g&&g.length){f.interactions=[];d.each(g,function(){f.interactions.push(c.interaction(this,f))})}f.propagates=f.interactions.length;if(f.drop!==false&&a.drop){a.drop.handler(h,f)}c.textselect(false);if(c.touched){b.add(c.touched,"touchmove touchend",c.handler,f)}else{b.add(document,"mousemove mouseup",c.handler,f)}if(!c.touched||f.live){return false}},touchFix:function(h,f){var j=h.originalEvent,g=0;if(j&&j.changedTouches){h.pageX=j.changedTouches[0].pageX;h.pageY=j.changedTouches[0].pageY}},interaction:function(g,f){var h=d(g)[f.relative?"position":"offset"]()||{top:0,left:0};return{drag:g,callback:new c.callback(),droppable:[],offset:h}},handler:function(g){var f=g.data;if(c.touched){c.touchFix(g,f)}switch(g.type){case !f.dragging&&"touchmove":g.preventDefault();case !f.dragging&&"mousemove":if(Math.pow(g.pageX-f.pageX,2)+Math.pow(g.pageY-f.pageY,2)<Math.pow(f.distance,2)){break}g.target=f.target;c.hijack(g,"dragstart",f);if(f.propagates){f.dragging=true}case"touchmove":g.preventDefault();case"mousemove":if(f.dragging){c.hijack(g,"drag",f);if(f.propagates){if(f.drop!==false&&a.drop){a.drop.handler(g,f)}break}g.type="mouseup"}case"touchend":case"mouseup":if(c.touched){b.remove(c.touched,"touchmove touchend",c.handler)}else{b.remove(document,"mousemove mouseup",c.handler)}if(f.dragging){if(f.drop!==false&&a.drop){a.drop.handler(g,f)}c.hijack(g,"dragend",f)}else{c.hijack(g,"dragclickonly",f)}c.textselect(true);if(f.click===false&&f.dragging){d.data(f.mousedown,"suppress.click",new Date().getTime()+5)}f.dragging=c.touched=false;break}},hijack:function(g,n,q,o,j){if(!q){return}var p={event:g.originalEvent,type:g.type},l=n.indexOf("drop")?"drag":"drop",s,k=o||0,h,f,r,m=!isNaN(o)?o:q.interactions.length;g.type=n;g.originalEvent=null;q.results=[];do{if(h=q.interactions[k]){if(n!=="dragend"&&h.cancelled){continue}r=c.properties(g,q,h);h.results=[];d(j||h[l]||q.droppable).each(function(t,i){r.target=i;s=i?b.handle.call(i,g,r):null;if(s===false){if(l=="drag"){h.cancelled=true;q.propagates-=1}if(n=="drop"){h[l][t]=null}}else{if(n=="dropinit"){h.droppable.push(c.element(s)||i)}}if(n=="dragstart"){h.proxy=d(c.element(s)||h.drag)[0]}h.results.push(s);delete g.result;if(n!=="dropinit"){return s}});q.results[k]=c.flatten(h.results);if(n=="dropinit"){h.droppable=c.flatten(h.droppable)}if(n=="dragstart"&&!h.cancelled){r.update()}}}while(++k<m);g.type=p.type;g.originalEvent=p.event;return c.flatten(q.results)},properties:function(h,f,g){var i=g.callback;i.drag=g.drag;i.proxy=g.proxy||g.drag;i.startX=f.pageX;i.startY=f.pageY;i.deltaX=h.pageX-f.pageX;i.deltaY=h.pageY-f.pageY;i.originalX=g.offset.left;i.originalY=g.offset.top;i.offsetX=i.originalX+i.deltaX;i.offsetY=i.originalY+i.deltaY;i.drop=c.flatten((g.drop||[]).slice());i.available=c.flatten((g.droppable||[]).slice());return i},element:function(f){if(f&&(f.jquery||f.nodeType==1)){return f}},flatten:function(f){return d.map(f,function(g){return g&&g.jquery?d.makeArray(g):g&&g.length?c.flatten(g):g})},textselect:function(f){d(document)[f?"unbind":"bind"]("selectstart",c.dontstart).css("MozUserSelect",f?"":"none");document.unselectable=f?"off":"on"},dontstart:function(){return false},callback:function(){}};c.callback.prototype={update:function(){if(a.drop&&this.available.length){d.each(this.available,function(f){a.drop.locate(this,f)})}}};var e=b.handle;b.handle=function(f){if(d.data(this,"suppress."+f.type)-new Date().getTime()>0){d.removeData(this,"suppress."+f.type);return}return e.apply(this,arguments)};a.draginit=a.dragstart=a.dragend=c})(jQuery); \ No newline at end of file --- a/static/scripts/packed/trackster.js Thu Mar 24 15:03:12 2011 -0400 +++ b/static/scripts/packed/trackster.js Thu Mar 24 15:05:28 2011 -0400 @@ -1,1 +1,1 @@ -CanvasRenderingContext2D.prototype.dashedLine=function(c,j,b,h,f){if(f===undefined){f=4}var e=b-c;var d=h-j;var g=Math.floor(Math.sqrt(e*e+d*d)/f);var l=e/g;var k=d/g;var a;for(a=0;a<g;a++,c+=l,j+=k){if(a%2!==0){continue}this.fillRect(c,j,f,1)}};CanvasRenderingContext2D.prototype.drawDownwardEquilateralTriangle=function(b,a,e){var d=b-e/2,c=b+e/2,f=a-Math.sqrt(e*3/2);this.beginPath();this.moveTo(d,f);this.lineTo(c,f);this.lineTo(b,a);this.lineTo(d,f);this.strokeStyle=this.fillStyle;this.fill();this.stroke();this.closePath()};function sortable(a,b){a.bind("drag",{handle:b,relative:true},function(h,j){var g=$(this).parent();var f=g.children();var c;for(c=0;c<f.length;c++){if(j.offsetY<$(f.get(c)).position().top){break}}if(c===f.length){if(this!==f.get(c-1)){g.append(this)}}else{if(this!==f.get(c)){$(this).insertBefore(f.get(c))}}})}var NO_OVERLAP=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005;function compute_overlap(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=NO_OVERLAP}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=NO_OVERLAP}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a}function is_overlap(b,a){return(compute_overlap(b,a)!==NO_OVERLAP)}var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=1,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,ERROR_PADDING=10,LABEL_SPACING=2,PACK_SPACING=5,MIN_SQUISH_VIEW_WIDTH=12000,DEFAULT_FONT="9px Monaco, Lucida Console, monospace",DENSITY=200,FEATURE_LEVELS=10,MAX_FEATURE_DEPTH=100,DEFAULT_DATA_QUERY_WAIT=5000,MAX_CHROMS_SELECTABLE=100,CONNECTOR_COLOR="#ccc",DATA_ERROR="There was an error in indexing this dataset. ",DATA_NOCONVERTER="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",DATA_NONE="No data for this chrom/contig.",DATA_PENDING="Currently indexing... please wait",DATA_CANNOT_RUN_TOOL="Tool cannot be rerun: ",DATA_LOADING="Loading data...",DATA_OK="Ready for display",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=5,CACHED_DATA=5,DUMMY_CANVAS=document.createElement("canvas"),RIGHT_STRAND,LEFT_STRAND;if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(DUMMY_CANVAS)}var CONTEXT=DUMMY_CANVAS.getContext("2d");CONTEXT.font=DEFAULT_FONT;var CHAR_WIDTH_PX=CONTEXT.measureText("A").width,CHAR_HEIGHT_PX=9;var right_img=new Image();right_img.src=image_path+"/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var left_img=new Image();left_img.src=image_path+"/visualization/strand_left.png";left_img.onload=function(){LEFT_STRAND=CONTEXT.createPattern(left_img,"repeat")};var right_img_inv=new Image();right_img_inv.src=image_path+"/visualization/strand_right_inv.png";right_img_inv.onload=function(){RIGHT_STRAND_INV=CONTEXT.createPattern(right_img_inv,"repeat")};var left_img_inv=new Image();left_img_inv.src=image_path+"/visualization/strand_left_inv.png";left_img_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};function round_1000(a){return Math.round(a*1000)/1000}var Cache=function(a){this.num_elements=a;this.clear()};$.extend(Cache.prototype,{get:function(b){var a=this.key_ary.indexOf(b);if(a!==-1){this.move_key_to_end(b,a)}return this.obj_cache[b]},set:function(b,c){if(!this.obj_cache[b]){if(this.key_ary.length>=this.num_elements){var a=this.key_ary.shift();delete this.obj_cache[a]}this.key_ary.push(b)}this.obj_cache[b]=c;return c},move_key_to_end:function(b,a){this.key_ary.splice(a,1);this.key_ary.push(b)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var DataCache=function(a){Cache.call(this,a)};$.extend(DataCache.prototype,Cache.prototype,{get_data:function(g,b,e){var h=this.get(this.gen_key(g,b,e));if(h){return h}var j,f,a,d,e,h;for(var c=0;c<this.key_ary.length;c++){j=this.key_ary[c];f=this.split_key(j);a=f[0];d=f[1];if(g>=a&&b<=d){h=this.obj_cache[j];if(h.dataset_type!=="summary_tree"&&h.extra_info!=="no_detail"){this.move_key_to_end(j,c);return h}}}return undefined},set_data:function(b,c,d,a){return this.set(this.gen_key(b,c,d),a)},gen_key:function(a,c,d){var b=a+"_"+c+"_"+d;return b},split_key:function(a){return a.split("_")}});var View=function(a,d,c,b,e){this.container=a;this.chrom=null;this.vis_id=c;this.dbkey=b;this.title=d;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init(e);this.reset()};$.extend(View.prototype,{init:function(d){var c=this.container,a=this;this.top_container=$("<div/>").addClass("top-container").appendTo(c);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(c);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(c);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").text("Select a chrom from the dropdown below").hide();this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var b=function(f){if(f.type==="focusout"||(f.keyCode||f.which)===13||(f.keyCode||f.which)===27){if((f.keyCode||f.which)!==27){a.go_to($(this).val())}$(this).hide();a.location_span.show();a.chrom_select.show();return false}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",b).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.bind("click",function(){a.location_span.hide();a.chrom_select.hide();a.nav_input.css("display","inline-block");a.nav_input.select();a.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a id='zoom-out' />").click(function(){a.zoom_out();a.redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){a.zoom_in();a.redraw()}).appendTo(this.nav_controls);this.load_chroms({low:0},d);this.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())});this.intro_div.show();this.content_div.bind("click",function(f){$(this).find("input").trigger("blur")});this.content_div.bind("dblclick",function(f){a.zoom_in(f.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(f,g){this.current_x=g.offsetX}).bind("drag",function(f,h){var j=h.offsetX-this.current_x;this.current_x=h.offsetX;var g=Math.round(j/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-g)});this.overview_close.bind("click",function(){for(var f=0,e=a.tracks.length;f<e;f++){a.tracks[f].is_overview=false}$(this).siblings().filter("canvas").remove();$(this).parent().css("height",a.overview_box.height());a.overview_highlight.hide();$(this).hide()});this.viewport_container.bind("draginit",function(f,g){if(f.clientX>a.viewport_container.width()-16){return false}}).bind("dragstart",function(f,g){g.original_low=a.low;g.current_height=f.clientY;g.current_x=g.offsetX}).bind("drag",function(h,k){var f=$(this);var l=k.offsetX-k.current_x;var g=f.scrollTop()-(h.clientY-k.current_height);f.scrollTop(g);k.current_height=h.clientY;k.current_x=k.offsetX;var j=Math.round(l/a.viewport_container.width()*(a.high-a.low));a.move_delta(j)}).bind("mousewheel",function(h,k,g,f){if(g){var j=Math.round(-g/a.viewport_container.width()*(a.high-a.low));a.move_delta(j)}});this.top_labeltrack.bind("dragstart",function(f,g){return $("<div />").css({height:a.content_div.height()+a.top_labeltrack.height()+a.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(k,l){$(l.proxy).css({left:Math.min(k.pageX,l.startX),width:Math.abs(k.pageX-l.startX)});var g=Math.min(k.pageX,l.startX)-a.container.offset().left,f=Math.max(k.pageX,l.startX)-a.container.offset().left,j=(a.high-a.low),h=a.viewport_container.width();a.update_location(Math.round(g/h*j)+a.low,Math.round(f/h*j)+a.low)}).bind("dragend",function(l,m){var g=Math.min(l.pageX,m.startX),f=Math.max(l.pageX,m.startX),j=(a.high-a.low),h=a.viewport_container.width(),k=a.low;a.low=Math.round(g/h*j)+k;a.high=Math.round(f/h*j)+k;$(m.proxy).remove();a.redraw()});this.add_label_track(new LabelTrack(this,this.top_labeltrack));this.add_label_track(new LabelTrack(this,this.nav_labeltrack));$(window).bind("resize",function(){a.resize_window()});$(document).bind("redraw",function(){a.redraw()});this.reset();$(window).trigger("resize")},update_location:function(a,b){this.location_span.text(commatize(a)+" - "+commatize(b));this.nav_input.val(this.chrom+":"+commatize(a)+"-"+commatize(b))},load_chroms:function(b,c){b.num=MAX_CHROMS_SELECTABLE;$.extend(b,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var a=this;$.ajax({url:chrom_url,data:b,dataType:"json",success:function(e){if(e.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=e.chrom_info;var h='<option value="">Select Chrom/Contig</option>';for(var g=0,d=a.chrom_data.length;g<d;g++){var f=a.chrom_data[g].chrom;h+='<option value="'+f+'">'+f+"</option>"}if(e.prev_chroms){h+='<option value="previous">Previous '+MAX_CHROMS_SELECTABLE+"</option>"}if(e.next_chroms){h+='<option value="next">Next '+MAX_CHROMS_SELECTABLE+"</option>"}a.chrom_select.html(h);if(c){c()}a.chrom_start_index=e.start_index},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}})},change_chrom:function(e,b,g){if(!e||e==="None"){return}var d=this;if(e==="previous"){d.load_chroms({low:this.chrom_start_index-MAX_CHROMS_SELECTABLE});return}if(e==="next"){d.load_chroms({low:this.chrom_start_index+MAX_CHROMS_SELECTABLE});return}var f=$.grep(d.chrom_data,function(j,k){return j.chrom===e})[0];if(f===undefined){d.load_chroms({chrom:e},function(){d.change_chrom(e,b,g)});return}else{if(e!==d.chrom){d.chrom=e;if(!d.chrom){d.intro_div.show()}else{d.intro_div.hide()}d.chrom_select.val(d.chrom);d.max_high=f.len-1;d.reset();d.redraw(true);for(var h=0,a=d.tracks.length;h<a;h++){var c=d.tracks[h];if(c.init){c.init()}}}if(b!==undefined&&g!==undefined){d.low=Math.max(b,0);d.high=Math.min(g,d.max_high)}d.reset_overview();d.redraw()}},go_to:function(f){var k=this,a,d,b=f.split(":"),h=b[0],j=b[1];if(j!==undefined){try{var g=j.split("-");a=parseInt(g[0].replace(/,/g,""),10);d=parseInt(g[1].replace(/,/g,""),10)}catch(c){return false}}k.change_chrom(h,a,d)},move_fraction:function(c){var a=this;var b=a.high-a.low;this.move_delta(c*b)},move_delta:function(c){var a=this;var b=a.high-a.low;if(a.low-c<a.max_low){a.low=a.max_low;a.high=a.max_low+b}else{if(a.high-c>a.max_high){a.high=a.max_high;a.low=a.max_high-b}else{a.high-=c;a.low-=c}}a.redraw()},add_track:function(a){a.view=this;a.track_id=this.track_id_counter;this.tracks.push(a);if(a.init){a.init()}a.container_div.attr("id","track_"+a.track_id);sortable(a.container_div,".draghandle");this.track_id_counter+=1;this.num_tracks+=1},add_label_track:function(a){a.view=this;this.label_tracks.push(a)},remove_track:function(a){this.has_changes=true;a.container_div.fadeOut("slow",function(){$(this).remove()});delete this.tracks[this.tracks.indexOf(a)];this.num_tracks-=1},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},redraw:function(h){var g=this.high-this.low,f=this.low,b=this.high;if(f<this.max_low){f=this.max_low}if(b>this.max_high){b=this.max_high}if(this.high!==0&&g<this.min_separation){b=f+this.min_separation}this.low=Math.floor(f);this.high=Math.ceil(b);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low)/200)/Math.LN10));this.zoom_res=Math.pow(FEATURE_LEVELS,Math.max(0,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS))));var a=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var e=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var j=13;this.overview_box.css({left:a,width:Math.max(j,e)}).show();if(e<j){this.overview_box.css("left",a-(j-e)/2)}if(this.overview_highlight){this.overview_highlight.css({left:a,width:e})}this.update_location(this.low,this.high);if(!h){for(var c=0,d=this.tracks.length;c<d;c++){if(this.tracks[c]&&this.tracks[c].enabled){this.tracks[c].draw()}}for(c=0,d=this.label_tracks.length;c<d;c++){this.label_tracks[c].draw()}}},zoom_in:function(b,c){if(this.max_high===0||this.high-this.low<this.min_separation){return}var d=this.high-this.low,e=d/2+this.low,a=(d/this.zoom_factor)/2;if(b){e=b/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(e-a);this.high=Math.round(e+a);this.redraw()},zoom_out:function(){if(this.max_high===0){return}var b=this.high-this.low,c=b/2+this.low,a=(b*this.zoom_factor)/2;this.low=Math.round(c-a);this.high=Math.round(c+a);this.redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.redraw()},reset_overview:function(){this.overview_viewport.find("canvas").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide()}});var Tool=function(a,b){this.name=a;this.params=b};$.extend(Tool.prototype,{get_param_values_dict:function(){var b={};for(var a=0;a<this.params.length;a++){var c=this.params[a];b[c.name]=c.value}return b},get_param_values:function(){var b=[];for(var a=0;a<this.params.length;a++){b[a]=this.params[a].value}return b}});var NumberToolParameter=function(c,b,e,a,d){this.name=c;this.label=b;this.min=e;this.max=a;this.value=d};var get_tool_from_dict=function(f){if(obj_length(f)===0){return undefined}var b=f.name;var l=f.params;var c=Array();for(var e=0;e<l.length;e++){var g=l[e];var a=g.name,k=g.label,h=g.type,d=g.min,j=g.max,m=g.value;c[c.length]=new NumberToolParameter(a,k,d,j,m)}return new Tool(b,c)};var Filter=function(b,a,c){this.name=b;this.index=a;this.value=c};var NumberFilter=function(b,a){this.name=b;this.index=a;this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.slider_min=Number.MAX_VALUE;this.slider_max=-Number.MAX_VALUE;this.slider=null;this.slider_label=null};$.extend(NumberFilter.prototype,{applies_to:function(a){if(a.length>this.index){return true}return false},keep:function(a){if(!this.applies_to(a)){return true}return(a[this.index]>=this.low&&a[this.index]<=this.high)},update_attrs:function(b){var a=false;if(!this.applies_to(b)){return a}if(b[this.index]<this.slider_min){this.slider_min=b[this.index];a=true}if(b[this.index]>this.slider_max){this.slider_max=b[this.index];a=false}return a},update_ui_elt:function(){var b=this.slider.slider("option","min"),a=this.slider.slider("option","max");if(this.slider_min<b||this.slider_max>a){this.slider.slider("option","min",this.slider_min);this.slider.slider("option","max",this.slider_max);this.slider.slider("option","values",[this.slider_min,this.slider_max])}}});var get_filters_from_dict=function(a){var g=[];for(var d=0;d<a.length;d++){var f=a[d];var c=f.name,e=f.type,b=f.index;if(e==="int"||e==="float"){g[d]=new NumberFilter(c,b)}else{g[d]=new Filter(c,b,e)}}return g};var TrackConfig=function(a){this.track=a.track;this.params=a.params;this.values={};if(a.saved_values){this.restore_values(a.saved_values)}this.onchange=a.onchange};$.extend(TrackConfig.prototype,{restore_values:function(a){var b=this;$.each(this.params,function(c,d){if(a[d.key]!==undefined){b.values[d.key]=a[d.key]}else{b.values[d.key]=d.default_value}})},build_form:function(){var b=this;var a=$("<div />");$.each(this.params,function(f,d){if(!d.hidden){var c="param_"+f;var l=$("<div class='form-row' />").appendTo(a);l.append($("<label />").attr("for",c).text(d.label+":"));if(d.type==="bool"){l.append($('<input type="checkbox" />').attr("id",c).attr("name",c).attr("checked",b.values[d.key]))}else{if(d.type==="color"){var h=b.values[d.key];var g=$("<input />").attr("id",c).attr("name",c).val(h);var j=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var e=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(j);var k=$("<div/>").appendTo(e).farbtastic({width:100,height:100,callback:g,color:h});$("<div />").append(g).append(j).appendTo(l).bind("click",function(m){j.css({left:$(this).position().left+($(g).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){j.hide();$(document).unbind("click.color-picker")});m.stopPropagation()})}else{l.append($("<input />").attr("id",c).attr("name",c).val(b.values[d.key]))}}}});return a},update_from_form:function(a){var c=this;var b=false;$.each(this.params,function(d,f){if(!f.hidden){var g="param_"+d;var e=a.find("#"+g).val();if(f.type==="float"){e=parseFloat(e)}else{if(f.type==="int"){e=parseInt(e)}else{if(f.type==="bool"){e=a.find("#"+g).is(":checked")}}}if(e!==c.values[f.key]){c.values[f.key]=e;b=true}}});if(b){this.onchange()}}});var Track=function(b,a,e,c,d){this.name=b;this.view=a;this.parent_element=e;this.data_url=(c?c:default_data_url);this.data_query_wait=(d?d:DEFAULT_DATA_QUERY_WAIT);this.dataset_check_url=converted_datasets_state_url;this.container_div=$("<div />").addClass("track").css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div class='draghandle' />").appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)};$.extend(Track.prototype,{init:function(){var a=this;a.enabled=false;a.tile_cache.clear();a.data_cache.clear();a.initial_canvas=undefined;a.content_div.css("height","auto");a.container_div.removeClass("nodata error pending");if(!a.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:a.hda_ldda,dataset_id:a.dataset_id,chrom:a.view.chrom},function(b){if(!b||b==="error"||b.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(b.message){var d=a.view.tracks.indexOf(a);var c=$(" <a href='javascript:void(0);'></a>").text("View error").bind("click",function(){show_modal("Trackster Error","<pre>"+b.message+"</pre>",{Close:hide_modal})});a.content_div.append(c)}}else{if(b==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(b==="no data"||(b.data!==undefined&&(b.data===null||b.data.length===0))){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(b==="pending"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},a.data_query_wait)}else{if(b.status==="data"){if(b.valid_chroms){a.valid_chroms=b.valid_chroms;a.make_name_popup_menu()}a.content_div.text(DATA_OK);if(a.view.chrom){a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;$.when(a.predraw_init()).done(function(){a.draw()})}}}}}}})},predraw_init:function(){},update_name:function(a){this.old_name=this.name;this.name=a;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)}});var TiledTrack=function(b,j,n){var c=this,o=c.view;this.filters=(b!==undefined?get_filters_from_dict(b):[]);this.filters_available=false;this.filters_visible=false;this.tool=(j!==undefined?get_tool_from_dict(j):undefined);this.parent_track=n;this.child_tracks=[];if(c.hidden){return}if(this.parent_track){this.header_div.find(".draghandle").removeClass("draghandle").addClass("child-track-icon").addClass("icon-button");this.parent_element.addClass("child-track");this.tool=undefined}this.filters_div=$("<div/>").addClass("filters").hide();this.header_div.after(this.filters_div);this.filters_div.bind("drag",function(q){q.stopPropagation()}).bind("dblclick",function(q){q.stopPropagation()});$.each(this.filters,function(t,w){var u=$("<div/>").addClass("slider-row").appendTo(c.filters_div);var v=$("<div/>").addClass("slider-label").appendTo(u);var s=$("<span/>").addClass("name").appendTo(v);s.text(w.name+" ");var r=$("<span/>").addClass("values").appendTo(v);var q=$("<div/>").addClass("slider").appendTo(u);w.control_element=$("<div/>").attr("id",w.name+"-filter-control").appendTo(q);w.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(y,z){var x=z.values;r.text("["+x[0]+"-"+x[1]+"]");w.low=x[0];w.high=x[1];c.draw(true,true)},change:function(x,y){w.control_element.slider("option","slide").call(w.control_element,x,y)}});w.slider=w.control_element;w.slider_label=r;$("<div style='clear: both;'/>").appendTo(u)});if(this.tool){this.dynamic_tool_div=$("<div/>").addClass("dynamic-tool").hide();this.header_div.after(this.dynamic_tool_div);this.dynamic_tool_div.bind("drag",function(q){q.stopPropagation()}).bind("click",function(q){q.stopPropagation()}).bind("dblclick",function(q){q.stopPropagation()});var m=$("<div class='tool-name'>").appendTo(this.dynamic_tool_div).text(this.tool.name);var l=this.tool.params;var c=this;$.each(this.tool.params,function(x,s){var v=$("<div>").addClass("slider-row").appendTo(c.dynamic_tool_div);var u=$("<div>").addClass("slider-label").appendTo(v);var z=$("<span class='param-name'>").text(s.label+" ").appendTo(u);var t=$("<span/>").text(s.value);var w=$("<span class='param-value'>").appendTo(u).append("[").append(t).append("]");var y=$("<div/>").addClass("slider").appendTo(v);var q=$("<div id='"+s.name+"-param-control'>").appendTo(y);var r=(s.max<=1?0.01:(s.max<=1000?1:5));q.slider({min:s.min,max:s.max,step:r,value:s.value,slide:function(A,C){var B=C.value;s.value=B;if(0<B&&B<1){B=parseFloat(B).toFixed(2)}t.text(B)},change:function(A,B){s.value=B.value}});w.click(function(){var C=t,B=C.text(),A=(s.max<=1?4:s.max.length);C.text("");$("<input type='text'/>").attr("size",A).attr("maxlength",A).attr("value",B).appendTo(C).focus().select().click(function(D){D.stopPropagation()}).blur(function(){$(this).remove();C.text(B)}).keyup(function(F){if(F.keyCode===27){$(this).trigger("blur")}else{if(F.keyCode===13){var D=$(this),E=parseFloat(D.val());if(isNaN(E)||E>s.max||E<s.min){alert("Parameter value must be in the range ["+s.min+"-"+s.max+"]");return $(this)}C.text(E);q.slider("value",E);s.value=E}}})});$("<div style='clear: both;'/>").appendTo(v)});var p=$("<div>").addClass("slider-row").appendTo(this.dynamic_tool_div);var k=$("<input type='submit'>").attr("value","Run").appendTo(p);var c=this;k.click(function(){c.run_tool()})}c.child_tracks_container=$("<div/>").addClass("child-tracks-container").hide();c.container_div.append(c.child_tracks_container);if(c.display_modes!==undefined){if(c.mode_div===undefined){c.mode_div=$("<div class='right-float menubutton popup' />").appendTo(c.header_div);var e=(c.track_config&&c.track_config.values.mode?c.track_config.values.mode:c.display_modes[0]);c.mode=e;c.mode_div.text(e);var d=function(q){c.mode_div.text(q);c.mode=q;c.track_config.values.mode=q;c.tile_cache.clear();c.draw()};var a={};for(var f=0,h=c.display_modes.length;f<h;f++){var g=c.display_modes[f];a[g]=function(q){return function(){d(q)}}(g)}make_popupmenu(c.mode_div,a)}else{c.mode_div.hide()}}this.make_name_popup_menu()};$.extend(TiledTrack.prototype,Track.prototype,{make_name_popup_menu:function(){var b=this;var a={};a["Edit configuration"]=function(){var h=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},f=function(){b.track_config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},g=function(j){if((j.keyCode||j.which)===27){h()}else{if((j.keyCode||j.which)===13){f()}}};$(window).bind("keypress.check_enter_esc",g);show_modal("Configure Track",b.track_config.build_form(),{Cancel:h,OK:f})};if(b.filters_available>0){var e=(b.filters_div.is(":visible")?"Hide filters":"Show filters");a[e]=function(){b.filters_visible=(b.filters_div.is(":visible"));b.filters_div.toggle();b.make_name_popup_menu()}}if(b.tool){var e=(b.dynamic_tool_div.is(":visible")?"Hide Tool":"Show Tool");a[e]=function(){if(!b.dynamic_tool_div.is(":visible")){b.update_name(b.name+b.tool_region_and_parameters_str())}else{menu_option_text="Show dynamic tool";b.revert_name()}b.dynamic_tool_div.toggle();b.make_name_popup_menu()}}if(b.track_type=="ReadTrack"){var e=(b.show_insertions?"Hide Insertions":"Show Insertions");a[e]=function(){b.show_insertions=!b.show_insertions;b.draw(true);b.make_name_popup_menu()}}if(b.valid_chroms){a["List chrom/contigs with data"]=function(){show_modal("Chrom/contigs with data","<p>"+b.valid_chroms.join("<br/>")+"</p>",{Close:function(){hide_modal()}})}}var c=view;var d=function(){$("#no-tracks").show()};if(this.parent_track){c=this.parent_track;d=function(){}}a.Remove=function(){c.remove_track(b);if(c.num_tracks===0){d()}};make_popupmenu(b.name_div,a)},tile_data:function(d,a,g,k,j){var b=this,h=a*DENSITY*d,f=(a+1)*DENSITY*d,e={chrom:this.view.chrom,low:h,high:f,dbkey:this.view.dbkey};if(j===undefined){j=d+"_"+a}var c=b.data_cache.get(j);if(c){return k(c)}$.extend(e,g);$.ajax({url:this.data_url,dataType:"json",data:e,success:function(l){b.data_cache.set(j,l);return k(l)},error:function(m,l,n){console.log(m,l,n)}})},draw:function(a,d){var s=this.view.low,g=this.view.high,j=g-s,l=this.view.container.width(),m=this.view.resolution;var e=$("<div style='position: relative;'></div>"),f=l/j;if(!d){this.content_div.children().remove()}this.content_div.append(e);this.max_height=0;var o=Math.floor(s/m/DENSITY);var c={};while((o*DENSITY*m)<g){var r=l+"_"+f+"_"+o;var h=this.tile_cache.get(r);var p=o*DENSITY*this.view.resolution;var b=p+DENSITY*this.view.resolution;if(!a&&h){this.show_tile(h,e,p,f)}else{this.delayed_draw(a,r,p,b,o,m,e,f,c)}o+=1}if(d){var k=this;var q=setInterval(function(){if(obj_length(c)===0){var v=k.content_div.children();var u=false;for(var w=v.length-1,t=0;w>=t;w--){var x=$(v[w]);if(u){x.remove()}else{if(x.children().length!==0){u=true}}}clearInterval(q)}},50)}for(var n=0;n<this.child_tracks.length;n++){this.child_tracks[n].draw(a,d)}},delayed_draw:function(b,j,h,l,c,e,k,m,f){var d=this;var g=function(n){d.tile_cache.set(j,n);d.show_tile(n,k,h,m)};var a=setTimeout(function(){if(h<=d.view.high&&l>=d.view.low){var n;if(!b){n=d.tile_cache.get(j)}if(!n){d.draw_tile(e,c,k,m,function(p){if(p){var o=$("<div class='track-tile'>").prepend(p);n=o}g(n)})}if(n){g(n)}}delete f[a]},50);f[a]=true},show_tile:function(h,j,e,k){var a=this;var c=this.view.high-this.view.low,b=(e-this.view.low)*k;if(this.left_offset){b-=this.left_offset}h.css({position:"absolute",top:0,left:b,height:""});j.append(h);a.max_height=Math.max(a.max_height,h.height());a.content_div.css("height",a.max_height+"px");j.children().css("height",a.max_height+"px");if(a.hidden){return}for(var g=0;g<a.filters.length;g++){a.filters[g].update_ui_elt()}var d=false;if(a.example_feature){for(var g=0;g<a.filters.length;g++){if(a.filters[g].applies_to(a.example_feature)){d=true;break}}}if(a.filters_available!==d){a.filters_available=d;if(!a.filters_available){a.filters_div.hide()}a.make_name_popup_menu()}},set_overview:function(){var a=this.view;if(this.initial_canvas&&this.is_overview){a.overview_close.show();a.overview_viewport.append(this.initial_canvas);a.overview_highlight.show().height(this.initial_canvas.height());a.overview_viewport.height(this.initial_canvas.height()+a.overview_box.height())}$(window).trigger("resize")},run_tool:function(){var b={dataset_id:this.original_dataset_id,chrom:this.view.chrom,low:this.view.low,high:this.view.high,tool_id:this.tool.name};$.extend(b,this.tool.get_param_values_dict());var d=this,c=b.tool_id+d.tool_region_and_parameters_str(b.chrom,b.low,b.high),e;if(d.track_type==="FeatureTrack"){e=new ToolDataFeatureTrack(c,view,d.hda_ldda,undefined,{},{},d)}this.add_track(e);e.content_div.text("Starting job.");view.has_changes=true;var a=function(){$.getJSON(run_tool_url,b,function(f){if(f==="no converter"){e.container_div.addClass("error");e.content_div.text(DATA_NOCONVERTER)}else{if(f.error){e.container_div.addClass("error");e.content_div.text(DATA_CANNOT_RUN_TOOL+f.message)}else{if(f==="pending"){e.container_div.addClass("pending");e.content_div.text("Converting input data so that it can be easily reused.");setTimeout(a,2000)}else{e.dataset_id=f.dataset_id;e.content_div.text("Running job.");e.init()}}}})};a()},tool_region_and_parameters_str:function(c,a,d){var b=this,e=(c!==undefined&&a!==undefined&&d!==undefined?c+":"+a+"-"+d:"all");return" - region=["+e+"], parameters=["+b.tool.get_param_values().join(", ")+"]"},add_track:function(a){a.track_id=this.track_id+"_"+this.child_tracks.length;a.container_div.attr("id","track_"+a.track_id);this.child_tracks_container.append(a.container_div);sortable(a.container_div,".child-track-icon");if(!$(this.child_tracks_container).is(":visible")){this.child_tracks_container.show()}this.child_tracks.push(a)},remove_track:function(a){a.container_div.fadeOut("slow",function(){$(this).remove()})}});var LabelTrack=function(a,b){this.track_type="LabelTrack";this.hidden=true;Track.call(this,null,a,b);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.view.container.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 ReferenceTrack=function(a){this.track_type="ReferenceTrack";this.hidden=true;Track.call(this,null,a,a.top_labeltrack);TiledTrack.call(this);a.reference_track=this;this.left_offset=200;this.height_px=12;this.font=DEFAULT_FONT;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url;this.data_cache=new DataCache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE)};$.extend(ReferenceTrack.prototype,TiledTrack.prototype,{draw_tile:function(c,b,e,g,f){var a=this,d=DENSITY*c;if(g>CHAR_WIDTH_PX){a.tile_data(c,b,{},function(j){if(j===null){a.content_div.css("height","0px");return}var k=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(k)}k=$(k);var h=k.get(0).getContext("2d");k.get(0).width=Math.ceil(d*g+a.left_offset);k.get(0).height=a.height_px;h.font=DEFAULT_FONT;h.textAlign="center";for(var n=0,l=j.length;n<l;n++){var m=Math.round(n*g);h.fillText(j[n],m+a.left_offset,10)}return f(k)})}this.content_div.css("height","0px")}});var LineTrack=function(e,c,f,a,d){var b=this;this.track_type="LineTrack";this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";Track.call(this,e,c,c.viewport_container);TiledTrack.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=f;this.dataset_id=a;this.original_dataset_id=a;this.data_cache=new DataCache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE);this.track_config=new TrackConfig({track:this,params:[{key:"color",label:"Color",type:"color",default_value:"black"},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.height_px,hidden:true}],saved_values:d,onchange:function(){b.vertical_range=b.prefs.max_value-b.prefs.min_value;$("#linetrack_"+b.track_id+"_minval").text(b.prefs.min_value);$("#linetrack_"+b.track_id+"_maxval").text(b.prefs.max_value);b.tile_cache.clear();b.draw()}});this.prefs=this.track_config.values;this.height_px=this.track_config.values.height;this.vertical_range=this.track_config.values.max_value-this.track_config.values.min_value;(function(g){var k=false;var j=false;var h=$("<div class='track-resize'>");$(g.container_div).hover(function(){k=true;h.show()},function(){k=false;if(!j){h.hide()}});h.hide().bind("dragstart",function(l,m){j=true;m.original_height=$(g.content_div).height()}).bind("drag",function(m,n){var l=Math.min(Math.max(n.original_height+n.deltaY,g.min_height_px),g.max_height_px);$(g.content_div).css("height",l);g.height_px=l;g.draw(true)}).bind("dragend",function(l,m){g.tile_cache.clear();j=false;if(!k){h.hide()}g.track_config.values.height=g.height_px}).appendTo(g.container_div)})(this)};$.extend(LineTrack.prototype,TiledTrack.prototype,{predraw_init:function(){var a=this,b=a.view.tracks.indexOf(a);a.vertical_range=undefined;return $.getJSON(a.data_url,{stats:true,chrom:a.view.chrom,low:null,high:null,hda_ldda:a.hda_ldda,dataset_id:a.dataset_id},function(c){a.container_div.addClass("line-track");var e=c.data;if(isNaN(parseFloat(a.prefs.min_value))||isNaN(parseFloat(a.prefs.max_value))){a.prefs.min_value=e.min;a.prefs.max_value=e.max;$("#track_"+b+"_minval").val(a.prefs.min_value);$("#track_"+b+"_maxval").val(a.prefs.max_value)}a.vertical_range=a.prefs.max_value-a.prefs.min_value;a.total_frequency=e.total_frequency;a.container_div.find(".yaxislabel").remove();var f=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(round_1000(a.prefs.min_value));var d=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(round_1000(a.prefs.max_value));d.css({position:"absolute",top:"24px",left:"10px"});d.prependTo(a.container_div);f.css({position:"absolute",bottom:"2px",left:"10px"});f.prependTo(a.container_div)})},draw_tile:function(d,a,j,k,h){if(this.vertical_range===undefined){return}var c=this,f=a*DENSITY*d,b=DENSITY*d,g=d+"_"+a,e={hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,resolution:this.view.resolution};this.tile_data(d,a,e,function(C){var l=document.createElement("canvas"),q=C.data;if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(l)}l=$(l);l.get(0).width=Math.ceil(b*k);l.get(0).height=c.height_px;var z=l.get(0).getContext("2d"),n=false,B=c.prefs.min_value,v=c.prefs.max_value,A=c.vertical_range,m=c.total_frequency,u=c.height_px,s=c.mode;var r=Math.round(u+B/A*u);z.beginPath();z.moveTo(0,r);z.lineTo(b*k,r);z.fillStyle="#aaa";z.stroke();z.beginPath();z.fillStyle=c.prefs.color;var p,w,x;if(q.length>1){x=Math.ceil((q[1][0]-q[0][0])*k)}else{x=10}for(var o=0,t=q.length;o<t;o++){p=Math.round((q[o][0]-f)*k);w=q[o][1];if(w===null){if(n&&s==="Filled"){z.lineTo(p,u)}n=false;continue}if(w<B){w=B}else{if(w>v){w=v}}if(s==="Histogram"){w=Math.round(w/A*u);z.fillRect(p,r,x,-w)}else{if(s==="Intensity"){w=255-Math.floor((w-B)/A*255);z.fillStyle="rgb("+w+","+w+","+w+")";z.fillRect(p,0,x,u)}else{w=Math.round(u-(w-B)/A*u);if(n){z.lineTo(p,w)}else{n=true;if(s==="Filled"){z.moveTo(p,u);z.lineTo(p,w)}else{z.moveTo(p,w)}}}}}if(s==="Filled"){if(n){z.lineTo(p,r);z.lineTo(0,r)}z.fill()}else{z.stroke()}h(l)})}});var FeatureTrack=function(a,f,e,j,h,c,d,g){var b=this;this.track_type="FeatureTrack";this.display_modes=["Auto","Dense","Squish","Pack"];this.track_config=new TrackConfig({track:this,params:[{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:h,onchange:function(){b.tile_cache.clear();b.draw()}});this.prefs=this.track_config.values;Track.call(this,a,f,f.viewport_container);TiledTrack.call(this,c,d,g);this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=e;this.dataset_id=j;this.original_dataset_id=j;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.default_font=DEFAULT_FONT;this.inc_slots={};this.start_end_dct={};this.tile_cache=new Cache(CACHED_TILES_FEATURE);this.data_cache=new DataCache(20);this.left_offset=200};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{incremental_slots:function(a,h,p){var q=this.inc_slots[a];if(!q||(q.mode!==p)){q={};q.w_scale=a;q.mode=p;this.inc_slots[a]=q;this.start_end_dct[a]={}}var l=q.w_scale,w=[],x=[],j=0,n=this.view.max_low;for(var u=0,v=h.length;u<v;u++){var g=h[u],k=g[0];if(q[k]!==undefined){j=Math.max(j,q[k]);x.push(q[k])}else{w.push(u)}}var d=this.start_end_dct[a];var m=function(D,E){for(var C=0;C<=MAX_FEATURE_DEPTH;C++){var A=false,F=d[C];if(F!==undefined){for(var z=0,B=F.length;z<B;z++){var y=F[z];if(E>y[0]&&D<y[1]){A=true;break}}}if(!A){return C}}return -1};for(var u=0,v=w.length;u<v;u++){var g=h[w[u]],k=g[0],s=g[1],b=g[2],o=g[3],c=Math.floor((s-n)*l),f=Math.ceil((b-n)*l),t=CONTEXT.measureText(o).width,e;if(o!==undefined&&p==="Pack"){t+=(LABEL_SPACING+PACK_SPACING);if(c-t>=0){c-=t;e="left"}else{f+=t;e="right"}}var r=m(c,f);if(r>=0){if(d[r]===undefined){d[r]=[]}d[r].push([c,f]);q[k]=r;j=Math.max(j,r)}else{}}return j+1},draw_summary_tree:function(b,o,n,l,r,j,f,e){var c=j+LABEL_SPACING+CHAR_HEIGHT_PX;delta_x_px=Math.ceil(n*r);var h=$("<div />").addClass("yaxislabel");h.text(l);h.css({position:"absolute",top:"22px",left:"10px"});h.prependTo(this.container_div);var q=b.get(0).getContext("2d");for(var d=0,g=o.length;d<g;d++){var m=Math.floor((o[d][0]-f)*r);var k=o[d][1];if(!k){continue}var p=k/l*j;q.fillStyle="black";q.fillRect(m+e,c-p,delta_x_px,p);var a=4;if(this.prefs.show_counts&&(q.measureText(k).width+a)<delta_x_px){q.fillStyle="#666";q.textAlign="center";q.fillText(k,m+e+(delta_x_px/2),10)}}},draw_element:function(p,f,g,x,j,r,I,M,N,a,A){var u=x[0],K=x[1],C=x[2],s=x[3],D=Math.floor(Math.max(0,(K-r)*M)),q=Math.ceil(Math.min(a,Math.max(0,(C-r)*M))),B=ERROR_PADDING+(g==="Dense"?0:(0+j))*N,o,G,t=null,O=null,d=this.prefs.block_color,F=this.prefs.label_color;if(g==="Dense"){p.fillStyle=d;p.fillRect(D+A,B,q-D,DENSE_FEATURE_HEIGHT)}else{if(g==="no_detail"){p.fillStyle=d;p.fillRect(D+A,B+5,q-D,DENSE_FEATURE_HEIGHT)}else{var n=x[5],z=x[6],E=x[7],e=x[8];if(z&&E){t=Math.floor(Math.max(0,(z-r)*M));O=Math.ceil(Math.min(a,Math.max(0,(E-r)*M)))}var L,v;if(g==="Squish"){L=1;v=SQUISH_FEATURE_HEIGHT}else{L=5;v=PACK_FEATURE_HEIGHT}if(!e){if(x.strand){if(x.strand==="+"){p.fillStyle=RIGHT_STRAND_INV}else{if(x.strand==="-"){p.fillStyle=LEFT_STRAND_INV}}}else{p.fillStyle=d}p.fillRect(D+A,B,q-D,v)}else{var m,w;if(g==="Squish"){p.fillStyle=CONNECTOR_COLOR;m=B+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;w=1}else{if(n){var m=B;var w=v;if(n==="+"){p.fillStyle=RIGHT_STRAND}else{if(n==="-"){p.fillStyle=LEFT_STRAND}}}else{p.fillStyle=CONNECTOR_COLOR;m+=(SQUISH_FEATURE_HEIGHT/2)+1;w=1}}p.fillRect(D+A,m,q-D,w);for(var J=0,c=e.length;J<c;J++){var h=e[J],b=Math.floor(Math.max(0,(h[0]-r)*M)),y=Math.ceil(Math.min(a,Math.max((h[1]-r)*M)));if(b>y){continue}p.fillStyle=d;p.fillRect(b+A,B+(v-L)/2+1,y-b,L);if(t!==undefined&&!(b>O||y<t)){var H=Math.max(b,t),l=Math.min(y,O-1);p.fillRect(H+A,B+1,l-H,v)}}}if(g==="Pack"&&K>r){p.fillStyle=F;if(f===0&&D-p.measureText(s).width<0){p.textAlign="left";p.fillText(s,q+A+LABEL_SPACING,B+8)}else{p.textAlign="right";p.fillText(s,D+A-LABEL_SPACING,B+8)}p.fillStyle=d}}}},get_y_scale:function(b){var a;if(b==="summary_tree"){}if(b==="Dense"){a=DENSE_TRACK_HEIGHT}else{if(b==="no_detail"){a=NO_DETAIL_TRACK_HEIGHT}else{if(b==="Squish"){a=SQUISH_TRACK_HEIGHT}else{a=PACK_TRACK_HEIGHT}}}return a},draw_tile:function(z,E,l,n,j,d,p){var v=this;if(v.view.reference_track&&n>CHAR_WIDTH_PX&&d===undefined){return v.view.reference_track.tile_data(z,E,{},function(f){v.draw_tile(z,E,l,n,j,f)})}var G=E*DENSITY*z,a=(E+1)*DENSITY*z,s=a-G,H={hda_ldda:v.hda_ldda,dataset_id:v.dataset_id,resolution:this.view.resolution,mode:this.mode};if(p===undefined){var q=this.data_cache.get_data(G,a,this.mode),J=z+"_"+E+"_"+this.mode;if(q===undefined){return v.tile_data(z,E,H,function(f){v.data_cache.set_data(G,a,this.mode,f);v.draw_tile(z,E,l,n,j,d,f)},J)}p=q}var x=Math.ceil(s*n),u=this.mode,K=25,g=this.left_offset,r,h;var c=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(c)}c=$(c);if(u==="Auto"){if(p.dataset_type==="summary_tree"){u=p.dataset_type}else{if(p.extra_info==="no_detail"){u="no_detail"}else{var I=p.data;if((I.length&&I.length<4)||(this.view.high-this.view.low>MIN_SQUISH_VIEW_WIDTH)){u="Squish"}else{u="Pack"}}}}var A=this.get_y_scale(u);if(u==="summary_tree"){h=this.summary_draw_height}if(u==="Dense"){h=K}else{if(u==="no_detail"||u==="Squish"||u==="Pack"){h=this.incremental_slots(n,p.data,u)*A+K;r=this.inc_slots[n]}}c.get(0).width=x+g;c.get(0).height=h;if(p.dataset_type==="summary_tree"){c.get(0).height+=LABEL_SPACING+CHAR_HEIGHT_PX}l.parent().css("height",Math.max(this.height_px,h)+"px");var y=c.get(0).getContext("2d");y.fillStyle=this.prefs.block_color;y.font=this.default_font;y.textAlign="right";this.container_div.find(".yaxislabel").remove();if(u==="summary_tree"){this.draw_summary_tree(c,p.data,p.delta,p.max,n,h,G,g);return j(c)}if(p.message){c.css({"border-top":"1px solid red"});y.fillStyle="red";y.textAlign="left";var t=y.textBaseline;y.textBaseline="top";y.fillText(p.message,g,0);y.textBaseline=t;if(!p.data){return j(c)}}this.example_feature=(p.data.length?p.data[0]:undefined);var I=p.data;for(var B=0,D=I.length;B<D;B++){var k=I[B],m=k[0],w=k[1],b=k[2],e=(r&&r[m]!==undefined?r[m]:null);var C=false;var o;for(var F=0;F<this.filters.length;F++){o=this.filters[F];o.update_attrs(k);if(!o.keep(k)){C=true;break}}if(C){continue}if(is_overlap([w,b],[G,a])&&(u=="Dense"||e!==null)){this.draw_element(y,E,u,k,e,G,a,n,A,x,g,d)}}j(c)}});var VcfTrack=function(d,b,f,a,c,e){FeatureTrack.call(this,d,b,f,a,c,e);this.track_type="VcfTrack"};$.extend(VcfTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{draw_element:function(u,p,j,e,x,c,m,v,s){var j=data[i],l=j[0],t=j[1],d=j[2]-1,o=j[3],g=Math.floor(Math.max(0,(t-x)*m)),k=Math.ceil(Math.min(s,Math.max(0,(d-x)*m))),f=ERROR_PADDING+(p==="Dense"?0:(0+e))*v,a,y,b=null,n=null;if(no_label){u.fillStyle=block_color;u.fillRect(g+left_offset,f+5,k-g,1)}else{var w=j[4],r=j[5],h=j[6];a=9;y=1;u.fillRect(g+left_offset,f,k-g,a);if(p!=="Dense"&&o!==undefined&&t>x){u.fillStyle=label_color;if(tile_index===0&&g-u.measureText(o).width<0){u.textAlign="left";u.fillText(o,k+2+left_offset,f+8)}else{u.textAlign="right";u.fillText(o,g-2+left_offset,f+8)}u.fillStyle=block_color}var q=w+" / "+r;if(t>x&&u.measureText(q).width<(k-g)){u.fillStyle="white";u.textAlign="center";u.fillText(q,left_offset+g+(k-g)/2,f+8);u.fillStyle=block_color}}}});var ReadTrack=function(d,b,f,a,c,e){FeatureTrack.call(this,d,b,f,a,c,e);this.track_type="ReadTrack";this.difference_mode=true;this.show_insertions=false;this.make_name_popup_menu()};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{get_y_scale:function(b){var a;if(b==="summary_tree"){}if(b==="Dense"){a=DENSE_TRACK_HEIGHT}else{if(b==="Squish"){a=SQUISH_TRACK_HEIGHT}else{a=PACK_TRACK_HEIGHT;if(this.show_insertions){a*=2}}}return a},draw_read:function(m,d,J,n,D,G,e,o,y,a){m.textAlign="center";var l=this,u=[n,D],C=0,z=0,f=0;var r=[];if((d==="Pack"||this.mode==="Auto")&&o!==undefined&&J>CHAR_WIDTH_PX){f=Math.round(J/2)}if(!e){e=[[0,o.length]]}for(var h=0,k=e.length;h<k;h++){var b=e[h],g="MIDNSHP=X"[b[0]],v=b[1];if(g==="H"||g==="S"){C-=v}var x=G+C,B=Math.floor(Math.max(0,(x-n)*J)),E=Math.floor(Math.max(0,(x+v-n)*J));switch(g){case"H":break;case"S":case"M":case"=":var p=compute_overlap([x,x+v],u);if(p!==NO_OVERLAP){var q=o.slice(z,z+v);if(f>0){m.fillStyle=this.prefs.block_color;m.fillRect(B+this.left_offset-f,y+1,E-B,9);m.fillStyle=CONNECTOR_COLOR;for(var I=0,j=q.length;I<j;I++){if(this.difference_mode&&a){var s=a[x-n+I];if(!s||s.toLowerCase()===q[I].toLowerCase()){continue}}if(x+I>=n&&x+I<=D){var A=Math.floor(Math.max(0,(x+I-n)*J));m.fillText(q[I],A+this.left_offset,y+9)}}}else{m.fillStyle=this.prefs.block_color;m.fillRect(B+this.left_offset,y+(this.mode!=="Dense"?4:5),E-B,(d!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}z+=v;C+=v;break;case"N":m.fillStyle=CONNECTOR_COLOR;m.fillRect(B+this.left_offset-f,y+5,E-B,1);C+=v;break;case"D":m.fillStyle="red";m.fillRect(B+this.left_offset-f,y+4,E-B,3);C+=v;break;case"P":break;case"I":var p=compute_overlap([x,x+v],u),K=this.left_offset+B-f;if(p!==NO_OVERLAP){var q=o.slice(z,z+v);if(this.show_insertions){var w=this.left_offset+B-(E-B)/2;if((d==="Pack"||this.mode==="Auto")&&o!==undefined&&J>CHAR_WIDTH_PX){m.fillStyle="yellow";m.fillRect(w-f,y-9,E-B,9);r[r.length]={type:"triangle",data:[K,y+4,5]};m.fillStyle=CONNECTOR_COLOR;switch(p){case (OVERLAP_START):q=q.slice(n-x);break;case (OVERLAP_END):q=q.slice(0,x-D);break;case (CONTAINED_BY):break;case (CONTAINS):q=q.slice(n-x,x-D);break}for(var I=0,j=q.length;I<j;I++){var A=Math.floor(Math.max(0,(x+I-n)*J));m.fillText(q[I],A+this.left_offset-(E-B)/2,y)}}else{m.fillStyle="yellow";m.fillRect(w,y+(this.mode!=="Dense"?2:5),E-B,(d!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((d==="Pack"||this.mode==="Auto")&&o!==undefined&&J>CHAR_WIDTH_PX){r[r.length]={type:"text",data:[q.length,K,y+9]}}else{}}}z+=v;break;case"X":z+=v;break}}m.fillStyle="yellow";var t,L,H;for(var F=0;F<r.length;F++){t=r[F];L=t.type;H=t.data;if(L==="text"){m.font="bold "+DEFAULT_FONT;m.fillText(H[0],H[1],H[2]);m.font=DEFAULT_FONT}else{if(L=="triangle"){m.drawDownwardEquilateralTriangle(H[0],H[1],H[2])}}}},draw_element:function(w,y,r,k,e,A,b,n,x,u,f,c){var m=k[0],v=k[1],d=k[2],o=k[3],h=Math.floor(Math.max(0,(v-A)*n)),j=Math.ceil(Math.min(u,Math.max(0,(d-A)*n))),g=(r==="Dense"?1:(1+e))*x,z=this.prefs.block_color,l=this.prefs.label_color;t=0;w.fillStyle=z;if(k[5] instanceof Array){var s=Math.floor(Math.max(0,(k[4][0]-A)*n)),q=Math.ceil(Math.min(u,Math.max(0,(k[4][1]-A)*n))),p=Math.floor(Math.max(0,(k[5][0]-A)*n)),a=Math.ceil(Math.min(u,Math.max(0,(k[5][1]-A)*n)));if(k[4][1]>=A&&k[4][0]<=b&&k[4][2]){this.draw_read(w,r,n,A,b,k[4][0],k[4][2],k[4][3],g,c)}if(k[5][1]>=A&&k[5][0]<=b&&k[5][2]){this.draw_read(w,r,n,A,b,k[5][0],k[5][2],k[5][3],g,c)}if(p>q){w.fillStyle=CONNECTOR_COLOR;w.dashedLine(q+f,g+5,f+p,g+5)}}else{w.fillStyle=z;this.draw_read(w,r,n,A,b,v,k[4],k[5],g,c)}if(r==="Pack"&&v>A){w.fillStyle=this.prefs.label_color;if((r==="Pack"||this.mode==="Auto")&&n>CHAR_WIDTH_PX){var t=Math.round(n/2)}if(y===0&&h-w.measureText(o).width<0){w.textAlign="left";w.fillText(o,j+f+LABEL_SPACING-t,g+8)}else{w.textAlign="right";w.fillText(o,h+f-LABEL_SPACING-t,g+8)}w.fillStyle=z}}});var ToolDataFeatureTrack=function(e,c,g,a,d,f,b){FeatureTrack.call(this,e,c,g,a,d,f,{},b);this.track_type="ToolDataFeatureTrack";this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};$.extend(ToolDataFeatureTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{predraw_init:function(){var b=this;var a=function(){if(b.data_cache.size()===0){setTimeout(a,300)}else{b.data_url=default_data_url;b.data_query_wait=DEFAULT_DATA_QUERY_WAIT;b.dataset_state_url=converted_datasets_state_url;$.getJSON(b.dataset_state_url,{dataset_id:b.dataset_id,hda_ldda:b.hda_ldda},function(c){})}};a()}}); \ No newline at end of file +CanvasRenderingContext2D.prototype.dashedLine=function(c,j,b,h,f){if(f===undefined){f=4}var e=b-c;var d=h-j;var g=Math.floor(Math.sqrt(e*e+d*d)/f);var l=e/g;var k=d/g;var a;for(a=0;a<g;a++,c+=l,j+=k){if(a%2!==0){continue}this.fillRect(c,j,f,1)}};CanvasRenderingContext2D.prototype.drawDownwardEquilateralTriangle=function(b,a,e){var d=b-e/2,c=b+e/2,f=a-Math.sqrt(e*3/2);this.beginPath();this.moveTo(d,f);this.lineTo(c,f);this.lineTo(b,a);this.lineTo(d,f);this.strokeStyle=this.fillStyle;this.fill();this.stroke();this.closePath()};function sortable(a,b){a.bind("drag",{handle:b,relative:true},function(h,j){var g=$(this).parent();var f=g.children();var c;for(c=0;c<f.length;c++){if(j.offsetY<$(f.get(c)).position().top){break}}if(c===f.length){if(this!==f.get(c-1)){g.append(this)}}else{if(this!==f.get(c)){$(this).insertBefore(f.get(c))}}})}var NO_OVERLAP=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005;function compute_overlap(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=NO_OVERLAP}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=NO_OVERLAP}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a}function is_overlap(b,a){return(compute_overlap(b,a)!==NO_OVERLAP)}var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=1,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,ERROR_PADDING=10,LABEL_SPACING=2,PACK_SPACING=5,MIN_SQUISH_VIEW_WIDTH=12000,DEFAULT_FONT="9px Monaco, Lucida Console, monospace",DENSITY=200,FEATURE_LEVELS=10,MAX_FEATURE_DEPTH=100,DEFAULT_DATA_QUERY_WAIT=5000,MAX_CHROMS_SELECTABLE=100,CONNECTOR_COLOR="#ccc",DATA_ERROR="There was an error in indexing this dataset. ",DATA_NOCONVERTER="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",DATA_NONE="No data for this chrom/contig.",DATA_PENDING="Currently indexing... please wait",DATA_CANNOT_RUN_TOOL="Tool cannot be rerun: ",DATA_LOADING="Loading data...",DATA_OK="Ready for display",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=5,CACHED_DATA=5,DUMMY_CANVAS=document.createElement("canvas"),RIGHT_STRAND,LEFT_STRAND;if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(DUMMY_CANVAS)}var CONTEXT=DUMMY_CANVAS.getContext("2d");CONTEXT.font=DEFAULT_FONT;var CHAR_WIDTH_PX=CONTEXT.measureText("A").width,CHAR_HEIGHT_PX=9;var right_img=new Image();right_img.src=image_path+"/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var left_img=new Image();left_img.src=image_path+"/visualization/strand_left.png";left_img.onload=function(){LEFT_STRAND=CONTEXT.createPattern(left_img,"repeat")};var right_img_inv=new Image();right_img_inv.src=image_path+"/visualization/strand_right_inv.png";right_img_inv.onload=function(){RIGHT_STRAND_INV=CONTEXT.createPattern(right_img_inv,"repeat")};var left_img_inv=new Image();left_img_inv.src=image_path+"/visualization/strand_left_inv.png";left_img_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};function round_1000(a){return Math.round(a*1000)/1000}var Cache=function(a){this.num_elements=a;this.clear()};$.extend(Cache.prototype,{get:function(b){var a=this.key_ary.indexOf(b);if(a!==-1){this.move_key_to_end(b,a)}return this.obj_cache[b]},set:function(b,c){if(!this.obj_cache[b]){if(this.key_ary.length>=this.num_elements){var a=this.key_ary.shift();delete this.obj_cache[a]}this.key_ary.push(b)}this.obj_cache[b]=c;return c},move_key_to_end:function(b,a){this.key_ary.splice(a,1);this.key_ary.push(b)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var DataManager=function(b,a){Cache.call(this,b);this.track=a};$.extend(DataManager.prototype,Cache.prototype,{load_data:function(d,a,f,h,b,e){var g={chrom:d,low:a,high:f,mode:h,resolution:b,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(g,e);var c=this;return $.getJSON(this.track.data_url,g,function(j){c.set_data(a,f,h,j)})},get_data:function(j,k,c,h,b,f){var l=this.get(this.gen_key(k,c,h));if(l){return l}var m,g,a,e,h,l;for(var d=0;d<this.key_ary.length;d++){m=this.key_ary[d];g=this.split_key(m);a=g[0];e=g[1];if(k>=a&&c<=e){l=this.obj_cache[m];if(l.dataset_type!=="summary_tree"&&l.extra_info!=="no_detail"){this.move_key_to_end(m,d);return l}}}return this.load_data(j,k,c,h,b,f)},set_data:function(b,c,d,a){return this.set(this.gen_key(b,c,d),a)},gen_key:function(a,c,d){var b=a+"_"+c+"_"+d;return b},split_key:function(a){return a.split("_")}});var View=function(a,d,c,b,e){this.container=a;this.chrom=null;this.vis_id=c;this.dbkey=b;this.title=d;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init(e);this.reset()};$.extend(View.prototype,{init:function(d){var c=this.container,a=this;this.top_container=$("<div/>").addClass("top-container").appendTo(c);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(c);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(c);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").text("Select a chrom from the dropdown below").hide();this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var b=function(f){if(f.type==="focusout"||(f.keyCode||f.which)===13||(f.keyCode||f.which)===27){if((f.keyCode||f.which)!==27){a.go_to($(this).val())}$(this).hide();$(this).val("");a.location_span.show();a.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",b).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.bind("click",function(){a.location_span.hide();a.chrom_select.hide();a.nav_input.val(a.chrom+":"+a.low+"-"+a.high);a.nav_input.css("display","inline-block");a.nav_input.select();a.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a id='zoom-out' />").click(function(){a.zoom_out();a.redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){a.zoom_in();a.redraw()}).appendTo(this.nav_controls);this.load_chroms({low:0},d);this.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())});this.intro_div.show();this.content_div.bind("click",function(f){$(this).find("input").trigger("blur")});this.content_div.bind("dblclick",function(f){a.zoom_in(f.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(f,g){this.current_x=g.offsetX}).bind("drag",function(f,h){var j=h.offsetX-this.current_x;this.current_x=h.offsetX;var g=Math.round(j/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-g)});this.overview_close.bind("click",function(){for(var f=0,e=a.tracks.length;f<e;f++){a.tracks[f].is_overview=false}$(this).siblings().filter("canvas").remove();$(this).parent().css("height",a.overview_box.height());a.overview_highlight.hide();$(this).hide()});this.viewport_container.bind("draginit",function(f,g){if(f.clientX>a.viewport_container.width()-16){return false}}).bind("dragstart",function(f,g){g.original_low=a.low;g.current_height=f.clientY;g.current_x=g.offsetX}).bind("drag",function(h,k){var f=$(this);var l=k.offsetX-k.current_x;var g=f.scrollTop()-(h.clientY-k.current_height);f.scrollTop(g);k.current_height=h.clientY;k.current_x=k.offsetX;var j=Math.round(l/a.viewport_container.width()*(a.high-a.low));a.move_delta(j)}).bind("mousewheel",function(h,k,g,f){if(g){var j=Math.round(-g/a.viewport_container.width()*(a.high-a.low));a.move_delta(j)}});this.top_labeltrack.bind("dragstart",function(f,g){return $("<div />").css({height:a.content_div.height()+a.top_labeltrack.height()+a.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(k,l){$(l.proxy).css({left:Math.min(k.pageX,l.startX),width:Math.abs(k.pageX-l.startX)});var g=Math.min(k.pageX,l.startX)-a.container.offset().left,f=Math.max(k.pageX,l.startX)-a.container.offset().left,j=(a.high-a.low),h=a.viewport_container.width();a.update_location(Math.round(g/h*j)+a.low,Math.round(f/h*j)+a.low)}).bind("dragend",function(l,m){var g=Math.min(l.pageX,m.startX),f=Math.max(l.pageX,m.startX),j=(a.high-a.low),h=a.viewport_container.width(),k=a.low;a.low=Math.round(g/h*j)+k;a.high=Math.round(f/h*j)+k;$(m.proxy).remove();a.redraw()});this.add_label_track(new LabelTrack(this,this.top_labeltrack));this.add_label_track(new LabelTrack(this,this.nav_labeltrack));$(window).bind("resize",function(){a.resize_window()});$(document).bind("redraw",function(){a.redraw()});this.reset();$(window).trigger("resize")},update_location:function(a,b){this.location_span.text(commatize(a)+" - "+commatize(b));this.nav_input.val(this.chrom+":"+commatize(a)+"-"+commatize(b))},load_chroms:function(b,c){b.num=MAX_CHROMS_SELECTABLE;$.extend(b,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var a=this;$.ajax({url:chrom_url,data:b,dataType:"json",success:function(e){if(e.chrom_info.length===0){alert("Invalid chromosome: "+b.chrom);return}if(e.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=e.chrom_info;var h='<option value="">Select Chrom/Contig</option>';for(var g=0,d=a.chrom_data.length;g<d;g++){var f=a.chrom_data[g].chrom;h+='<option value="'+f+'">'+f+"</option>"}if(e.prev_chroms){h+='<option value="previous">Previous '+MAX_CHROMS_SELECTABLE+"</option>"}if(e.next_chroms){h+='<option value="next">Next '+MAX_CHROMS_SELECTABLE+"</option>"}a.chrom_select.html(h);if(c){c()}a.chrom_start_index=e.start_index},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}})},change_chrom:function(e,b,g){if(!e||e==="None"){return}var d=this;if(e==="previous"){d.load_chroms({low:this.chrom_start_index-MAX_CHROMS_SELECTABLE});return}if(e==="next"){d.load_chroms({low:this.chrom_start_index+MAX_CHROMS_SELECTABLE});return}var f=$.grep(d.chrom_data,function(j,k){return j.chrom===e})[0];if(f===undefined){d.load_chroms({chrom:e},function(){d.change_chrom(e,b,g)});return}else{if(e!==d.chrom){d.chrom=e;if(!d.chrom){d.intro_div.show()}else{d.intro_div.hide()}d.chrom_select.val(d.chrom);d.max_high=f.len-1;d.reset();d.redraw(true);for(var h=0,a=d.tracks.length;h<a;h++){var c=d.tracks[h];if(c.init){c.init()}}}if(b!==undefined&&g!==undefined){d.low=Math.max(b,0);d.high=Math.min(g,d.max_high)}d.reset_overview();d.redraw()}},go_to:function(f){var k=this,a,d,b=f.split(":"),h=b[0],j=b[1];if(j!==undefined){try{var g=j.split("-");a=parseInt(g[0].replace(/,/g,""),10);d=parseInt(g[1].replace(/,/g,""),10)}catch(c){return false}}k.change_chrom(h,a,d)},move_fraction:function(c){var a=this;var b=a.high-a.low;this.move_delta(c*b)},move_delta:function(c){var a=this;var b=a.high-a.low;if(a.low-c<a.max_low){a.low=a.max_low;a.high=a.max_low+b}else{if(a.high-c>a.max_high){a.high=a.max_high;a.low=a.max_high-b}else{a.high-=c;a.low-=c}}a.redraw()},add_track:function(a){a.view=this;a.track_id=this.track_id_counter;this.tracks.push(a);if(a.init){a.init()}a.container_div.attr("id","track_"+a.track_id);sortable(a.container_div,".draghandle");this.track_id_counter+=1;this.num_tracks+=1},add_label_track:function(a){a.view=this;this.label_tracks.push(a)},remove_track:function(a){this.has_changes=true;a.container_div.fadeOut("slow",function(){$(this).remove()});delete this.tracks[this.tracks.indexOf(a)];this.num_tracks-=1},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},redraw:function(h){var g=this.high-this.low,f=this.low,b=this.high;if(f<this.max_low){f=this.max_low}if(b>this.max_high){b=this.max_high}if(this.high!==0&&g<this.min_separation){b=f+this.min_separation}this.low=Math.floor(f);this.high=Math.ceil(b);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low)/200)/Math.LN10));this.zoom_res=Math.pow(FEATURE_LEVELS,Math.max(0,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS))));var a=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var e=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var j=13;this.overview_box.css({left:a,width:Math.max(j,e)}).show();if(e<j){this.overview_box.css("left",a-(j-e)/2)}if(this.overview_highlight){this.overview_highlight.css({left:a,width:e})}this.update_location(this.low,this.high);if(!h){for(var c=0,d=this.tracks.length;c<d;c++){if(this.tracks[c]&&this.tracks[c].enabled){this.tracks[c].draw()}}for(c=0,d=this.label_tracks.length;c<d;c++){this.label_tracks[c].draw()}}},zoom_in:function(b,c){if(this.max_high===0||this.high-this.low<this.min_separation){return}var d=this.high-this.low,e=d/2+this.low,a=(d/this.zoom_factor)/2;if(b){e=b/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(e-a);this.high=Math.round(e+a);this.redraw()},zoom_out:function(){if(this.max_high===0){return}var b=this.high-this.low,c=b/2+this.low,a=(b*this.zoom_factor)/2;this.low=Math.round(c-a);this.high=Math.round(c+a);this.redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.redraw()},reset_overview:function(){this.overview_viewport.find("canvas").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide()}});var Tool=function(a,b){this.name=a;this.params=b};$.extend(Tool.prototype,{get_param_values_dict:function(){var b={};for(var a=0;a<this.params.length;a++){var c=this.params[a];b[c.name]=c.value}return b},get_param_values:function(){var b=[];for(var a=0;a<this.params.length;a++){b[a]=this.params[a].value}return b}});var NumberToolParameter=function(c,b,e,a,d){this.name=c;this.label=b;this.min=e;this.max=a;this.value=d};var get_tool_from_dict=function(f){if(obj_length(f)===0){return undefined}var b=f.name;var l=f.params;var c=Array();for(var e=0;e<l.length;e++){var g=l[e];var a=g.name,k=g.label,h=g.type,d=g.min,j=g.max,m=g.value;c[c.length]=new NumberToolParameter(a,k,d,j,m)}return new Tool(b,c)};var Filter=function(b,a,c){this.name=b;this.index=a;this.value=c};var NumberFilter=function(b,a){this.name=b;this.index=a;this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.slider_min=Number.MAX_VALUE;this.slider_max=-Number.MAX_VALUE;this.slider=null;this.slider_label=null};$.extend(NumberFilter.prototype,{applies_to:function(a){if(a.length>this.index){return true}return false},keep:function(a){if(!this.applies_to(a)){return true}return(a[this.index]>=this.low&&a[this.index]<=this.high)},update_attrs:function(b){var a=false;if(!this.applies_to(b)){return a}if(b[this.index]<this.slider_min){this.slider_min=b[this.index];a=true}if(b[this.index]>this.slider_max){this.slider_max=b[this.index];a=false}return a},update_ui_elt:function(){var b=this.slider.slider("option","min"),a=this.slider.slider("option","max");if(this.slider_min<b||this.slider_max>a){this.slider.slider("option","min",this.slider_min);this.slider.slider("option","max",this.slider_max);this.slider.slider("option","values",[this.slider_min,this.slider_max])}}});var get_filters_from_dict=function(a){var g=[];for(var d=0;d<a.length;d++){var f=a[d];var c=f.name,e=f.type,b=f.index;if(e==="int"||e==="float"){g[d]=new NumberFilter(c,b)}else{g[d]=new Filter(c,b,e)}}return g};var TrackConfig=function(a){this.track=a.track;this.params=a.params;this.values={};if(a.saved_values){this.restore_values(a.saved_values)}this.onchange=a.onchange};$.extend(TrackConfig.prototype,{restore_values:function(a){var b=this;$.each(this.params,function(c,d){if(a[d.key]!==undefined){b.values[d.key]=a[d.key]}else{b.values[d.key]=d.default_value}})},build_form:function(){var b=this;var a=$("<div />");$.each(this.params,function(f,d){if(!d.hidden){var c="param_"+f;var l=$("<div class='form-row' />").appendTo(a);l.append($("<label />").attr("for",c).text(d.label+":"));if(d.type==="bool"){l.append($('<input type="checkbox" />').attr("id",c).attr("name",c).attr("checked",b.values[d.key]))}else{if(d.type==="color"){var h=b.values[d.key];var g=$("<input />").attr("id",c).attr("name",c).val(h);var j=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var e=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(j);var k=$("<div/>").appendTo(e).farbtastic({width:100,height:100,callback:g,color:h});$("<div />").append(g).append(j).appendTo(l).bind("click",function(m){j.css({left:$(this).position().left+($(g).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){j.hide();$(document).unbind("click.color-picker")});m.stopPropagation()})}else{l.append($("<input />").attr("id",c).attr("name",c).val(b.values[d.key]))}}}});return a},update_from_form:function(a){var c=this;var b=false;$.each(this.params,function(d,f){if(!f.hidden){var g="param_"+d;var e=a.find("#"+g).val();if(f.type==="float"){e=parseFloat(e)}else{if(f.type==="int"){e=parseInt(e)}else{if(f.type==="bool"){e=a.find("#"+g).is(":checked")}}}if(e!==c.values[f.key]){c.values[f.key]=e;b=true}}});if(b){this.onchange()}}});var Track=function(b,a,e,c,d){this.name=b;this.view=a;this.parent_element=e;this.data_url=(c?c:default_data_url);this.data_url_extra_params={};this.data_query_wait=(d?d:DEFAULT_DATA_QUERY_WAIT);this.dataset_check_url=converted_datasets_state_url;this.container_div=$("<div />").addClass("track").css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div class='draghandle' />").appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)};$.extend(Track.prototype,{init:function(){var a=this;a.enabled=false;a.tile_cache.clear();a.data_cache.clear();a.initial_canvas=undefined;a.content_div.css("height","auto");a.container_div.removeClass("nodata error pending");if(!a.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:a.hda_ldda,dataset_id:a.dataset_id,chrom:a.view.chrom},function(b){if(!b||b==="error"||b.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(b.message){var d=a.view.tracks.indexOf(a);var c=$(" <a href='javascript:void(0);'></a>").text("View error").bind("click",function(){show_modal("Trackster Error","<pre>"+b.message+"</pre>",{Close:hide_modal})});a.content_div.append(c)}}else{if(b==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(b==="no data"||(b.data!==undefined&&(b.data===null||b.data.length===0))){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(b==="pending"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},a.data_query_wait)}else{if(b.status==="data"){if(b.valid_chroms){a.valid_chroms=b.valid_chroms;a.make_name_popup_menu()}a.content_div.text(DATA_OK);if(a.view.chrom){a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;$.when(a.predraw_init()).done(function(){a.draw()})}}}}}}})},predraw_init:function(){},update_name:function(a){this.old_name=this.name;this.name=a;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)}});var TiledTrack=function(b,j,n){var c=this,o=c.view;this.filters=(b!==undefined?get_filters_from_dict(b):[]);this.filters_available=false;this.filters_visible=false;this.tool=(j!==undefined?get_tool_from_dict(j):undefined);this.parent_track=n;this.child_tracks=[];if(c.hidden){return}if(this.parent_track){this.header_div.find(".draghandle").removeClass("draghandle").addClass("child-track-icon").addClass("icon-button");this.parent_element.addClass("child-track");this.tool=undefined}this.filters_div=$("<div/>").addClass("filters").hide();this.header_div.after(this.filters_div);this.filters_div.bind("drag",function(q){q.stopPropagation()}).bind("dblclick",function(q){q.stopPropagation()});$.each(this.filters,function(t,w){var u=$("<div/>").addClass("slider-row").appendTo(c.filters_div);var v=$("<div/>").addClass("slider-label").appendTo(u);var s=$("<span/>").addClass("name").appendTo(v);s.text(w.name+" ");var r=$("<span/>").addClass("values").appendTo(v);var q=$("<div/>").addClass("slider").appendTo(u);w.control_element=$("<div/>").attr("id",w.name+"-filter-control").appendTo(q);w.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(y,z){var x=z.values;r.text("["+x[0]+"-"+x[1]+"]");w.low=x[0];w.high=x[1];c.draw(true,true)},change:function(x,y){w.control_element.slider("option","slide").call(w.control_element,x,y)}});w.slider=w.control_element;w.slider_label=r;$("<div style='clear: both;'/>").appendTo(u)});if(this.tool){this.dynamic_tool_div=$("<div/>").addClass("dynamic-tool").hide();this.header_div.after(this.dynamic_tool_div);this.dynamic_tool_div.bind("drag",function(q){q.stopPropagation()}).bind("click",function(q){q.stopPropagation()}).bind("dblclick",function(q){q.stopPropagation()});var m=$("<div class='tool-name'>").appendTo(this.dynamic_tool_div).text(this.tool.name);var l=this.tool.params;var c=this;$.each(this.tool.params,function(x,s){var v=$("<div>").addClass("slider-row").appendTo(c.dynamic_tool_div);var u=$("<div>").addClass("slider-label").appendTo(v);var z=$("<span class='param-name'>").text(s.label+" ").appendTo(u);var t=$("<span/>").text(s.value);var w=$("<span class='param-value'>").appendTo(u).append("[").append(t).append("]");var y=$("<div/>").addClass("slider").appendTo(v);var q=$("<div id='"+s.name+"-param-control'>").appendTo(y);var r=(s.max<=1?0.01:(s.max<=1000?1:5));q.slider({min:s.min,max:s.max,step:r,value:s.value,slide:function(A,C){var B=C.value;s.value=B;if(0<B&&B<1){B=parseFloat(B).toFixed(2)}t.text(B)},change:function(A,B){s.value=B.value}});w.click(function(){var C=t,B=C.text(),A=(s.max<=1?4:s.max.length);C.text("");$("<input type='text'/>").attr("size",A).attr("maxlength",A).attr("value",B).appendTo(C).focus().select().click(function(D){D.stopPropagation()}).blur(function(){$(this).remove();C.text(B)}).keyup(function(F){if(F.keyCode===27){$(this).trigger("blur")}else{if(F.keyCode===13){var D=$(this),E=parseFloat(D.val());if(isNaN(E)||E>s.max||E<s.min){alert("Parameter value must be in the range ["+s.min+"-"+s.max+"]");return $(this)}C.text(E);q.slider("value",E);s.value=E}}})});$("<div style='clear: both;'/>").appendTo(v)});var p=$("<div>").addClass("slider-row").appendTo(this.dynamic_tool_div);var k=$("<input type='submit'>").attr("value","Run").appendTo(p);var c=this;k.click(function(){c.run_tool()})}c.child_tracks_container=$("<div/>").addClass("child-tracks-container").hide();c.container_div.append(c.child_tracks_container);if(c.display_modes!==undefined){if(c.mode_div===undefined){c.mode_div=$("<div class='right-float menubutton popup' />").appendTo(c.header_div);var e=(c.track_config&&c.track_config.values.mode?c.track_config.values.mode:c.display_modes[0]);c.mode=e;c.mode_div.text(e);var d=function(q){c.mode_div.text(q);c.mode=q;c.track_config.values.mode=q;c.tile_cache.clear();c.draw()};var a={};for(var f=0,h=c.display_modes.length;f<h;f++){var g=c.display_modes[f];a[g]=function(q){return function(){d(q)}}(g)}make_popupmenu(c.mode_div,a)}else{c.mode_div.hide()}}this.make_name_popup_menu()};$.extend(TiledTrack.prototype,Track.prototype,{make_name_popup_menu:function(){var b=this;var a={};a["Edit configuration"]=function(){var h=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},f=function(){b.track_config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},g=function(j){if((j.keyCode||j.which)===27){h()}else{if((j.keyCode||j.which)===13){f()}}};$(window).bind("keypress.check_enter_esc",g);show_modal("Configure Track",b.track_config.build_form(),{Cancel:h,OK:f})};if(b.filters_available>0){var e=(b.filters_div.is(":visible")?"Hide filters":"Show filters");a[e]=function(){b.filters_visible=(b.filters_div.is(":visible"));b.filters_div.toggle();b.make_name_popup_menu()}}if(b.tool){var e=(b.dynamic_tool_div.is(":visible")?"Hide Tool":"Show Tool");a[e]=function(){if(!b.dynamic_tool_div.is(":visible")){b.update_name(b.name+b.tool_region_and_parameters_str())}else{menu_option_text="Show dynamic tool";b.revert_name()}b.dynamic_tool_div.toggle();b.make_name_popup_menu()}}if(b.track_type=="ReadTrack"){var e=(b.show_insertions?"Hide Insertions":"Show Insertions");a[e]=function(){b.show_insertions=!b.show_insertions;b.draw(true);b.make_name_popup_menu()}}if(b.valid_chroms){a["List chrom/contigs with data"]=function(){show_modal("Chrom/contigs with data","<p>"+b.valid_chroms.join("<br/>")+"</p>",{Close:function(){hide_modal()}})}}var c=view;var d=function(){$("#no-tracks").show()};if(this.parent_track){c=this.parent_track;d=function(){}}a.Remove=function(){c.remove_track(b);if(c.num_tracks===0){d()}};make_popupmenu(b.name_div,a)},draw:function(a,d){console.log(this.name,a,d);var s=this.view.low,g=this.view.high,j=g-s,l=this.view.container.width(),m=this.view.resolution;var e=$("<div style='position: relative;'></div>"),f=l/j;if(!d){this.content_div.children().remove()}this.content_div.append(e);this.max_height=0;var o=Math.floor(s/m/DENSITY);var c={};while((o*DENSITY*m)<g){var r=l+"_"+f+"_"+o;var h=this.tile_cache.get(r);var p=o*DENSITY*this.view.resolution;var b=p+DENSITY*this.view.resolution;if(!a&&h){this.show_tile(h,e,p,f)}else{this.delayed_draw(a,r,p,b,o,m,e,f,c)}o+=1}if(d){var k=this;var q=setInterval(function(){if(obj_length(c)===0){var v=k.content_div.children();var u=false;for(var w=v.length-1,t=0;w>=t;w--){var x=$(v[w]);if(u){x.remove()}else{if(x.children().length!==0){u=true}}}clearInterval(q)}},50)}for(var n=0;n<this.child_tracks.length;n++){this.child_tracks[n].draw(a,d)}},delayed_draw:function(b,j,g,l,c,e,k,m,f){var d=this;var h=function(u,n,p,o,s,t,q){returned_tile=d.draw_tile(n,p,o,s,t,q);var r=$("<div class='track-tile'>").prepend(returned_tile);tile_element=r;d.tile_cache.set(j,tile_element);d.show_tile(tile_element,s,g,t);delete f[u]};var a=setTimeout(function(){if(g<=d.view.high&&l>=d.view.low){var n=(b?undefined:d.tile_cache.get(j));if(n){d.show_tile(n,k,g,m);delete f[a]}else{$.when(d.data_cache.get_data(view.chrom,g,l,d.mode,e,d.data_url_extra_params)).then(function(){result=d.data_cache.get_data(view.chrom,g,l,d.mode,e,d.data_url_extra_params);if(view.reference_track&&m>CHAR_WIDTH_PX){$.when(view.reference_track.data_cache.get_data(view.chrom,g,l,d.mode,e,view.reference_track.data_url_extra_params)).then(function(){seq_data=view.reference_track.data_cache.get_data(view.chrom,g,l,d.mode,e,view.reference_track.data_url_extra_params);h(a,result,e,c,k,m,seq_data)})}else{h(a,result,e,c,k,m)}})}}},50);f[a]=true},show_tile:function(h,j,e,k){var a=this;var c=this.view.high-this.view.low,b=(e-this.view.low)*k;if(this.left_offset){b-=this.left_offset}h.css({position:"absolute",top:0,left:b,height:""});j.append(h);a.max_height=Math.max(a.max_height,h.height());a.content_div.css("height",a.max_height+"px");j.children().css("height",a.max_height+"px");if(a.hidden){return}for(var g=0;g<a.filters.length;g++){a.filters[g].update_ui_elt()}var d=false;if(a.example_feature){for(var g=0;g<a.filters.length;g++){if(a.filters[g].applies_to(a.example_feature)){d=true;break}}}if(a.filters_available!==d){a.filters_available=d;if(!a.filters_available){a.filters_div.hide()}a.make_name_popup_menu()}},set_overview:function(){var a=this.view;if(this.initial_canvas&&this.is_overview){a.overview_close.show();a.overview_viewport.append(this.initial_canvas);a.overview_highlight.show().height(this.initial_canvas.height());a.overview_viewport.height(this.initial_canvas.height()+a.overview_box.height())}$(window).trigger("resize")},run_tool:function(){var b={dataset_id:this.original_dataset_id,chrom:this.view.chrom,low:this.view.low,high:this.view.high,tool_id:this.tool.name};$.extend(b,this.tool.get_param_values_dict());var d=this,c=b.tool_id+d.tool_region_and_parameters_str(b.chrom,b.low,b.high),e;if(d.track_type==="FeatureTrack"){e=new ToolDataFeatureTrack(c,view,d.hda_ldda,undefined,{},{},d)}this.add_track(e);e.content_div.text("Starting job.");view.has_changes=true;var a=function(){$.getJSON(run_tool_url,b,function(f){if(f==="no converter"){e.container_div.addClass("error");e.content_div.text(DATA_NOCONVERTER)}else{if(f.error){e.container_div.addClass("error");e.content_div.text(DATA_CANNOT_RUN_TOOL+f.message)}else{if(f==="pending"){e.container_div.addClass("pending");e.content_div.text("Converting input data so that it can be easily reused.");setTimeout(a,2000)}else{e.dataset_id=f.dataset_id;e.content_div.text("Running job.");e.init()}}}})};a()},tool_region_and_parameters_str:function(c,a,d){var b=this,e=(c!==undefined&&a!==undefined&&d!==undefined?c+":"+a+"-"+d:"all");return" - region=["+e+"], parameters=["+b.tool.get_param_values().join(", ")+"]"},add_track:function(a){a.track_id=this.track_id+"_"+this.child_tracks.length;a.container_div.attr("id","track_"+a.track_id);this.child_tracks_container.append(a.container_div);sortable(a.container_div,".child-track-icon");if(!$(this.child_tracks_container).is(":visible")){this.child_tracks_container.show()}this.child_tracks.push(a)},remove_track:function(a){a.container_div.fadeOut("slow",function(){$(this).remove()})}});var LabelTrack=function(a,b){this.track_type="LabelTrack";this.hidden=true;Track.call(this,null,a,b);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.view.container.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 ReferenceTrack=function(a){this.track_type="ReferenceTrack";this.hidden=true;Track.call(this,null,a,a.top_labeltrack);TiledTrack.call(this);a.reference_track=this;this.left_offset=200;this.height_px=12;this.font=DEFAULT_FONT;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url;this.data_url_extra_params={dbkey:a.dbkey};this.data_cache=new DataManager(CACHED_DATA,this);this.tile_cache=new Cache(CACHED_TILES_LINE)};$.extend(ReferenceTrack.prototype,TiledTrack.prototype,{draw_tile:function(m,g,b,j,n){var f=this,d=DENSITY*g;if(n>CHAR_WIDTH_PX){if(m===null){f.content_div.css("height","0px");return}var e=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(e)}e=$(e);var l=e.get(0).getContext("2d");e.get(0).width=Math.ceil(d*n+f.left_offset);e.get(0).height=f.height_px;l.font=DEFAULT_FONT;l.textAlign="center";for(var h=0,k=m.length;h<k;h++){var a=Math.round(h*n);l.fillText(m[h],a+f.left_offset,10)}return e}this.content_div.css("height","0px")}});var LineTrack=function(e,c,f,a,d){var b=this;this.track_type="LineTrack";this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";Track.call(this,e,c,c.viewport_container);TiledTrack.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=f;this.dataset_id=a;this.original_dataset_id=a;this.data_cache=new DataManager(CACHED_DATA,this);this.tile_cache=new Cache(CACHED_TILES_LINE);this.track_config=new TrackConfig({track:this,params:[{key:"color",label:"Color",type:"color",default_value:"black"},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.height_px,hidden:true}],saved_values:d,onchange:function(){b.vertical_range=b.prefs.max_value-b.prefs.min_value;$("#linetrack_"+b.track_id+"_minval").text(b.prefs.min_value);$("#linetrack_"+b.track_id+"_maxval").text(b.prefs.max_value);b.tile_cache.clear();b.draw()}});this.prefs=this.track_config.values;this.height_px=this.track_config.values.height;this.vertical_range=this.track_config.values.max_value-this.track_config.values.min_value;(function(g){var k=false;var j=false;var h=$("<div class='track-resize'>");$(g.container_div).hover(function(){k=true;h.show()},function(){k=false;if(!j){h.hide()}});h.hide().bind("dragstart",function(l,m){j=true;m.original_height=$(g.content_div).height()}).bind("drag",function(m,n){var l=Math.min(Math.max(n.original_height+n.deltaY,g.min_height_px),g.max_height_px);$(g.content_div).css("height",l);g.height_px=l;g.draw(true)}).bind("dragend",function(l,m){g.tile_cache.clear();j=false;if(!k){h.hide()}g.track_config.values.height=g.height_px}).appendTo(g.container_div)})(this)};$.extend(LineTrack.prototype,TiledTrack.prototype,{predraw_init:function(){var a=this,b=a.view.tracks.indexOf(a);a.vertical_range=undefined;return $.getJSON(a.data_url,{stats:true,chrom:a.view.chrom,low:null,high:null,hda_ldda:a.hda_ldda,dataset_id:a.dataset_id},function(c){a.container_div.addClass("line-track");var e=c.data;if(isNaN(parseFloat(a.prefs.min_value))||isNaN(parseFloat(a.prefs.max_value))){a.prefs.min_value=e.min;a.prefs.max_value=e.max;$("#track_"+b+"_minval").val(a.prefs.min_value);$("#track_"+b+"_maxval").val(a.prefs.max_value)}a.vertical_range=a.prefs.max_value-a.prefs.min_value;a.total_frequency=e.total_frequency;a.container_div.find(".yaxislabel").remove();var f=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(round_1000(a.prefs.min_value));var d=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(round_1000(a.prefs.max_value));d.css({position:"absolute",top:"24px",left:"10px"});d.prependTo(a.container_div);f.css({position:"absolute",bottom:"2px",left:"10px"});f.prependTo(a.container_div)})},draw_tile:function(j,q,t,c,e){if(this.vertical_range===undefined){return}var o=this,u=t*DENSITY*q,a=DENSITY*q,B=q+"_"+t,v={hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,resolution:this.view.resolution};var b=document.createElement("canvas"),z=j.data;if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(b)}b=$(b);b.get(0).width=Math.ceil(a*e);b.get(0).height=o.height_px;var p=b.get(0).getContext("2d"),k=false,l=o.prefs.min_value,g=o.prefs.max_value,n=o.vertical_range,w=o.total_frequency,d=o.height_px,m=o.mode;var A=Math.round(d+l/n*d);p.beginPath();p.moveTo(0,A);p.lineTo(a*e,A);p.fillStyle="#aaa";p.stroke();p.beginPath();p.fillStyle=o.prefs.color;var x,h,f;if(z.length>1){f=Math.ceil((z[1][0]-z[0][0])*e)}else{f=10}for(var r=0,s=z.length;r<s;r++){x=Math.round((z[r][0]-u)*e);h=z[r][1];if(h===null){if(k&&m==="Filled"){p.lineTo(x,d)}k=false;continue}if(h<l){h=l}else{if(h>g){h=g}}if(m==="Histogram"){h=Math.round(h/n*d);p.fillRect(x,A,f,-h)}else{if(m==="Intensity"){h=255-Math.floor((h-l)/n*255);p.fillStyle="rgb("+h+","+h+","+h+")";p.fillRect(x,0,f,d)}else{h=Math.round(d-(h-l)/n*d);if(k){p.lineTo(x,h)}else{k=true;if(m==="Filled"){p.moveTo(x,d);p.lineTo(x,h)}else{p.moveTo(x,h)}}}}}if(m==="Filled"){if(k){p.lineTo(x,A);p.lineTo(0,A)}p.fill()}else{p.stroke()}return b}});var FeatureTrack=function(a,f,e,j,h,c,d,g){var b=this;this.track_type="FeatureTrack";this.display_modes=["Auto","Dense","Squish","Pack"];this.track_config=new TrackConfig({track:this,params:[{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:h,onchange:function(){b.tile_cache.clear();b.draw()}});this.prefs=this.track_config.values;Track.call(this,a,f,f.viewport_container);TiledTrack.call(this,c,d,g);this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=e;this.dataset_id=j;this.original_dataset_id=j;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.default_font=DEFAULT_FONT;this.inc_slots={};this.start_end_dct={};this.tile_cache=new Cache(CACHED_TILES_FEATURE);this.data_cache=new DataManager(20,this);this.left_offset=200};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{incremental_slots:function(a,h,p){var q=this.inc_slots[a];if(!q||(q.mode!==p)){q={};q.w_scale=a;q.mode=p;this.inc_slots[a]=q;this.start_end_dct[a]={}}var l=q.w_scale,w=[],x=[],j=0,n=this.view.max_low;for(var u=0,v=h.length;u<v;u++){var g=h[u],k=g[0];if(q[k]!==undefined){j=Math.max(j,q[k]);x.push(q[k])}else{w.push(u)}}var d=this.start_end_dct[a];var m=function(D,E){for(var C=0;C<=MAX_FEATURE_DEPTH;C++){var A=false,F=d[C];if(F!==undefined){for(var z=0,B=F.length;z<B;z++){var y=F[z];if(E>y[0]&&D<y[1]){A=true;break}}}if(!A){return C}}return -1};for(var u=0,v=w.length;u<v;u++){var g=h[w[u]],k=g[0],s=g[1],b=g[2],o=g[3],c=Math.floor((s-n)*l),f=Math.ceil((b-n)*l),t=CONTEXT.measureText(o).width,e;if(o!==undefined&&p==="Pack"){t+=(LABEL_SPACING+PACK_SPACING);if(c-t>=0){c-=t;e="left"}else{f+=t;e="right"}}var r=m(c,f);if(r>=0){if(d[r]===undefined){d[r]=[]}d[r].push([c,f]);q[k]=r;j=Math.max(j,r)}else{}}return j+1},draw_summary_tree:function(b,o,n,l,r,j,f,e){var c=j+LABEL_SPACING+CHAR_HEIGHT_PX;delta_x_px=Math.ceil(n*r);var h=$("<div />").addClass("yaxislabel");h.text(l);h.css({position:"absolute",top:"22px",left:"10px"});h.prependTo(this.container_div);var q=b.get(0).getContext("2d");for(var d=0,g=o.length;d<g;d++){var m=Math.floor((o[d][0]-f)*r);var k=o[d][1];if(!k){continue}var p=k/l*j;q.fillStyle="black";q.fillRect(m+e,c-p,delta_x_px,p);var a=4;if(this.prefs.show_counts&&(q.measureText(k).width+a)<delta_x_px){q.fillStyle="#666";q.textAlign="center";q.fillText(k,m+e+(delta_x_px/2),10)}}},draw_element:function(p,f,g,x,j,r,I,M,N,a,A){var u=x[0],K=x[1],C=x[2]-1,s=x[3],D=Math.floor(Math.max(0,(K-r)*M)),q=Math.ceil(Math.min(a,Math.max(0,(C-r)*M))),B=ERROR_PADDING+(g==="Dense"?0:(0+j))*N,o,G,t=null,O=null,d=this.prefs.block_color,F=this.prefs.label_color;if(g==="Dense"){p.fillStyle=d;p.fillRect(D+A,B,q-D,DENSE_FEATURE_HEIGHT)}else{if(g==="no_detail"){p.fillStyle=d;p.fillRect(D+A,B+5,q-D,DENSE_FEATURE_HEIGHT)}else{var n=x[5],z=x[6],E=x[7],e=x[8];if(z&&E){t=Math.floor(Math.max(0,(z-r)*M));O=Math.ceil(Math.min(a,Math.max(0,(E-r)*M)))}var L,v;if(g==="Squish"){L=1;v=SQUISH_FEATURE_HEIGHT}else{L=5;v=PACK_FEATURE_HEIGHT}if(!e){if(x.strand){if(x.strand==="+"){p.fillStyle=RIGHT_STRAND_INV}else{if(x.strand==="-"){p.fillStyle=LEFT_STRAND_INV}}}else{p.fillStyle=d}p.fillRect(D+A,B,q-D,v)}else{var m,w;if(g==="Squish"){p.fillStyle=CONNECTOR_COLOR;m=B+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;w=1}else{if(n){var m=B;var w=v;if(n==="+"){p.fillStyle=RIGHT_STRAND}else{if(n==="-"){p.fillStyle=LEFT_STRAND}}}else{p.fillStyle=CONNECTOR_COLOR;m+=(SQUISH_FEATURE_HEIGHT/2)+1;w=1}}p.fillRect(D+A,m,q-D,w);for(var J=0,c=e.length;J<c;J++){var h=e[J],b=Math.floor(Math.max(0,(h[0]-r)*M)),y=Math.ceil(Math.min(a,Math.max((h[1]-1-r)*M)));if(b>y){continue}p.fillStyle=d;p.fillRect(b+A,B+(v-L)/2+1,y-b,L);if(t!==undefined&&!(b>O||y<t)){var H=Math.max(b,t),l=Math.min(y,O);p.fillRect(H+A,B+1,l-H,v)}}}if(g==="Pack"&&K>r){p.fillStyle=F;if(f===0&&D-p.measureText(s).width<0){p.textAlign="left";p.fillText(s,q+A+LABEL_SPACING,B+8)}else{p.textAlign="right";p.fillText(s,D+A-LABEL_SPACING,B+8)}p.fillStyle=d}}}},get_y_scale:function(b){var a;if(b==="summary_tree"){}if(b==="Dense"){a=DENSE_TRACK_HEIGHT}else{if(b==="no_detail"){a=NO_DETAIL_TRACK_HEIGHT}else{if(b==="Squish"){a=SQUISH_TRACK_HEIGHT}else{a=PACK_TRACK_HEIGHT}}}return a},draw_tile:function(o,x,C,k,m,d){var t=this;var E=C*DENSITY*x,a=(C+1)*DENSITY*x,q=a-E,F={hda_ldda:t.hda_ldda,dataset_id:t.dataset_id,resolution:this.view.resolution,mode:this.mode};var v=Math.ceil(q*m),s=this.mode,H=25,g=this.left_offset,p,h;var c=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(c)}c=$(c);if(s==="Auto"){if(o.dataset_type==="summary_tree"){s=o.dataset_type}else{if(o.extra_info==="no_detail"){s="no_detail"}else{var G=o.data;if((G.length&&G.length<4)||(this.view.high-this.view.low>MIN_SQUISH_VIEW_WIDTH)){s="Squish"}else{s="Pack"}}}}var y=this.get_y_scale(s);if(s==="summary_tree"){h=this.summary_draw_height}if(s==="Dense"){h=H}else{if(s==="no_detail"||s==="Squish"||s==="Pack"){h=this.incremental_slots(m,o.data,s)*y+H;p=this.inc_slots[m]}}c.get(0).width=v+g;c.get(0).height=h;if(o.dataset_type==="summary_tree"){c.get(0).height+=LABEL_SPACING+CHAR_HEIGHT_PX}k.parent().css("height",Math.max(this.height_px,h)+"px");var w=c.get(0).getContext("2d");w.fillStyle=this.prefs.block_color;w.font=this.default_font;w.textAlign="right";this.container_div.find(".yaxislabel").remove();if(s==="summary_tree"){this.draw_summary_tree(c,o.data,o.delta,o.max,m,h,E,g);return c}if(o.message){c.css({"border-top":"1px solid red"});w.fillStyle="red";w.textAlign="left";var r=w.textBaseline;w.textBaseline="top";w.fillText(o.message,g,0);w.textBaseline=r;if(!o.data){return c}}this.example_feature=(o.data.length?o.data[0]:undefined);var G=o.data;for(var z=0,B=G.length;z<B;z++){var j=G[z],l=j[0],u=j[1],b=j[2],e=(p&&p[l]!==undefined?p[l]:null);var A=false;var n;for(var D=0;D<this.filters.length;D++){n=this.filters[D];n.update_attrs(j);if(!n.keep(j)){A=true;break}}if(A){continue}if(is_overlap([u,b],[E,a])&&(s=="Dense"||e!==null)){this.draw_element(w,C,s,j,e,E,a,m,y,v,g,d)}}return c}});var VcfTrack=function(d,b,f,a,c,e){FeatureTrack.call(this,d,b,f,a,c,e);this.track_type="VcfTrack"};$.extend(VcfTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{draw_element:function(u,p,j,e,x,c,m,v,s){var j=data[i],l=j[0],t=j[1],d=j[2]-1,o=j[3],g=Math.floor(Math.max(0,(t-x)*m)),k=Math.ceil(Math.min(s,Math.max(0,(d-x)*m))),f=ERROR_PADDING+(p==="Dense"?0:(0+e))*v,a,y,b=null,n=null;if(no_label){u.fillStyle=block_color;u.fillRect(g+left_offset,f+5,k-g,1)}else{var w=j[4],r=j[5],h=j[6];a=9;y=1;u.fillRect(g+left_offset,f,k-g,a);if(p!=="Dense"&&o!==undefined&&t>x){u.fillStyle=label_color;if(tile_index===0&&g-u.measureText(o).width<0){u.textAlign="left";u.fillText(o,k+2+left_offset,f+8)}else{u.textAlign="right";u.fillText(o,g-2+left_offset,f+8)}u.fillStyle=block_color}var q=w+" / "+r;if(t>x&&u.measureText(q).width<(k-g)){u.fillStyle="white";u.textAlign="center";u.fillText(q,left_offset+g+(k-g)/2,f+8);u.fillStyle=block_color}}}});var ReadTrack=function(d,b,f,a,c,e){FeatureTrack.call(this,d,b,f,a,c,e);this.track_type="ReadTrack";this.difference_mode=true;this.show_insertions=false;this.make_name_popup_menu()};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{get_y_scale:function(b){var a;if(b==="summary_tree"){}if(b==="Dense"){a=DENSE_TRACK_HEIGHT}else{if(b==="Squish"){a=SQUISH_TRACK_HEIGHT}else{a=PACK_TRACK_HEIGHT;if(this.show_insertions){a*=2}}}return a},draw_read:function(m,d,J,n,D,G,e,o,y,a){m.textAlign="center";var l=this,u=[n,D],C=0,z=0,f=0;var r=[];if((d==="Pack"||this.mode==="Auto")&&o!==undefined&&J>CHAR_WIDTH_PX){f=Math.ceil(CHAR_WIDTH_PX/2+1)}if(!e){e=[[0,o.length]]}for(var h=0,k=e.length;h<k;h++){var b=e[h],g="MIDNSHP=X"[b[0]],v=b[1];if(g==="H"||g==="S"){C-=v}var x=G+C,B=Math.floor(Math.max(0,(x-n)*J)),E=Math.floor(Math.max(0,(x+v-n)*J));switch(g){case"H":break;case"S":case"M":case"=":var p=compute_overlap([x,x+v],u);if(p!==NO_OVERLAP){var q=o.slice(z,z+v);if(f>0){m.fillStyle=this.prefs.block_color;m.fillRect(B+this.left_offset-f,y+1,E-B,9);m.fillStyle=CONNECTOR_COLOR;for(var I=0,j=q.length;I<j;I++){if(this.difference_mode&&a){var s=a[x-n+I];if(!s||s.toLowerCase()===q[I].toLowerCase()){continue}}if(x+I>=n&&x+I<=D){var A=Math.floor(Math.max(0,(x+I-n)*J));m.fillText(q[I],A+this.left_offset,y+9)}}}else{m.fillStyle=this.prefs.block_color;m.fillRect(B+this.left_offset,y+(this.mode!=="Dense"?4:5),E-B,(d!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}z+=v;C+=v;break;case"N":m.fillStyle=CONNECTOR_COLOR;m.fillRect(B+this.left_offset-f,y+5,E-B,1);C+=v;break;case"D":m.fillStyle="red";m.fillRect(B+this.left_offset-f,y+4,E-B,3);C+=v;break;case"P":break;case"I":var p=compute_overlap([x,x+v],u),K=this.left_offset+B-f;if(p!==NO_OVERLAP){var q=o.slice(z,z+v);if(this.show_insertions){var w=this.left_offset+B-(E-B)/2;if((d==="Pack"||this.mode==="Auto")&&o!==undefined&&J>CHAR_WIDTH_PX){m.fillStyle="yellow";m.fillRect(w-f,y-9,E-B,9);r[r.length]={type:"triangle",data:[K,y+4,5]};m.fillStyle=CONNECTOR_COLOR;switch(p){case (OVERLAP_START):q=q.slice(n-x);break;case (OVERLAP_END):q=q.slice(0,x-D);break;case (CONTAINED_BY):break;case (CONTAINS):q=q.slice(n-x,x-D);break}for(var I=0,j=q.length;I<j;I++){var A=Math.floor(Math.max(0,(x+I-n)*J));m.fillText(q[I],A+this.left_offset-(E-B)/2,y)}}else{m.fillStyle="yellow";m.fillRect(w,y+(this.mode!=="Dense"?2:5),E-B,(d!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((d==="Pack"||this.mode==="Auto")&&o!==undefined&&J>CHAR_WIDTH_PX){r[r.length]={type:"text",data:[q.length,K,y+9]}}else{}}}z+=v;break;case"X":z+=v;break}}m.fillStyle="yellow";var t,L,H;for(var F=0;F<r.length;F++){t=r[F];L=t.type;H=t.data;if(L==="text"){m.font="bold "+DEFAULT_FONT;m.fillText(H[0],H[1],H[2]);m.font=DEFAULT_FONT}else{if(L=="triangle"){m.drawDownwardEquilateralTriangle(H[0],H[1],H[2])}}}},draw_element:function(w,y,r,k,e,A,b,n,x,u,f,c){var m=k[0],v=k[1],d=k[2],o=k[3],h=Math.floor(Math.max(0,(v-A)*n)),j=Math.ceil(Math.min(u,Math.max(0,(d-A)*n))),g=(r==="Dense"?1:(1+e))*x,z=this.prefs.block_color,l=this.prefs.label_color;t=0;w.fillStyle=z;if(k[5] instanceof Array){var s=Math.floor(Math.max(0,(k[4][0]-A)*n)),q=Math.ceil(Math.min(u,Math.max(0,(k[4][1]-A)*n))),p=Math.floor(Math.max(0,(k[5][0]-A)*n)),a=Math.ceil(Math.min(u,Math.max(0,(k[5][1]-A)*n)));if(k[4][1]>=A&&k[4][0]<=b&&k[4][2]){this.draw_read(w,r,n,A,b,k[4][0],k[4][2],k[4][3],g,c)}if(k[5][1]>=A&&k[5][0]<=b&&k[5][2]){this.draw_read(w,r,n,A,b,k[5][0],k[5][2],k[5][3],g,c)}if(p>q){w.fillStyle=CONNECTOR_COLOR;w.dashedLine(q+f,g+5,f+p,g+5)}}else{w.fillStyle=z;this.draw_read(w,r,n,A,b,v,k[4],k[5],g,c)}if(r==="Pack"&&v>A){w.fillStyle=this.prefs.label_color;if((r==="Pack"||this.mode==="Auto")&&n>CHAR_WIDTH_PX){var t=Math.round(n/2)}if(y===0&&h-w.measureText(o).width<0){w.textAlign="left";w.fillText(o,j+f+LABEL_SPACING-t,g+8)}else{w.textAlign="right";w.fillText(o,h+f-LABEL_SPACING-t,g+8)}w.fillStyle=z}}});var ToolDataFeatureTrack=function(e,c,g,a,d,f,b){FeatureTrack.call(this,e,c,g,a,d,f,{},b);this.track_type="ToolDataFeatureTrack";this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};$.extend(ToolDataFeatureTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{predraw_init:function(){var b=this;var a=function(){if(b.data_cache.size()===0){setTimeout(a,300)}else{b.data_url=default_data_url;b.data_query_wait=DEFAULT_DATA_QUERY_WAIT;b.dataset_state_url=converted_datasets_state_url;$.getJSON(b.dataset_state_url,{dataset_id:b.dataset_id,hda_ldda:b.hda_ldda},function(c){})}};a()}}); \ No newline at end of file --- a/static/scripts/trackster.js Thu Mar 24 15:03:12 2011 -0400 +++ b/static/scripts/trackster.js Thu Mar 24 15:05:28 2011 -0400 @@ -243,13 +243,30 @@ }); /** - * Data-specific cache. + * Data manager for a track. */ -var DataCache = function(num_elements) { - Cache.call(this, num_elements); +var DataManager = function(num_elements, track) { + Cache.call(this, num_elements); + this.track = track; }; -$.extend(DataCache.prototype, Cache.prototype, { - get_data: function(low, high, mode) { +$.extend(DataManager.prototype, Cache.prototype, { + /** + * Load data from server; returns AJAX object so that use of Deferred is possible. + */ + load_data: function(chrom, low, high, mode, resolution, extra_params) { + var params = {"chrom": chrom, "low": low, "high": high, "mode": mode, + "resolution": resolution, "dataset_id" : this.track.dataset_id, + "hda_ldda": this.track.hda_ldda}; + $.extend(params, extra_params); + var manager = this; + return $.getJSON(this.track.data_url, params, function (result) { + manager.set_data(low, high, mode, result); + }); + }, + /** + * Get data and do callback. + */ + get_data: function(chrom, low, high, mode, resolution, extra_params) { // Debugging: //console.log("get_data", low, high, mode); /* @@ -259,7 +276,7 @@ } */ - // Look for key in cache and, if found, return it. + // Look for key in cache and, if found, do callback. var entry = this.get(this.gen_key(low, high, mode)); if (entry) { return entry; @@ -290,18 +307,25 @@ } } - return undefined; + // + // Load data from server. + // + return this.load_data(chrom, low, high, mode, resolution, extra_params); }, set_data: function(low, high, mode, result) { //console.log("set_data", low, high, mode, result); return this.set(this.gen_key(low, high, mode), result); }, - // Generate key for cache. + /** + * Generate key for cache. + */ gen_key: function(low, high, mode) { var key = low + "_" + high + "_" + mode; return key; }, - // Split key from cache into array with format [low, high, mode] + /** + * Split key from cache into array with format [low, high, mode] + */ split_key: function(key) { return key.split("_"); } @@ -1028,6 +1052,7 @@ this.view = view; this.parent_element = parent_element; this.data_url = (data_url ? data_url : default_data_url); + this.data_url_extra_params = {} this.data_query_wait = (data_query_wait ? data_query_wait : DEFAULT_DATA_QUERY_WAIT); this.dataset_check_url = converted_datasets_state_url; @@ -1496,45 +1521,12 @@ make_popupmenu(track.name_div, track_dropdown); }, - tile_data: function(resolution, tile_index, extra_params, callback, key) { - var track = this, - low = tile_index * DENSITY * resolution, - high = ( tile_index + 1 ) * DENSITY * resolution, - params = { "chrom": this.view.chrom, "low": low, "high": high, "dbkey": this.view.dbkey }; - - if (key === undefined) { - key = resolution + "_" + tile_index; - } - var cached = track.data_cache.get(key); - if (cached) { - return callback(cached); - } - $.extend(params, extra_params); - $.ajax({ 'url': this.data_url, 'dataType': 'json', 'data': params, - success: function (result) { - track.data_cache.set(key, result); - return callback(result); - }, error: function(r, t, e) { - console.log(r, t, e); - } - }); - }, /** * Draw track. It is possible to force a redraw rather than use cached tiles and/or clear old * tiles after drawing new tiles. - * - * NOTE/TODO: clear_after only works when no data needs to be loaded. Because tiles fetch their own - * data and then draw themselves, there's no way to determine when all track tiles have been drawn - * because a tile may be waiting on data or drawing itself and there is no way to track a tile's status - * when it requests data and subsequently draws itself. Without the ability to determine when - * a track has been drawn, clear_after may not clear old tiles because it may be called too soon and - * miss old tiles that are being/will be drawn over. - * - * This problem can be fixed by either (a) fetching the data before drawing tiles so that tile drawing - * status can be fully monitored; or (b) keeping a global dictionary of tiles being drawn and their - * status. (a) is probably the better approach. */ draw: function(force, clear_after) { + console.log(this.name, force, clear_after); var low = this.view.low, high = this.view.high, range = high - low, @@ -1544,9 +1536,7 @@ var parent_element = $("<div style='position: relative;'></div>"), w_scale = width / range; - if (!clear_after) { - this.content_div.children().remove(); - } + if (!clear_after) { this.content_div.children().remove(); } this.content_div.append( parent_element ); this.max_height = 0; // Index of first tile that overlaps visible region @@ -1571,7 +1561,7 @@ } // - // Actions to take after new tiles have been loaded/drawn: + // Actions to take after tiles have been drawn: // (1) remove old tile(s); // (2) update filtering UI elements. // @@ -1612,44 +1602,66 @@ delayed_draw: function(force, key, tile_low, tile_high, tile_index, resolution, parent_element, w_scale, draw_tile_dict) { var track = this; // Put a 50ms delay on drawing so that if the user scrolls fast, we don't load extra data - var draw_tile = function(tile_element) { + var draw_and_show_tile = function(id, result, resolution, tile_index, parent_element, w_scale, seq_data) { + returned_tile = track.draw_tile(result, resolution, tile_index, parent_element, w_scale, seq_data) + + // Wrap element in div for background + var wrapper_element = $("<div class='track-tile'>").prepend(returned_tile); + tile_element = wrapper_element; + track.tile_cache.set(key, tile_element); track.show_tile(tile_element, parent_element, tile_low, w_scale); + + // TODO: this should go in a post-draw function. + // Store initial canvas in case we need to use it for overview + /* This is completely broken, just saves the first tile it sees + regardless of if it should be the overview + if (!track.initial_canvas && !window.G_vmlCanvasManager) { + track.initial_canvas = $(tile_element).clone(); + var src_ctx = tile_element.get(0).getContext("2d"); + var tgt_ctx = track.initial_canvas.get(0).getContext("2d"); + var data = src_ctx.getImageData(0, 0, src_ctx.canvas.width, src_ctx.canvas.height); + tgt_ctx.putImageData(data, 0, 0); + track.set_overview(); + } + */ + + delete draw_tile_dict[id]; }; var id = setTimeout(function() { if (tile_low <= track.view.high && tile_high >= track.view.low) { // Show/draw tile: check cache for tile; if tile not in cache, draw it. - var tile_element; - if (!force) { - tile_element = track.tile_cache.get(key); + var tile_element = (force ? undefined : track.tile_cache.get(key)); + if (tile_element) { + track.show_tile(tile_element, parent_element, tile_low, w_scale); + delete draw_tile_dict[id]; } - if (!tile_element) { - track.draw_tile(resolution, tile_index, parent_element, w_scale, function(returned_tile) { - if ( returned_tile ) { - // Wrap element in div for background - var wrapper_element = $("<div class='track-tile'>").prepend( returned_tile ); - tile_element = wrapper_element; + else { + // + // Really draw tile: get data, seq data if available, and draw tile. + // + $.when(track.data_cache.get_data(view.chrom, tile_low, tile_high, track.mode, + resolution, track.data_url_extra_params)).then(function() { + // Data available for track. + result = track.data_cache.get_data(view.chrom, tile_low, tile_high, track.mode, + resolution, track.data_url_extra_params); + // If sequence data needed, get that and draw. Otherwise draw. + if (view.reference_track && w_scale > CHAR_WIDTH_PX) { + $.when(view.reference_track.data_cache.get_data(view.chrom, tile_low, tile_high, + track.mode, resolution, + view.reference_track.data_url_extra_params)).then(function() { + seq_data = view.reference_track.data_cache.get_data(view.chrom, tile_low, tile_high, + track.mode, resolution, + view.reference_track.data_url_extra_params); + draw_and_show_tile(id, result, resolution, tile_index, parent_element, w_scale, seq_data); + }); } - draw_tile(tile_element); - }); - } - if (tile_element) { - // Store initial canvas in case we need to use it for overview - /* This is completely broken, just saves the first tile it sees - regardless of if it should be the overview - if (!track.initial_canvas && !window.G_vmlCanvasManager) { - track.initial_canvas = $(tile_element).clone(); - var src_ctx = tile_element.get(0).getContext("2d"); - var tgt_ctx = track.initial_canvas.get(0).getContext("2d"); - var data = src_ctx.getImageData(0, 0, src_ctx.canvas.width, src_ctx.canvas.height); - tgt_ctx.putImageData(data, 0, 0); - track.set_overview(); - } - */ - draw_tile(tile_element); + else { + draw_and_show_tile(id, result, resolution, tile_index, parent_element, w_scale); + } + }); } } - delete draw_tile_dict[id]; }, 50); draw_tile_dict[id] = true; }, @@ -1846,8 +1858,8 @@ var ReferenceTrack = function (view) { this.track_type = "ReferenceTrack"; this.hidden = true; - Track.call( this, null, view, view.top_labeltrack ); - TiledTrack.call( this ); + Track.call(this, null, view, view.top_labeltrack); + TiledTrack.call(this); view.reference_track = this; this.left_offset = 200; @@ -1858,42 +1870,43 @@ this.content_div.css("min-height", "0px"); this.content_div.css("border", "none"); this.data_url = reference_url; - this.data_cache = new DataCache(CACHED_DATA); + this.data_url_extra_params = {dbkey: view.dbkey}; + this.data_cache = new DataManager(CACHED_DATA, this); this.tile_cache = new Cache(CACHED_TILES_LINE); }; -$.extend( ReferenceTrack.prototype, TiledTrack.prototype, { - draw_tile: function( resolution, tile_index, parent_element, w_scale, callback ) { +$.extend(ReferenceTrack.prototype, TiledTrack.prototype, { + /** + * Draw ReferenceTrack tile. + */ + draw_tile: function(seq, resolution, tile_index, parent_element, w_scale) { var track = this, tile_length = DENSITY * resolution; if (w_scale > CHAR_WIDTH_PX) { - track.tile_data(resolution, tile_index, {}, function(seq) { - if (seq === null) { - track.content_div.css("height", "0px"); - return; - } - var canvas = document.createElement("canvas"); - if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(canvas); } // EXCANVAS HACK - canvas = $(canvas); + if (seq === null) { + track.content_div.css("height", "0px"); + return; + } + var canvas = document.createElement("canvas"); + if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(canvas); } // EXCANVAS HACK + canvas = $(canvas); - var ctx = canvas.get(0).getContext("2d"); - canvas.get(0).width = Math.ceil( tile_length * w_scale + track.left_offset); - canvas.get(0).height = track.height_px; - ctx.font = DEFAULT_FONT; - ctx.textAlign = "center"; - for (var c = 0, str_len = seq.length; c < str_len; c++) { - var c_start = Math.round(c * w_scale); - ctx.fillText(seq[c], c_start + track.left_offset, 10); - } - // parent_element.append(canvas); - return callback(canvas); - }); + var ctx = canvas.get(0).getContext("2d"); + canvas.get(0).width = Math.ceil( tile_length * w_scale + track.left_offset); + canvas.get(0).height = track.height_px; + ctx.font = DEFAULT_FONT; + ctx.textAlign = "center"; + for (var c = 0, str_len = seq.length; c < str_len; c++) { + var c_start = Math.round(c * w_scale); + ctx.fillText(seq[c], c_start + track.left_offset, 10); + } + return canvas; } this.content_div.css("height", "0px"); } }); -var LineTrack = function ( name, view, hda_ldda, dataset_id, prefs ) { +var LineTrack = function (name, view, hda_ldda, dataset_id, prefs) { var track = this; this.track_type = "LineTrack"; this.display_modes = ["Histogram", "Line", "Filled", "Intensity"]; @@ -1907,7 +1920,7 @@ this.hda_ldda = hda_ldda; this.dataset_id = dataset_id; this.original_dataset_id = dataset_id; - this.data_cache = new DataCache(CACHED_DATA); + this.data_cache = new DataManager(CACHED_DATA, this); this.tile_cache = new Cache(CACHED_TILES_LINE); // Define track configuration @@ -1968,7 +1981,7 @@ }).appendTo( track.container_div ); })(this); }; -$.extend( LineTrack.prototype, TiledTrack.prototype, { +$.extend(LineTrack.prototype, TiledTrack.prototype, { predraw_init: function() { var track = this, track_id = track.view.tracks.indexOf(track); @@ -2001,7 +2014,10 @@ min_label.prependTo(track.container_div); }); }, - draw_tile: function( resolution, tile_index, parent_element, w_scale, callback ) { + /** + * Draw LineTrack tile. + */ + draw_tile: function(result, resolution, tile_index, parent_element, w_scale) { if (this.vertical_range === undefined) { return; } @@ -2012,94 +2028,93 @@ key = resolution + "_" + tile_index, params = { hda_ldda: this.hda_ldda, dataset_id: this.dataset_id, resolution: this.view.resolution }; - this.tile_data(resolution, tile_index, params, function(result) { - var canvas = document.createElement("canvas"), - data = result.data; - if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(canvas); } // EXCANVAS HACK - canvas = $(canvas); - canvas.get(0).width = Math.ceil( tile_length * w_scale ); - canvas.get(0).height = track.height_px; - var ctx = canvas.get(0).getContext("2d"), - in_path = false, - min_value = track.prefs.min_value, - max_value = track.prefs.max_value, - vertical_range = track.vertical_range, - total_frequency = track.total_frequency, - height_px = track.height_px, - mode = track.mode; + var canvas = document.createElement("canvas"), + data = result.data; + if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(canvas); } // EXCANVAS HACK + canvas = $(canvas); + + canvas.get(0).width = Math.ceil( tile_length * w_scale ); + canvas.get(0).height = track.height_px; + var ctx = canvas.get(0).getContext("2d"), + in_path = false, + min_value = track.prefs.min_value, + max_value = track.prefs.max_value, + vertical_range = track.vertical_range, + total_frequency = track.total_frequency, + height_px = track.height_px, + mode = track.mode; - // Pixel position of 0 on the y axis - var y_zero = Math.round( height_px + min_value / vertical_range * height_px ); + // Pixel position of 0 on the y axis + var y_zero = Math.round( height_px + min_value / vertical_range * height_px ); - // Line at 0.0 - ctx.beginPath(); - ctx.moveTo( 0, y_zero ); - ctx.lineTo( tile_length * w_scale, y_zero ); - // ctx.lineWidth = 0.5; - ctx.fillStyle = "#aaa"; - ctx.stroke(); - - ctx.beginPath(); - ctx.fillStyle = track.prefs.color; - var x_scaled, y, delta_x_px; - if (data.length > 1) { - delta_x_px = Math.ceil((data[1][0] - data[0][0]) * w_scale); + // Line at 0.0 + ctx.beginPath(); + ctx.moveTo( 0, y_zero ); + ctx.lineTo( tile_length * w_scale, y_zero ); + // ctx.lineWidth = 0.5; + ctx.fillStyle = "#aaa"; + ctx.stroke(); + + ctx.beginPath(); + ctx.fillStyle = track.prefs.color; + var x_scaled, y, delta_x_px; + if (data.length > 1) { + delta_x_px = Math.ceil((data[1][0] - data[0][0]) * w_scale); + } else { + delta_x_px = 10; + } + for (var i = 0, len = data.length; i < len; i++) { + x_scaled = Math.round((data[i][0] - tile_low) * w_scale); + y = data[i][1]; + if (y === null) { + if (in_path && mode === "Filled") { + ctx.lineTo(x_scaled, height_px); + } + in_path = false; + continue; + } + if (y < min_value) { + y = min_value; + } else if (y > max_value) { + y = max_value; + } + + if (mode === "Histogram") { + // y becomes the bar height in pixels, which is the negated for canvas coords + y = Math.round( y / vertical_range * height_px ); + ctx.fillRect(x_scaled, y_zero, delta_x_px, - y ); + } else if (mode === "Intensity" ) { + y = 255 - Math.floor( (y - min_value) / vertical_range * 255 ); + ctx.fillStyle = "rgb(" +y+ "," +y+ "," +y+ ")"; + ctx.fillRect(x_scaled, 0, delta_x_px, height_px); } else { - delta_x_px = 10; - } - for (var i = 0, len = data.length; i < len; i++) { - x_scaled = Math.round((data[i][0] - tile_low) * w_scale); - y = data[i][1]; - if (y === null) { - if (in_path && mode === "Filled") { - ctx.lineTo(x_scaled, height_px); - } - in_path = false; - continue; - } - if (y < min_value) { - y = min_value; - } else if (y > max_value) { - y = max_value; - } - - if (mode === "Histogram") { - // y becomes the bar height in pixels, which is the negated for canvas coords - y = Math.round( y / vertical_range * height_px ); - ctx.fillRect(x_scaled, y_zero, delta_x_px, - y ); - } else if (mode === "Intensity" ) { - y = 255 - Math.floor( (y - min_value) / vertical_range * 255 ); - ctx.fillStyle = "rgb(" +y+ "," +y+ "," +y+ ")"; - ctx.fillRect(x_scaled, 0, delta_x_px, height_px); + // console.log(y, track.min_value, track.vertical_range, (y - track.min_value) / track.vertical_range * track.height_px); + y = Math.round( height_px - (y - min_value) / vertical_range * height_px ); + // console.log(canvas.get(0).height, canvas.get(0).width); + if (in_path) { + ctx.lineTo(x_scaled, y); } else { - // console.log(y, track.min_value, track.vertical_range, (y - track.min_value) / track.vertical_range * track.height_px); - y = Math.round( height_px - (y - min_value) / vertical_range * height_px ); - // console.log(canvas.get(0).height, canvas.get(0).width); - if (in_path) { + in_path = true; + if (mode === "Filled") { + ctx.moveTo(x_scaled, height_px); ctx.lineTo(x_scaled, y); } else { - in_path = true; - if (mode === "Filled") { - ctx.moveTo(x_scaled, height_px); - ctx.lineTo(x_scaled, y); - } else { - ctx.moveTo(x_scaled, y); - } + ctx.moveTo(x_scaled, y); } } } - if (mode === "Filled") { - if (in_path) { - ctx.lineTo( x_scaled, y_zero ); - ctx.lineTo( 0, y_zero ); - } - ctx.fill(); - } else { - ctx.stroke(); + } + if (mode === "Filled") { + if (in_path) { + ctx.lineTo( x_scaled, y_zero ); + ctx.lineTo( 0, y_zero ); } - callback(canvas); - }); + ctx.fill(); + } else { + ctx.stroke(); + } + return canvas; } }); @@ -2147,10 +2162,10 @@ this.inc_slots = {}; this.start_end_dct = {}; this.tile_cache = new Cache(CACHED_TILES_FEATURE); - this.data_cache = new DataCache(20); + this.data_cache = new DataManager(20, this); this.left_offset = 200; }; -$.extend( FeatureTrack.prototype, TiledTrack.prototype, { +$.extend(FeatureTrack.prototype, TiledTrack.prototype, { /** * Place features in slots for drawing (i.e. pack features). * this.inc_slots[level] is created in this method. this.inc_slots[level] @@ -2501,14 +2516,10 @@ /** * Draw FeatureTrack tile. */ - draw_tile: function(resolution, tile_index, parent_element, w_scale, callback, ref_seq, result) { + draw_tile: function(result, resolution, tile_index, parent_element, w_scale, ref_seq) { // Fetch reference sequence data if it exists and we are displaying var track = this; - if (track.view.reference_track && w_scale > CHAR_WIDTH_PX && ref_seq === undefined) { - return track.view.reference_track.tile_data(resolution, tile_index, {}, function(ret_ref_seq) { - track.draw_tile(resolution, tile_index, parent_element, w_scale, callback, ret_ref_seq); - }); - } + var tile_low = tile_index * DENSITY * resolution, tile_high = ( tile_index + 1 ) * DENSITY * resolution, tile_span = tile_high - tile_low, @@ -2516,21 +2527,6 @@ resolution: this.view.resolution, mode: this.mode }; // - // Get tile data; if data not available, issue get_data request and rerun with data - // - if (result === undefined) { - var cached = this.data_cache.get_data(tile_low, tile_high, this.mode), - key = resolution + "_" + tile_index + "_" + this.mode; - if (cached === undefined) { - return track.tile_data(resolution, tile_index, params, function(get_data_result) { - track.data_cache.set_data(tile_low, tile_high, this.mode, get_data_result); - track.draw_tile(resolution, tile_index, parent_element, w_scale, callback, ref_seq, get_data_result); - }, key); - } - result = cached; - } - - // // Create/set/compute some useful vars. // var width = Math.ceil( tile_span * w_scale ), @@ -2611,7 +2607,7 @@ if (mode === "summary_tree") { this.draw_summary_tree(canvas, result.data, result.delta, result.max, w_scale, required_height, tile_low, left_offset); - return callback(canvas); + return canvas; } // @@ -2631,7 +2627,7 @@ // If there's no data, return. if (!result.data) { - return callback(canvas); + return canvas; } } @@ -2674,7 +2670,7 @@ width, left_offset, ref_seq); } } - callback(canvas); + return canvas; } }); Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.
participants (1)
-
Bitbucket