# HG changeset patch -- Bitbucket.org # Project galaxy-dist # URL http://bitbucket.org/galaxy/galaxy-dist/overview # User Kanwei Li <kanwei@gmail.com> # Date 1278029069 14400 # Node ID 692458d15b9211ba7e6569e07b350ef2c3c9757a # Parent e7678fd94340e969552c8cea825bc2a2cbace68e trackster: Track browsers can now be embedded in Galaxy Pages as multiple browsers can now exist at the same time after refactoring. Display code is now separated from editor code. Some scrolling bugs have been fixed as well. --- /dev/null +++ b/templates/visualization/item_content.mako @@ -0,0 +1,3 @@ +<%namespace file="/visualization/display.mako" import="*" /> + +${render_item( item, item_data )} --- a/templates/visualization/display.mako +++ b/templates/visualization/display.mako @@ -1,169 +1,23 @@ <%inherit file="/display_base.mako"/><%def name="javascripts()"> + <% config = item_data %> ${parent.javascripts()} - ${h.js( "jquery.event.drag", "jquery.autocomplete", "jquery.mousewheel", "trackster", "ui.core", "ui.sortable" )} + ${h.js( "jquery.event.drag", "jquery.autocomplete", "jquery.mousewheel", "trackster" )} - ## HACK: set config as item_data. - <% config = item_data %> - - ## TODO: Copied from browser.mako -- probably should create JS file for visualization code and include visualization JS above. <script type="text/javascript"> - - ## JG: add controller name. - var data_url = "${h.url_for( controller='/tracks', action='data' )}"; var view; - - $(function() { - - %if config: - view = new View( "${config.get('chrom')}", "${config.get('title') | h}", "${config.get('vis_id')}", "${config.get('dbkey')}" ); - %for track in config.get('tracks'): - view.add_track( - new ${track["track_type"]}( "${track['name'] | h}", ${track['dataset_id']}, ${track['prefs']} ) - ); - %endfor - init(); - %else: - continue_fn = function() { - view = new View( undefined, $("#new-title").val(), undefined, $("#new-dbkey").val() ); - init(); - hide_modal(); - }; - $.ajax({ - url: "${h.url_for( action='new_browser' )}", - data: {}, - error: function() { alert( "Couldn't create new browser" ) }, - success: function(form_html) { - show_modal("New Track Browser", form_html, { - "Cancel": function() { window.location = "/"; }, - "Continue": function() { $(document).trigger("convert_dbkeys"); continue_fn(); } - }); - $("#new-title").focus(); - replace_big_select_inputs(); - } - }); - %endif - - // Execute this when everything is ready - function init() { - $("ul#sortable-ul").sortable({ - update: function(event, ui) { - for (var track_id in view.tracks) { - var track = view.tracks[track_id]; - } - } - }); - - $(document).bind( "redraw", function( e ) { - view.redraw(); - }); - - $("#content").bind("mousewheel", function( e, delta ) { - if (delta > 0) { - view.zoom_in(e.pageX, $("#viewport-container")); - } else { - view.zoom_out(); - } - e.preventDefault(); - }); - - $("#content").bind("dblclick", function( e ) { - view.zoom_in(e.pageX, $("#viewport-container")); - }); - - // To let the overview box be draggable - $("#overview-box").bind("dragstart", function( e ) { - this.current_x = e.offsetX; - }).bind("drag", function( e ) { - var delta = e.offsetX - this.current_x; - this.current_x = e.offsetX; - - var delta_chrom = Math.round(delta / $(document).width() * view.span); - view.center += delta_chrom; - view.redraw(); - }); - - // To adjust the size of the viewport to fit the fixed-height footer - var refresh = function( e ) { - $("#viewport-container").height( $(window).height() - 120 ); - $("#nav-container").width( $("#center").width() ); - view.redraw(); - }; - $(window).bind( "resize", function(e) { refresh(e); } ); - $("#right-border").bind( "click", function(e) { refresh(e); } ); - $("#right-border").bind( "dragend", function(e) { refresh(e); } ); - $(window).trigger( "resize" ); - - $("#viewport-container").bind( "dragstart", function( e ) { - this.original_low = view.low; - this.current_height = e.clientY; - this.current_x = e.offsetX; - }).bind( "drag", function( e ) { - var container = $(this); - var delta = e.offsetX - this.current_x; - var new_scroll = container.scrollTop() - (e.clientY - this.current_height); - if ( new_scroll < container.get(0).scrollHeight - container.height() ) { - container.scrollTop(new_scroll); - } - this.current_height = e.clientY; - this.current_x = e.offsetX; - - var delta_chrom = Math.round(delta / $(document).width() * (view.high - view.low)); - view.center -= delta_chrom; - view.redraw(); - }); - - ## JG: Removed 'add-track' init code. - - ## JG: Removed 'save-button' init code - - view.add_label_track( new LabelTrack( $("#top-labeltrack" ) ) ); - view.add_label_track( new LabelTrack( $("#nav-labeltrack" ) ) ); - - $.ajax({ - ## JG: added controller name - url: "${h.url_for( controller='/tracks', action='chroms' )}", - data: { vis_id: view.vis_id }, - dataType: "json", - success: function ( data ) { - view.chrom_data = data; - var chrom_options = '<option value="">Select Chrom/Contig</option>'; - for (i in data) { - var chrom = data[i]['chrom'] - chrom_options += '<option value="' + chrom + '">' + chrom + '</option>'; - } - $("#chrom").html(chrom_options); - $("#chrom").bind( "change", function () { - view.chrom = $("#chrom").val(); - var found = $.grep(view.chrom_data, function(v, i) { - return v.chrom === view.chrom; - })[0]; - view.max_high = found.len; - view.reset(); - view.redraw(true); - - for (var track_id in view.tracks) { - var track = view.tracks[track_id]; - if (track.init) { - track.init(); - } - } - view.redraw(); - }); - }, - error: function() { - alert( "Could not load chroms for this dbkey:", view.dbkey ); - } - }); - - ## JG: Removed function sidebar_box() and sidebar init code. - - $(window).trigger("resize"); - }; - - }); - + // To adjust the size of the viewport to fit the fixed-height footer + var refresh = function( e ) { + if (view !== undefined) { + view.viewport_container.height( $(window).height() - 100 ); + view.nav_container.width( $("#center").width() ); + view.redraw(); + } + }; + $(window).bind( "resize", function(e) { refresh(e); } ); + $("#right-border").bind( "click dragend", function(e) { refresh(e); } ); + $(window).trigger( "resize" ); </script></%def> @@ -171,60 +25,45 @@ <%def name="stylesheets()"> ${parent.stylesheets()} - ${h.css( "history" )} - <link rel="stylesheet" type="text/css" href="${h.url_for('/static/trackster.css')}" /> - <style type="text/css"> - ul#sortable-ul { - list-style: none; - padding: 0; - margin: 5px; + .nav-container { + position: fixed; + width: 100%; + left: 0; + bottom: 0; } - ul#sortable-ul li { - display: block; - margin: 5px 0; - background: #eee; + .page-body { + padding: 0px; } + </style></%def> +<%def name="render_item_header( item )"> + ## Don't need to show header +</%def> + <%def name="render_item_links( visualization )"> - ## TODO + </%def><%def name="render_item( visualization, config )"> - <br><br> - ## Copied from center_panel() in browser.mako -- probably need to create visualization_common.mako to render view. - <div id="content"> - <div id="top-labeltrack"></div> - <div id="viewport-container" style="overflow-x: hidden; overflow-y: auto;"> - <div id="viewport"></div> - </div> - </div> - <div id="nav-container" style="width:100%;"> - <div id="nav-labeltrack"></div> - <div id="nav"> - <div id="overview"> - <div id="overview-viewport"> - <div id="overview-box"></div> - </div> - </div> - <div id="nav-controls"> - <form action="#"> - <select id="chrom" name="chrom" style="width: 15em;"> - <option value="">Loading</option> - </select> - <input id="low" size="12" />:<input id="high" size="12" /> - <input type="hidden" name="id" value="${config.get('vis_id', '')}" /> - <a href="#" onclick="javascript:view.zoom_in();view.redraw();"> - <img src="${h.url_for('/static/images/fugue/magnifier-zoom.png')}" /> - </a> - <a href="#" onclick="javascript:view.zoom_out();view.redraw();"> - <img src="${h.url_for('/static/images/fugue/magnifier-zoom-out.png')}" /> - </a> - </form> - <div id="debug" style="float: right"></div> - </div> - </div> - </div> + <div id="${visualization.id}"></div> + + <script type="text/javascript"> + + var data_url = "${h.url_for( controller='/tracks', action='data' )}", + reference_url = "${h.url_for( controller='/tracks', action='reference' )}", + chrom_url = "${h.url_for( controller='/tracks', action='chroms' )}", + view; + + var container_element = $("#${visualization.id}"); + view = new View( container_element, "${config.get('chrom')}", "${config.get('title') | h}", "${config.get('vis_id')}", "${config.get('dbkey')}" ); + %for track in config.get('tracks'): + view.add_track( + new ${track["track_type"]}( "${track['name'] | h}", view, ${track['dataset_id']}, ${track['prefs']} ) + ); + %endfor + + </script></%def> --- a/templates/display_base.mako +++ b/templates/display_base.mako @@ -32,7 +32,7 @@ <%def name="javascripts()"> ${parent.javascripts()} - ${h.js( "jquery", "jquery.tipsy", "galaxy.base", "json2", "class", "jquery.jstore", "jquery.autocomplete", "autocomplete_tagging" )} + ${h.js( "jquery", "jquery.tipsy", "galaxy.base", "json2", "class", "jquery.jstore", "jquery.autocomplete", "autocomplete_tagging", "trackster" )} <script type="text/javascript"> @@ -72,6 +72,8 @@ <%def name="stylesheets()"> ${parent.stylesheets()} ${h.css( "autocomplete_tagging", "embed_item" )} + <link rel="stylesheet" type="text/css" href="${h.url_for('/static/trackster.css')}" /> + <style type="text/css"> .page-body { padding: 10px; --- a/static/scripts/packed/galaxy.base.js +++ b/static/scripts/packed/galaxy.base.js @@ -1,1 +1,1 @@ -$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};function ensure_popup_helper(){if($("#popup-helper").length===0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function attach_popupmenu(b,d){var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scrollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).click(c)}function make_popupmenu(c,b){ensure_popup_helper();var a=$("<ul id='"+c.attr("id") +"-menu'></ul>");$.each(b,function(f,e){if(e){$("<li/>").html(f).click(e).appendTo(a)}else{$("<li class='head'/>").html(f).appendTo(a)}});var d=$("<div class='popmenu-wrapper'>");d.append(a).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(c,d)}function make_popup_menus(){jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}else{if(e=="_top"){g=window.top}}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.addClass("popup").show()})}function array_length(b){if(b.length){return b.length}var c=0;for(var a in b){c++}return c}function naturalSort(i,g){var n=/(-?[0-9\.]+)/g,j=i.toString().toLowerCase()||"",f=g.toString().toLowerCase()||"",k=String.fromCharCode(0),l=j.replace(n,k+" $1"+k).split(k),e=f.replace(n,k+"$1"+k).split(k),d=(new Date(j)).getTime(),m=d?(new Date(f)).getTime():null;if(m){if(d<m){return -1}else{if(d>m){return 1}}}for(var h=0,c=Math.max(l.length,e.length);h<c;h++){oFxNcL=parseFloat(l[h])||l[h];oFyNcL=parseFloat(e[h])||e[h];if(oFxNcL<oFyNcL){return -1}else{if(oFxNcL>oFyNcL){return 1}}}return 0}function replace_big_select_inputs(a,b){if(!jQuery().autocomplete){return}if(a===undefined){a=20}if(b===undefined){b=3000}$("select").each(function(){var e=$(this);var h=e.find("option").length;if((h<a)||(h>b)){return}if(e.attr("multiple")==true){return}var l=e.attr("value");var c=$("<input type='text' class='text-and-autocomplete-select'></input>");c.attr("size",40);c.attr("name",e.attr("name"));c.attr("id",e.attr("id"));c.click(function(){var m=$(this).val();$(this).val("Loading...");$(this).showAllInCache();$(this).val(m);$(this).select()});var f=[];var i={};e.children("option").each(function(){var n=$(this).text();var m=$(this).attr("value ");f.push(n);i[n]=m;i[m]=m;if(m==l){c.attr("value",n)}});if(l==""||l=="?"){c.attr("value","Click to Search or Select")}if(e.attr("name")=="dbkey"){f=f.sort(naturalSort)}var g={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:b,minChars:0,hideForLessThanMinChars:false};c.autocomplete(f,g);e.replaceWith(c);var k=function(){var n=c.attr("value");var m=i[n];if(m!==null&&m!==undefined){c.attr("value",m)}else{if(l!=""){c.attr("value",l)}else{c.attr("value","?")}}};c.parents("form").submit(function(){k()});$(document).bind("convert_dbkeys",function(){k()});if(e.attr("refresh_on_change")=="true"){var d=e.attr("refresh_on_change_values");if(d!==undefined){d=d.split(",")}var j=function(){var o=c.attr("value");var n=i[o];if(n!==null&&n!==undefined){refresh=false;if(d!==undefined){for(var m=0;m<d.length;m++){if(n==d[m]){refresh=true;break}}}else{refresh=true}if(refresh){c.attr("value",n);c.parents("form").submit()}}};c.bind("result",j);c.keyup(function(m){if(m.key Code===13){j()}});c.keydown(function(m){if(m.keyCode===13){return false}})}})}function async_save_text(d,f,e,a,c,h,i,g,b){if(c===undefined){c=30}if(i===undefined){i=4}$("#"+d).live("click",function(){if($("#renaming-active").length>0){return}var l=$("#"+f),k=l.text(),j;if(h){j=$("<textarea></textarea>").attr({rows:i,cols:c}).text(k)}else{j=$("<input type='text'></input>").attr({value:k,size:c})}j.attr("id","renaming-active");j.blur(function(){$(this).remove();l.show();if(b){b(j)}});j.keyup(function(n){if(n.keyCode===27){$(this).trigger("blur")}else{if(n.keyCode===13){var m={};m[a]=$(this).val();$(this).trigger("blur");$.ajax({url:e,data:m,error:function(){alert("Text editing for elt "+f+" failed")},success:function(o){l.text(o);if(b){b(j)}}})}}});if(g){g(j)}l.hide();j.insertAfter(l);j.focus();j.select();return})}function init_history_items(d,a,c){var b=function(){try{var e=$.jStore.store("history_expand_state");if(e){for(var g in e){$("#"+g+" div.historyItemBody").show()}}}c atch(f){$.jStore.remove("history_expand_state")}if($.browser.mozilla){$("div.historyItemBody").each(function(){if(!$(this).is(":visible")){$(this).find("pre.peek").css("overflow","hidden")}})}d.each(function(){var j=this.id;var h=$(this).children("div.historyItemBody");var i=h.find("pre.peek");$(this).find(".historyItemTitleBar > .historyItemTitle").wrap("<a href='javascript:void(0);'></a>").click(function(){if(h.is(":visible")){if($.browser.mozilla){i.css("overflow","hidden")}h.slideUp("fast");if(!c){var k=$.jStore.store("history_expand_state");if(k){delete k[j];$.jStore.store("history_expand_state",k)}}}else{h.slideDown("fast",function(){if($.browser.mozilla){i.css("overflow","auto")}});if(!c){var k=$.jStore.store("history_expand_state");if(k===undefined){k={}}k[j]=true;$.jStore.store("history_expand_state",k)}}return false})});$("#top-links > a.toggle").click(function(){var h=$.jStore.store("history_expand_state");if(h===undefined){h={}}$("div.historyItemBody:visible").ea ch(function(){if($.browser.mozilla){$(this).find("pre.peek").css("overflow","hidden")}$(this).slideUp("fast");if(h){delete h[$(this).parent().attr("id")]}});$.jStore.store("history_expand_state",h)}).show()};if(a){b()}else{$.jStore.init("galaxy");$.jStore.engineReady(function(){b()})}}function commatize(b){b+="";var a=/(\d+)(\d{3})/;while(a.test(b)){b=b.replace(a,"$1,$2")}return b}function reset_tool_search(a){var c=$("#galaxy_tools").contents();if(c.length==0){c=$(document)}$(this).removeClass("search_active");c.find(".toolTitle").removeClass("search_match");c.find(".toolSectionBody").hide();c.find(".toolTitle").show();c.find(".toolPanelLabel").show();c.find(".toolSectionWrapper").each(function(){if($(this).attr("id")!="recently_used_wrapper"){$(this).show()}else{if($(this).hasClass("user_pref_visible")){$(this).show()}}});c.find("#search-no-results").hide();c.find("#search-spinner").hide();if(a){var b=c.find("#tool-search-query");b.val("search tools");b.css("font-style","i talic")}}function GalaxyAsync(a){this.url_dict={};this.log_action=(a===undefined?false:a)}GalaxyAsync.prototype.set_func_url=function(a,b){this.url_dict[a]=b};GalaxyAsync.prototype.set_user_pref=function(a,b){var c=this.url_dict[arguments.callee];if(c===undefined){return false}$.ajax({url:c,data:{pref_name:a,pref_value:b},error:function(){return false},success:function(){return true}})};GalaxyAsync.prototype.log_user_action=function(c,b,d){if(!this.log_action){return}var a=this.url_dict[arguments.callee];if(a===undefined){return false}$.ajax({url:a,data:{action:c,context:b,params:d},error:function(){return false},success:function(){return true}})};$(document).ready(function(){$("a[confirm]").click(function(){return confirm($(this).attr("confirm"))});if($.fn.tipsy){$(".tooltip").tipsy({gravity:"s"})}make_popup_menus();replace_big_select_inputs(20,1500)}); +$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};function ensure_popup_helper(){if($("#popup-helper").length===0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function attach_popupmenu(b,d){var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scrollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).click(c)}function make_popupmenu(c,b){ensure_popup_helper();var a=$("<ul id='"+c.attr("id") +"-menu'></ul>");$.each(b,function(f,e){if(e){$("<li/>").html(f).click(e).appendTo(a)}else{$("<li class='head'/>").html(f).appendTo(a)}});var d=$("<div class='popmenu-wrapper'>");d.append(a).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(c,d)}function make_popup_menus(){jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}else{if(e=="_top"){g=window.top}}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.addClass("popup").show()})}function array_length(b){if(b.length){return b.length}var c=0;for(var a in b){c++}return c}function naturalSort(i,g){var n=/(-?[0-9\.]+)/g,j=i.toString().toLowerCase()||"",f=g.toString().toLowerCase()||"",k=String.fromCharCode(0),l=j.replace(n,k+" $1"+k).split(k),e=f.replace(n,k+"$1"+k).split(k),d=(new Date(j)).getTime(),m=d?(new Date(f)).getTime():null;if(m){if(d<m){return -1}else{if(d>m){return 1}}}for(var h=0,c=Math.max(l.length,e.length);h<c;h++){oFxNcL=parseFloat(l[h])||l[h];oFyNcL=parseFloat(e[h])||e[h];if(oFxNcL<oFyNcL){return -1}else{if(oFxNcL>oFyNcL){return 1}}}return 0}function replace_big_select_inputs(a,b){if(!jQuery().autocomplete){return}if(a===undefined){a=20}if(b===undefined){b=3000}$("select").each(function(){var e=$(this);var h=e.find("option").length;if((h<a)||(h>b)){return}if(e.attr("multiple")==true){return}if(e.hasClass("no-autocomplete")){return}var l=e.attr("value");var c=$("<input type='text' class='text-and-autocomplete-select'></input>");c.attr("size",40);c.attr("name",e.attr("name"));c.attr("id",e.attr("id"));c.click(function(){var m=$(this).val();$(this).val("Loading...");$(this).showAllInCache();$(this).val(m);$(this).select()});var f=[];var i={};e.children("option").each(function(){var n =$(this).text();var m=$(this).attr("value");f.push(n);i[n]=m;i[m]=m;if(m==l){c.attr("value",n)}});if(l==""||l=="?"){c.attr("value","Click to Search or Select")}if(e.attr("name")=="dbkey"){f=f.sort(naturalSort)}var g={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:b,minChars:0,hideForLessThanMinChars:false};c.autocomplete(f,g);e.replaceWith(c);var k=function(){var n=c.attr("value");var m=i[n];if(m!==null&&m!==undefined){c.attr("value",m)}else{if(l!=""){c.attr("value",l)}else{c.attr("value","?")}}};c.parents("form").submit(function(){k()});$(document).bind("convert_dbkeys",function(){k()});if(e.attr("refresh_on_change")=="true"){var d=e.attr("refresh_on_change_values");if(d!==undefined){d=d.split(",")}var j=function(){var o=c.attr("value");var n=i[o];if(n!==null&&n!==undefined){refresh=false;if(d!==undefined){for(var m=0;m<d.length;m++){if(n==d[m]){refresh=true;break}}}else{refresh=true}if(refresh){c.attr("value",n);c.parents("form").submit()}}};c.bind ("result",j);c.keyup(function(m){if(m.keyCode===13){j()}});c.keydown(function(m){if(m.keyCode===13){return false}})}})}function async_save_text(d,f,e,a,c,h,i,g,b){if(c===undefined){c=30}if(i===undefined){i=4}$("#"+d).live("click",function(){if($("#renaming-active").length>0){return}var l=$("#"+f),k=l.text(),j;if(h){j=$("<textarea></textarea>").attr({rows:i,cols:c}).text(k)}else{j=$("<input type='text'></input>").attr({value:k,size:c})}j.attr("id","renaming-active");j.blur(function(){$(this).remove();l.show();if(b){b(j)}});j.keyup(function(n){if(n.keyCode===27){$(this).trigger("blur")}else{if(n.keyCode===13){var m={};m[a]=$(this).val();$(this).trigger("blur");$.ajax({url:e,data:m,error:function(){alert("Text editing for elt "+f+" failed")},success:function(o){l.text(o);if(b){b(j)}}})}}});if(g){g(j)}l.hide();j.insertAfter(l);j.focus();j.select();return})}function init_history_items(d,a,c){var b=function(){try{var e=$.jStore.store("history_expand_state");if(e){for(var g in e){$ ("#"+g+" div.historyItemBody").show()}}}catch(f){$.jStore.remove("history_expand_state")}if($.browser.mozilla){$("div.historyItemBody").each(function(){if(!$(this).is(":visible")){$(this).find("pre.peek").css("overflow","hidden")}})}d.each(function(){var j=this.id;var h=$(this).children("div.historyItemBody");var i=h.find("pre.peek");$(this).find(".historyItemTitleBar > .historyItemTitle").wrap("<a href='javascript:void(0);'></a>").click(function(){if(h.is(":visible")){if($.browser.mozilla){i.css("overflow","hidden")}h.slideUp("fast");if(!c){var k=$.jStore.store("history_expand_state");if(k){delete k[j];$.jStore.store("history_expand_state",k)}}}else{h.slideDown("fast",function(){if($.browser.mozilla){i.css("overflow","auto")}});if(!c){var k=$.jStore.store("history_expand_state");if(k===undefined){k={}}k[j]=true;$.jStore.store("history_expand_state",k)}}return false})});$("#top-links > a.toggle").click(function(){var h=$.jStore.store("history_expand_state");if(h===undefined) {h={}}$("div.historyItemBody:visible").each(function(){if($.browser.mozilla){$(this).find("pre.peek").css("overflow","hidden")}$(this).slideUp("fast");if(h){delete h[$(this).parent().attr("id")]}});$.jStore.store("history_expand_state",h)}).show()};if(a){b()}else{$.jStore.init("galaxy");$.jStore.engineReady(function(){b()})}}function commatize(b){b+="";var a=/(\d+)(\d{3})/;while(a.test(b)){b=b.replace(a,"$1,$2")}return b}function reset_tool_search(a){var c=$("#galaxy_tools").contents();if(c.length==0){c=$(document)}$(this).removeClass("search_active");c.find(".toolTitle").removeClass("search_match");c.find(".toolSectionBody").hide();c.find(".toolTitle").show();c.find(".toolPanelLabel").show();c.find(".toolSectionWrapper").each(function(){if($(this).attr("id")!="recently_used_wrapper"){$(this).show()}else{if($(this).hasClass("user_pref_visible")){$(this).show()}}});c.find("#search-no-results").hide();c.find("#search-spinner").hide();if(a){var b=c.find("#tool-search-query");b. val("search tools");b.css("font-style","italic")}}function GalaxyAsync(a){this.url_dict={};this.log_action=(a===undefined?false:a)}GalaxyAsync.prototype.set_func_url=function(a,b){this.url_dict[a]=b};GalaxyAsync.prototype.set_user_pref=function(a,b){var c=this.url_dict[arguments.callee];if(c===undefined){return false}$.ajax({url:c,data:{pref_name:a,pref_value:b},error:function(){return false},success:function(){return true}})};GalaxyAsync.prototype.log_user_action=function(c,b,d){if(!this.log_action){return}var a=this.url_dict[arguments.callee];if(a===undefined){return false}$.ajax({url:a,data:{action:c,context:b,params:d},error:function(){return false},success:function(){return true}})};$(document).ready(function(){$("a[confirm]").click(function(){return confirm($(this).attr("confirm"))});if($.fn.tipsy){$(".tooltip").tipsy({gravity:"s"})}make_popup_menus();replace_big_select_inputs(20,1500)}); --- a/static/scripts/packed/trackster.js +++ b/static/scripts/packed/trackster.js @@ -1,1 +1,1 @@ -var DENSITY=200,FEATURE_LEVELS=10,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_LOADING="Loading data...",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=30,CACHED_DATA=5,CONTEXT=$("<canvas></canvas>").get(0).getContext("2d"),PX_PER_CHAR=CONTEXT.measureText("A").width,RIGHT_STRAND,LEFT_STRAND;var right_img=new Image();right_img.src="/static/images/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var left_img=new Image();left_img.src="/static/images/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="/static/images/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="/static/images/visualization/strand_left_inv.png";left_img_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};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.key_ary.splice(a,1);this.key_ary.push(b)}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},clear:function(){this.obj_cache={};this.key_ary=[]}});var View=function(b,d,c,a){this.vis_id=c;this.dbkey=a;this.title=d;this.chrom=b;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.reset()};$.extend(View.prototype,{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);this.track_id_counter+=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)]},update_options:function(){this.has_changes=true;var b=$("ul#sortable-ul").sortable("toArray");for(var c in b){var e=b[c].split("_li")[0].split("track_")[1];$("#viewport").append($("#track_"+e))}for(var d in view.tracks){var a=view.tracks[d];if(a&&a.update_options){a.update_options(d)}}},reset:function(){this.low=this.max_low;this.high=this.max_high;$(".yaxislabel").remove()},redraw:function(f){var d=this.high-this.low,b=this.low,e=this.high;if(b<this.max_low){b=this.max_low}if(e>this.max_high){e=this.max_high}if(d<this.min_separation){e=b+this.min_separation}this.low=Math.floor(b);this.high=Math.ceil(e); 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))));$("#overview-box").css({left:(this.low/(this.max_high-this.max_low))*$("#overview-viewport").width(),width:Math.max(12,(this.high-this.low)/(this.max_high-this.max_low)*$("#overview-viewport").width())}).show();$("#low").val(commatize(this.low));$("#high").val(commatize(this.high));if(!f){for(var c=0,a=this.tracks.length;c<a;c++){if(this.tracks[c]&&this.tracks[c].enabled){this.tracks[c].draw()}}for(var c=0,a=this.label_tracks.length;c<a;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/c.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()}});var Track=function(a,b){this.name=a;this.parent_element=b;this.init_global()};$.extend(Track.prototype,{init_global:function(){this.header_div=$("<div class='track-header'>").text(this.name);this.content_div=$("<div class='track-content'>");this.container_div=$("<div />").addClass("track").append(this.header_div).append(this.content_div);this.parent_element.append(this.container_div)},init_each:function(c,b){var a=this;a.enabled=false;a.data_queue={};a.tile_cache.clear();a.data_cache.clear();if(!a.content_div.text()){a.content_div.text(DATA_LOADING)}a.container_div.removeClass("nodata error pending");if(a.view.chrom){$.getJSON(data_url,c,function(d){if(!d||d==="error"||d.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(d.message){var f=a.view.tracks.indexOf(a);var e=$("<a href='javascript :void(0);'></a>").attr("id",f+"_error");e.text("Click to view error");$("#"+f+"_error").live("click",function(){show_modal("Trackster Error","<pre>"+d.message+"</pre>",{Close:hide_modal})});a.content_div.append(e)}}else{if(d==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(d.data!==undefined&&(d.data===null||d.data.length===0)){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(d==="pending"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;b(d);a.draw()}}}}})}else{a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}}});var TiledTrack=function(){this.left_offset=200};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(){var i=this.view.low,e=this.view.high,f=e-i,d=this.view.resolution;var k=$("<div style='position: relative;'></div>"),l=this .content_div.width()/f,h;this.content_div.children(":first").remove();this.content_div.append(k),this.max_height=0;var a=Math.floor(i/d/DENSITY);while((a*DENSITY*d)<e){var j=this.content_div.width()+"_"+l+"_"+a;var c=this.tile_cache.get(j);if(c){var g=a*DENSITY*d;var b=(g-i)*l;if(this.left_offset){b-=this.left_offset}c.css({left:b});k.append(c);this.max_height=Math.max(this.max_height,c.height());this.content_div.css("height",this.max_height+"px")}else{this.delayed_draw(this,j,i,e,a,d,k,l)}a+=1}},delayed_draw:function(c,e,a,f,b,d,g,h){setTimeout(function(){if(!(a>c.view.high||f<c.view.low)){tile_element=c.draw_tile(d,b,g,h);if(tile_element){c.tile_cache.set(e,tile_element);c.max_height=Math.max(c.max_height,tile_element.height());c.content_div.css("height",c.max_height+"px")}}},50)}});var LabelTrack=function(a){Track.call(this,null,a);this.track_type="LabelTrack";this.hidden=true;this.container_div.addClass("label-track")};$.extend(LabelTrack.prototype,Track.prototype,{draw: function(){var c=this.view,d=c.high-c.low,g=Math.floor(Math.pow(10,Math.floor(Math.log(d)/Math.log(10)))),a=Math.floor(c.low/g)*g,e=this.content_div.width(),b=$("<div style='position: relative; height: 1.3em;'></div>");while(a<c.high){var f=(a-c.low)/d*e;b.append($("<div class='label'>"+commatize(a)+"</div>").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.content_div.append(b)}});var ReferenceTrack=function(){this.track_type="ReferenceTrack";Track.call(this,null,$("#top-labeltrack"));TiledTrack.call(this);this.hidden=true;this.height_px=12;this.container_div.addClass("reference-track");this.dummy_canvas=$("<canvas></canvas>").get(0).getContext("2d");this.data_queue={};this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE)};$.extend(ReferenceTrack.prototype,TiledTrack.prototype,{get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({ url:reference_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dbkey:this.view.dbkey},success:function(g){c.data_cache.set(e,g);delete c.data_queue[e];c.draw()},error:function(h,g,i){console.log(h,g,i)}})}},draw_tile:function(f,b,j,n){var g=b*DENSITY*f,d=DENSITY*f,e=$("<canvas class='tile'></canvas>"),m=e.get(0).getContext("2d"),i=f+"_"+b;if(n>PX_PER_CHAR){if(this.data_cache.get(i)===undefined){this.get_data(f,b);return}var l=this.data_cache.get(i);if(l===null){return}e.get(0).width=Math.ceil(d*n+this.left_offset);e.get(0).height=this.height_px;e.css({position:"absolute",top:0,left:(g-this.view.low)*n+this.left_offset});for(var h=0,k=l.length;h<k;h++){var a=Math.round(h*n);m.fillText(l[h],a+this.left_offset,10)}j.append(e);return e}}});var LineTrack=function(c,a,b){this.track_type="LineTrack";Track.call(this,c,$("#viewport"));TiledTrack.call(this);this.height_px=100;this.dataset_id=a;this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LI NE);this.prefs={min_value:undefined,max_value:undefined,mode:"Line"};if(b.min_value!==undefined){this.prefs.min_value=b.min_value}if(b.max_value!==undefined){this.prefs.max_value=b.max_value}if(b.mode!==undefined){this.prefs.mode=b.mode}};$.extend(LineTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b=a.view.tracks.indexOf(a);a.vertical_range=undefined;this.init_each({stats:true,chrom:a.view.chrom,low:null,high:null,dataset_id:a.dataset_id},function(c){a.container_div.addClass("line-track");data=c.data;if(isNaN(parseFloat(a.prefs.min_value))||isNaN(parseFloat(a.prefs.max_value))){a.prefs.min_value=data.min;a.prefs.max_value=data.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=data.total_frequency;$("#linetrack_"+b+"_minval").remove();$("#linetrack_"+b+"_maxval").remove();var e=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+" _minval").text(a.prefs.min_value);var d=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(a.prefs.max_value);d.css({position:"relative",top:"25px",left:"10px"});d.prependTo(a.container_div);e.css({position:"relative",top:a.height_px+55+"px",left:"10px"});e.prependTo(a.container_div)})},get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:data_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dataset_id:this.dataset_id,resolution:this.view.resolution},success:function(g){data=g.data;c.data_cache.set(e,data);delete c.data_queue[e];c.draw()},error:function(h,g,i){console.log(h,g,i)}})}},draw_tile:function(p,r,c,e){if(this.vertical_range===undefined){return}var s=r*DENSITY*p,a=DENSITY*p,b=$("<canvas class='tile'></canvas>"),v=p+"_"+r;if(this.data_cache.get(v)===undefined){this.get_data(p,r);return}var j=this.data_cache.get(v);if(j===null){return}b.css({position:"abs olute",top:0,left:(s-this.view.low)*e});b.get(0).width=Math.ceil(a*e+this.left_offset);b.get(0).height=this.height_px;var o=b.get(0).getContext("2d"),k=false,l=this.prefs.min_value,g=this.prefs.max_value,n=this.vertical_range,t=this.total_frequency,d=this.height_px,m=this.prefs.mode;o.beginPath();if(data.length>1){var f=Math.ceil((data[1][0]-data[0][0])*e)}else{var f=10}var u,h;for(var q=0;q<data.length;q++){u=(data[q][0]-s)*e;h=data[q][1];if(m=="Intensity"){if(h===null){continue}if(h<=l){h=l}else{if(h>=g){h=g}}h=255-Math.floor((h-l)/n*255);o.fillStyle="rgb("+h+","+h+","+h+")";o.fillRect(u,0,f,this.height_px)}else{if(h===null){if(k&&m==="Filled"){o.lineTo(u,d)}k=false;continue}else{if(h<=l){h=l}else{if(h>=g){h=g}}h=Math.round(d-(h-l)/n*d);if(k){o.lineTo(u,h)}else{k=true;if(m==="Filled"){o.moveTo(u,d);o.lineTo(u,h)}else{o.moveTo(u,h)}}}}}if(m==="Filled"){if(k){o.lineTo(u,d)}o.fill()}else{o.stroke()}c.append(b);return b},gen_options:function(n){var a=$("<div />").addClass("for m-row");var h="track_"+n+"_minval",l=$("<label></label>").attr("for",h).text("Min value:"),b=(this.prefs.min_value===undefined?"":this.prefs.min_value),m=$("<input></input>").attr("id",h).val(b),k="track_"+n+"_maxval",g=$("<label></label>").attr("for",k).text("Max value:"),j=(this.prefs.max_value===undefined?"":this.prefs.max_value),f=$("<input></input>").attr("id",k).val(j),e="track_"+n+"_mode",d=$("<label></label>").attr("for",e).text("Display mode:"),i=(this.prefs.mode===undefined?"Line":this.prefs.mode),c=$('<select id="'+e+'"><option value="Line" id="mode_Line">Line</option><option value="Filled" id="mode_Filled">Filled</option><option value="Intensity" id="mode_Intensity">Intensity</option></select>');c.children("#mode_"+i).attr("selected","selected");return a.append(l).append(m).append(g).append(f).append(d).append(c)},update_options:function(d){var a=$("#track_"+d+"_minval").val(),c=$("#track_"+d+"_maxval").val(),b=$("#track_"+d+"_mode option:selected").val();if(a!== this.prefs.min_value||c!==this.prefs.max_value||b!==this.prefs.mode){this.prefs.min_value=parseFloat(a);this.prefs.max_value=parseFloat(c);this.prefs.mode=b;this.vertical_range=this.prefs.max_value-this.prefs.min_value;$("#linetrack_"+d+"_minval").text(this.prefs.min_value);$("#linetrack_"+d+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.draw()}}});var FeatureTrack=function(c,a,b){this.track_type="FeatureTrack";Track.call(this,c,$("#viewport"));TiledTrack.call(this);this.height_px=100;this.container_div.addClass("feature-track");this.dataset_id=a;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.vertical_detail_px=10;this.vertical_nodetail_px=3;this.default_font="9px Monaco, Lucida Console, monospace";this.inc_slots={};this.data_queue={};this.s_e_by_tile={};this.tile_cache=new Cache(CACHED_TILES_FEATURE);this.data_cache=new Cache(20);this.prefs={block_color:"black",label_color:"black",show_counts:false};if(b.block_color!==undef ined){this.prefs.block_color=b.block_color}if(b.label_color!==undefined){this.prefs.label_color=b.label_color}if(b.show_counts!==undefined){this.prefs.show_counts=b.show_counts}};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b=a.view.max_low+"_"+a.view.max_high;a.mode="Auto";if(a.mode_div){a.mode_div.remove()}this.init_each({low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom,resolution:this.view.resolution},function(d){a.mode_div=$("<div class='right-float menubutton popup' />").text("Display Mode");a.header_div.append(a.mode_div);a.mode="Auto";var c=function(e){a.mode_div.text(e);a.mode=e;a.tile_cache.clear();a.draw()};make_popupmenu(a.mode_div,{Auto:function(){c("Auto")},Dense:function(){c("Dense")},Squish:function(){c("Squish")},Pack:function(){c("Pack")}});a.data_cache.set(b,d);a.draw()})},get_data:function(a,d){var b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.getJSON(data_url,{chrom:b.vie w.chrom,low:a,high:d,dataset_id:b.dataset_id,resolution:this.view.resolution,mode:this.mode},function(e){b.data_cache.set(c,e);delete b.data_queue[c];b.draw()})}},incremental_slots:function(a,h,c,r){if(!this.inc_slots[a]){this.inc_slots[a]={};this.inc_slots[a].w_scale=1/a;this.inc_slots[a].mode=r;this.s_e_by_tile[a]={}}var n=this.inc_slots[a].w_scale,z=[],l=0,b=$("<canvas></canvas>").get(0).getContext("2d"),o=this.view.max_low;var B=[];if(this.inc_slots[a].mode!==r){delete this.inc_slots[a];this.inc_slots[a]={mode:r,w_scale:n};delete this.s_e_by_tile[a];this.s_e_by_tile[a]={}}for(var w=0,x=h.length;w<x;w++){var g=h[w],m=g[0];if(this.inc_slots[a][m]!==undefined){l=Math.max(l,this.inc_slots[a][m]);B.push(this.inc_slots[a][m])}else{z.push(w)}}for(var w=0,x=z.length;w<x;w++){var g=h[z[w]],m=g[0],s=g[1],d=g[2],q=g[3],e=Math.floor((s-o)*n),f=Math.ceil((d-o)*n);if(q!==undefined&&!c){var t=b.measureText(q).width;if(e-t<0){f+=t}else{e-=t}}var v=0;while(true){var p=true;if(this.s_e_by _tile[a][v]!==undefined){for(var u=0,A=this.s_e_by_tile[a][v].length;u<A;u++){var y=this.s_e_by_tile[a][v][u];if(f>y[0]&&e<y[1]){p=false;break}}}if(p){if(this.s_e_by_tile[a][v]===undefined){this.s_e_by_tile[a][v]=[]}this.s_e_by_tile[a][v].push([e,f]);this.inc_slots[a][m]=v;l=Math.max(l,v);break}v++}}return l},rect_or_text:function(m,n,f,l,b,d,j,e,h){m.textAlign="center";var i=Math.round(n/2);if((this.mode==="Pack"||this.mode==="Auto")&&d!==undefined&&n>PX_PER_CHAR){m.fillStyle=this.prefs.block_color;m.fillRect(j,h+1,e,9);m.fillStyle="#eee";for(var g=0,k=d.length;g<k;g++){if(b+g>=f&&b+g<=l){var a=Math.floor(Math.max(0,(b+g-f)*n));m.fillText(d[g],a+this.left_offset+i,h+9)}}}else{m.fillStyle=this.prefs.block_color;m.fillRect(j,h+4,e,3)}},draw_tile:function(X,h,n,ak){var E=h*DENSITY*X,ad=(h+1)*DENSITY*X,D=DENSITY*X;var ae=E+"_"+ad;var z=this.data_cache.get(ae);if(z===undefined){this.data_queue[[E,ad]]=true;this.get_data(E,ad);return}var a=Math.ceil(D*ak),L=$("<canvas class='tile '></canvas>"),Z=this.prefs.label_color,f=this.prefs.block_color,m=this.mode,V=(m==="Squish")||(m==="Dense")&&(m!=="Pack")||(m==="Auto"&&(z.extra_info==="no_detail")),P=this.left_offset,aj,s,al;if(z.dataset_type==="summary_tree"){s=30}else{if(m==="Dense"){s=15;al=10}else{al=(V?this.vertical_nodetail_px:this.vertical_detail_px);s=this.incremental_slots(this.view.zoom_res,z.data,V,m)*al+15;aj=this.inc_slots[this.view.zoom_res]}}L.css({position:"absolute",top:0,left:(E-this.view.low)*ak-P});L.get(0).width=a+P;L.get(0).height=s;n.parent().css("height",Math.max(this.height_px,s)+"px");var A=L.get(0).getContext("2d");A.fillStyle=f;A.font=this.default_font;A.textAlign="right";if(z.dataset_type=="summary_tree"){var K,H=55,ac=255-H,g=ac*2/3,R=z.data,C=z.max,l=z.avg;if(R.length>2){var b=Math.ceil((R[1][0]-R[0][0])*ak)}else{var b=50}for(var ag=0,w=R.length;ag<w;ag++){var T=Math.ceil((R[ag][0]-E)*ak);var S=R[ag][1];if(!S){continue}K=Math.floor(ac-(S/C)*ac);A.fillStyle="rgb("+K+","+K+","+ K+")";A.fillRect(T+P,0,b,20);if(this.prefs.show_counts){if(K>g){A.fillStyle="black"}else{A.fillStyle="#ddd"}A.textAlign="center";A.fillText(R[ag][1],T+P+(b/2),12)}}n.append(L);return L}var ai=z.data;var af=0;for(var ag=0,w=ai.length;ag<w;ag++){var M=ai[ag],J=M[0],ah=M[1],U=M[2],F=M[3];if(ah<=ad&&U>=E){var W=Math.floor(Math.max(0,(ah-E)*ak)),B=Math.ceil(Math.min(a,Math.max(0,(U-E)*ak))),Q=(m==="Dense"?0:aj[J]*al);if(z.dataset_type==="bai"){A.fillStyle=f;if(M[4] instanceof Array){var t=Math.floor(Math.max(0,(M[4][0]-E)*ak)),I=Math.ceil(Math.min(a,Math.max(0,(M[4][1]-E)*ak))),r=Math.floor(Math.max(0,(M[5][0]-E)*ak)),p=Math.ceil(Math.min(a,Math.max(0,(M[5][1]-E)*ak)));if(M[4][1]>=E&&M[4][0]<=ad){this.rect_or_text(A,ak,E,ad,M[4][0],M[4][2],t+P,I-t,Q)}if(M[5][1]>=E&&M[5][0]<=ad){this.rect_or_text(A,ak,E,ad,M[5][0],M[5][2],r+P,p-r,Q)}if(r>I){A.fillStyle="#999";A.fillRect(I+P,Q+5,r-I,1)}}else{A.fillStyle=f;this.rect_or_text(A,ak,E,ad,ah,F,W+P,B-W,Q)}if(m!=="Dense"&&!V&&ah>E){A.fillS tyle=this.prefs.label_color;if(h===0&&W-A.measureText(F).width<0){A.textAlign="left";A.fillText(J,B+2+P,Q+8)}else{A.textAlign="right";A.fillText(J,W-2+P,Q+8)}A.fillStyle=f}}else{if(z.dataset_type==="interval_index"){if(V){A.fillRect(W+P,Q+5,B-W,1)}else{var v=M[4],O=M[5],Y=M[6],e=M[7];var u,aa,G=null,am=null;if(O&&Y){G=Math.floor(Math.max(0,(O-E)*ak));am=Math.ceil(Math.min(a,Math.max(0,(Y-E)*ak)))}if(m!=="Dense"&&F!==undefined&&ah>E){A.fillStyle=Z;if(h===0&&W-A.measureText(F).width<0){A.textAlign="left";A.fillText(F,B+2+P,Q+8)}else{A.textAlign="right";A.fillText(F,W-2+P,Q+8)}A.fillStyle=f}if(e){if(v){if(v=="+"){A.fillStyle=RIGHT_STRAND}else{if(v=="-"){A.fillStyle=LEFT_STRAND}}A.fillRect(W+P,Q,B-W,10);A.fillStyle=f}for(var ae=0,d=e.length;ae<d;ae++){var o=e[ae],c=Math.floor(Math.max(0,(o[0]-E)*ak)),N=Math.ceil(Math.min(a,Math.max((o[1]-E)*ak)));if(c>N){continue}u=5;aa=3;A.fillRect(c+P,Q+aa,N-c,u);if(G!==undefined&&!(c>am||N<G)){u=9;aa=1;var ab=Math.max(c,G),q=Math.min(N,am);A. fillRect(ab+P,Q+aa,q-ab,u)}}}else{u=9;aa=1;A.fillRect(W+P,Q+aa,B-W,u);if(M.strand){if(M.strand=="+"){A.fillStyle=RIGHT_STRAND_INV}else{if(M.strand=="-"){A.fillStyle=LEFT_STRAND_INV}}A.fillRect(W+P,Q,B-W,10);A.fillStyle=prefs.block_color}}}}}af++}}n.append(L);return L},gen_options:function(i){var a=$("<div />").addClass("form-row");var e="track_"+i+"_block_color",k=$("<label />").attr("for",e).text("Block color:"),l=$("<input />").attr("id",e).attr("name",e).val(this.prefs.block_color),j="track_"+i+"_label_color",g=$("<label />").attr("for",j).text("Text color:"),h=$("<input />").attr("id",j).attr("name",j).val(this.prefs.label_color),f="track_"+i+"_show_count",c=$("<label />").attr("for",f).text("Show summary counts"),b=$('<input type="checkbox" style="float:left;"></input>').attr("id",f).attr("name",f).attr("checked",this.prefs.show_counts),d=$("<div />").append(b).append(c);return a.append(k).append(l).append(g).append(h).append(d)},update_options:function(e){var b=$("#tra ck_"+e+"_block_color").val(),d=$("#track_"+e+"_label_color").val(),c=$("#track_"+e+"_mode option:selected").val(),a=$("#track_"+e+"_show_count").attr("checked");if(b!==this.prefs.block_color||d!==this.prefs.label_color||a!==this.prefs.show_counts){this.prefs.block_color=b;this.prefs.label_color=d;this.prefs.show_counts=a;this.tile_cache.clear();this.draw()}}});var ReadTrack=function(c,a,b){FeatureTrack.call(this,c,a,b);this.track_type="ReadTrack";this.vertical_detail_px=10;this.vertical_nodetail_px=5};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{}); +var DENSITY=200,FEATURE_LEVELS=10,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_LOADING="Loading data...",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=30,CACHED_DATA=5,CONTEXT=$("<canvas></canvas>").get(0).getContext("2d"),PX_PER_CHAR=CONTEXT.measureText("A").width,RIGHT_STRAND,LEFT_STRAND;var right_img=new Image();right_img.src="/static/images/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var left_img=new Image();left_img.src="/static/images/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="/static/images/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="/static/images/visualization/strand_left_inv.png";left_img_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};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.key_ary.splice(a,1);this.key_ary.push(b)}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},clear:function(){this.obj_cache={};this.key_ary=[]}});var View=function(a,c,e,d,b){this.container=a;this.vis_id=d;this.dbkey=b;this.title=e;this.chrom=c;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init();this.reset()};$.extend(View.p rototype,{init:function(){var c=this.container,a=this;this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(c);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.content_div);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.viewport=$("<div/>").addClass("viewport").appendTo(this.viewport_container);this.nav_container=$("<div/>").addClass("nav-container").appendTo(c);this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.nav_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.nav);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_form =$("<form/>").attr("action",function(){void (0)}).appendTo(this.nav_controls);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.chrom_form);this.low_input=$("<input/>").addClass("low").css("width","10em").appendTo(this.chrom_form);$("<span/>").text(" - ").appendTo(this.chrom_form);this.high_input=$("<input/>").addClass("high").css("width","10em").appendTo(this.chrom_form);this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.chrom_form);this.zi_link=$("<a/>").click(function(){a.zoom_in();a.redraw()}).html('<img src="/images/fugue/magnifier-zoom.png" />').appendTo(this.chrom_form);this.zo_link=$("<a/>").click(function(){a.zoom_out();a.redraw()}).html('<img src="/images/fugue/magnifier-zoom-out.png" />').appendTo(this.chrom_form);var b=(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey});$.ajax({url:chrom_url,data:b,dataType: "json",success:function(d){if(d.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=d.chrom_info;var f='<option value="">Select Chrom/Contig</option>';for(i in a.chrom_data){var e=a.chrom_data[i]["chrom"];f+='<option value="'+e+'">'+e+"</option>"}a.chrom_select.html(f);a.chrom_select.bind("change",function(){a.chrom=a.chrom_select.val();var h=$.grep(a.chrom_data,function(k,l){return k.chrom===a.chrom})[0];a.max_high=h.len;a.reset();a.redraw(true);for(var j in a.tracks){var g=a.tracks[j];if(g.init){g.init()}}a.redraw()})},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}});this.content_div.bind("mousewheel",function(d,f){if(Math.abs(f)<0.5){return}if(f>0){a.zoom_in(d.pageX,this.viewport_container)}else{a.zoom_out()}d.preventDefault()});this.content_div.bind("dblclick",function(d){a.zoom_in(d.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(d){this.current_x=d.offsetX}).bind("drag",function(d){var g=d.offsetX-this .current_x;this.current_x=d.offsetX;var f=Math.round(g/a.viewport_container.width()*(a.high-a.low));a.move_delta(-2*f)});this.viewport_container.bind("dragstart",function(d){this.original_low=a.low;this.current_height=d.clientY;this.current_x=d.offsetX}).bind("drag",function(g){var d=$(this);var j=g.offsetX-this.current_x;var f=d.scrollTop()-(g.clientY-this.current_height);if(f<d.get(0).scrollHeight-d.height()){d.scrollTop(f)}this.current_height=g.clientY;this.current_x=g.offsetX;var h=Math.round(j/a.viewport_container.width()*(a.high-a.low));a.move_delta(h)});this.top_labeltrack.bind("dragstart",function(d){this.drag_origin_x=d.clientX;this.drag_origin_pos=d.clientX/a.viewport_container.width()*(a.high-a.low)+a.low;this.drag_div=$("<div />").css({height:a.content_div.height(),top:"0px",position:"absolute","background-color":"#cfc",border:"1px solid #6a6",opacity:0.5}).appendTo($(this))}).bind("drag",function(j){var f=Math.min(j.clientX,this.drag_origin_x),d=Math.max(j.clien tX,this.drag_origin_x),h=(a.high-a.low),g=a.viewport_container.width();a.low_input.val(commatize(Math.round(f/g*h)+a.low));a.high_input.val(commatize(Math.round(d/g*h)+a.low));this.drag_div.css({left:f+"px",width:(d-f)+"px"})}).bind("dragend",function(k){var f=Math.min(k.clientX,this.drag_origin_x),d=Math.max(k.clientX,this.drag_origin_x),h=(a.high-a.low),g=a.viewport_container.width(),j=a.low;a.low=Math.round(f/g*h)+j;a.high=Math.round(d/g*h)+j;this.drag_div.remove();a.redraw()});this.add_label_track(new LabelTrack(this,this.top_labeltrack));this.add_label_track(new LabelTrack(this,this.nav_labeltrack))},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);this.trac k_id_counter+=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)]},update_options:function(){this.has_changes=true;var b=$("ul#sortable-ul").sortable("toArray");for(var c in b){var e=b[c].split("_li")[0].split("track_")[1];this.viewport.append($("#track_"+e))}for(var d in view.tracks){var a=view.tracks[d];if(a&&a.update_options){a.update_options(d)}}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},redraw:function(f){var d=this.high-this.low,b=this.low,e=this.high;if(b<this.max_low){b=this.max_low}if(e>this.max_high){e=this.max_high}if(d<this.min_separation){e=b+this.min_separation}this.low=Math.floor(b);this.high=Math.ceil(e);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))));this.overview_box.css({left:(this.low/(this.max_high-this.max_low))*this.overview_viewport.width(),width:Math.max(12,(this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())}).show();this.low_input.val(commatize(this.low));this.high_input.val(commatize(this.high));if(!f){for(var c=0,a=this.tracks.length;c<a;c++){if(this.tracks[c]&&this.tracks[c].enabled){this.tracks[c].draw()}}for(var c=0,a=this.label_tracks.length;c<a;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()}});var Track=function(b,a,c){this.name=b;this.parent_element=c;this.view=a;this.init_global()};$.extend(Track.prototype,{init_global:function(){this.header_div=$("<div class='track-header'>").text(this.name);this.content_div=$("<div class='track-content'>");this.container_div=$("<div />").addClass("track").append(this.header_div).append(this.content_div);this.parent_element.append(this.container_div)},init_each:function(c,b){var a=this;a.enabled=false;a.data_queue={};a.tile_cache.clear();a.data_cache.clear();if(!a.content_div.text()){a.content_div.text(DATA_LOADING)}a.container_div.removeClass("nodata error pending");if(a.view.chrom){$.getJSON(data_url,c,function(d){if(!d||d==="error"||d.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(d.message){var f=a.view.tracks.indexOf(a);var e=$("<a href='javascript:void(0);'></a>").attr("id",f+"_error");e.text("Click to view error");$(" #"+f+"_error").live("click",function(){show_modal("Trackster Error","<pre>"+d.message+"</pre>",{Close:hide_modal})});a.content_div.append(e)}}else{if(d==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(d.data!==undefined&&(d.data===null||d.data.length===0)){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(d==="pending"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;b(d);a.draw()}}}}})}else{a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}}});var TiledTrack=function(){this.left_offset=200};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(){var j=this.view.low,e=this.view.high,f=e-j,d=this.view.resolution;var l=$("<div style='position: relative;'></div>"),m=this.content_div.width()/f,h;this.content_div.children(":first").remove();thi s.content_div.append(l),this.max_height=0;var a=Math.floor(j/d/DENSITY);while((a*DENSITY*d)<e){var k=this.content_div.width()+"_"+m+"_"+a;var c=this.tile_cache.get(k);if(c){var g=a*DENSITY*d;var b=(g-j)*m;if(this.left_offset){b-=this.left_offset}c.css({left:b});l.append(c);this.max_height=Math.max(this.max_height,c.height());this.content_div.css("height",this.max_height+"px")}else{this.delayed_draw(this,k,j,e,a,d,l,m)}a+=1}},delayed_draw:function(c,e,a,f,b,d,g,h){setTimeout(function(){if(!(a>c.view.high||f<c.view.low)){tile_element=c.draw_tile(d,b,g,h);if(tile_element){c.tile_cache.set(e,tile_element);c.max_height=Math.max(c.max_height,tile_element.height());c.content_div.css("height",c.max_height+"px")}}},50)}});var LabelTrack=function(a,b){Track.call(this,null,a,b);this.track_type="LabelTrack";this.hidden=true;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,Ma th.floor(Math.log(d)/Math.log(10)))),a=Math.floor(c.low/g)*g,e=this.content_div.width(),b=$("<div style='position: relative; height: 1.3em;'></div>");while(a<c.high){var f=(a-c.low)/d*e;b.append($("<div class='label'>"+commatize(a)+"</div>").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.content_div.append(b)}});var ReferenceTrack=function(a){this.track_type="ReferenceTrack";Track.call(this,null,a,a.nav_labeltrack);TiledTrack.call(this);this.hidden=true;this.height_px=12;this.container_div.addClass("reference-track");this.dummy_canvas=$("<canvas></canvas>").get(0).getContext("2d");this.data_queue={};this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE)};$.extend(ReferenceTrack.prototype,TiledTrack.prototype,{get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:reference_url,dataType:"json",data:{chrom:this.view.chrom,low:a,hi gh:f,dbkey:this.view.dbkey},success:function(g){c.data_cache.set(e,g);delete c.data_queue[e];c.draw()},error:function(h,g,j){console.log(h,g,j)}})}},draw_tile:function(f,b,k,o){var g=b*DENSITY*f,d=DENSITY*f,e=$("<canvas class='tile'></canvas>"),n=e.get(0).getContext("2d"),j=f+"_"+b;if(o>PX_PER_CHAR){if(this.data_cache.get(j)===undefined){this.get_data(f,b);return}var m=this.data_cache.get(j);if(m===null){return}e.get(0).width=Math.ceil(d*o+this.left_offset);e.get(0).height=this.height_px;e.css({position:"absolute",top:0,left:(g-this.view.low)*o+this.left_offset});for(var h=0,l=m.length;h<l;h++){var a=Math.round(h*o);n.fillText(m[h],a+this.left_offset,10)}k.append(e);return e}}});var LineTrack=function(d,b,a,c){this.track_type="LineTrack";Track.call(this,d,b,b.viewport_container);TiledTrack.call(this);this.height_px=100;this.dataset_id=a;this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE);this.prefs={min_value:undefined,max_value:undefined,mode :"Line"};if(c.min_value!==undefined){this.prefs.min_value=c.min_value}if(c.max_value!==undefined){this.prefs.max_value=c.max_value}if(c.mode!==undefined){this.prefs.mode=c.mode}};$.extend(LineTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b=a.view.tracks.indexOf(a);a.vertical_range=undefined;this.init_each({stats:true,chrom:a.view.chrom,low:null,high:null,dataset_id:a.dataset_id},function(c){a.container_div.addClass("line-track");data=c.data;if(isNaN(parseFloat(a.prefs.min_value))||isNaN(parseFloat(a.prefs.max_value))){a.prefs.min_value=data.min;a.prefs.max_value=data.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=data.total_frequency;$("#linetrack_"+b+"_minval").remove();$("#linetrack_"+b+"_maxval").remove();var e=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(a.prefs.min_value);var d=$("<div />").addClas s("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(a.prefs.max_value);d.css({position:"relative",top:"25px",left:"10px"});d.prependTo(a.container_div);e.css({position:"relative",top:a.height_px+55+"px",left:"10px"});e.prependTo(a.container_div)})},get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:data_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dataset_id:this.dataset_id,resolution:this.view.resolution},success:function(g){data=g.data;c.data_cache.set(e,data);delete c.data_queue[e];c.draw()},error:function(h,g,j){console.log(h,g,j)}})}},draw_tile:function(p,r,c,e){if(this.vertical_range===undefined){return}var s=r*DENSITY*p,a=DENSITY*p,b=$("<canvas class='tile'></canvas>"),v=p+"_"+r;if(this.data_cache.get(v)===undefined){this.get_data(p,r);return}var j=this.data_cache.get(v);if(j===null){return}b.css({position:"absolute",top:0,left:(s-this.view.low)*e});b.get(0).width=Math. ceil(a*e+this.left_offset);b.get(0).height=this.height_px;var o=b.get(0).getContext("2d"),k=false,l=this.prefs.min_value,g=this.prefs.max_value,n=this.vertical_range,t=this.total_frequency,d=this.height_px,m=this.prefs.mode;o.beginPath();if(data.length>1){var f=Math.ceil((data[1][0]-data[0][0])*e)}else{var f=10}var u,h;for(var q=0;q<data.length;q++){u=(data[q][0]-s)*e;h=data[q][1];if(m=="Intensity"){if(h===null){continue}if(h<=l){h=l}else{if(h>=g){h=g}}h=255-Math.floor((h-l)/n*255);o.fillStyle="rgb("+h+","+h+","+h+")";o.fillRect(u,0,f,this.height_px)}else{if(h===null){if(k&&m==="Filled"){o.lineTo(u,d)}k=false;continue}else{if(h<=l){h=l}else{if(h>=g){h=g}}h=Math.round(d-(h-l)/n*d);if(k){o.lineTo(u,h)}else{k=true;if(m==="Filled"){o.moveTo(u,d);o.lineTo(u,h)}else{o.moveTo(u,h)}}}}}if(m==="Filled"){if(k){o.lineTo(u,d)}o.fill()}else{o.stroke()}c.append(b);return b},gen_options:function(o){var a=$("<div />").addClass("form-row");var h="track_"+o+"_minval",m=$("<label></label>").at tr("for",h).text("Min value:"),b=(this.prefs.min_value===undefined?"":this.prefs.min_value),n=$("<input></input>").attr("id",h).val(b),l="track_"+o+"_maxval",g=$("<label></label>").attr("for",l).text("Max value:"),k=(this.prefs.max_value===undefined?"":this.prefs.max_value),f=$("<input></input>").attr("id",l).val(k),e="track_"+o+"_mode",d=$("<label></label>").attr("for",e).text("Display mode:"),j=(this.prefs.mode===undefined?"Line":this.prefs.mode),c=$('<select id="'+e+'"><option value="Line" id="mode_Line">Line</option><option value="Filled" id="mode_Filled">Filled</option><option value="Intensity" id="mode_Intensity">Intensity</option></select>');c.children("#mode_"+j).attr("selected","selected");return a.append(m).append(n).append(g).append(f).append(d).append(c)},update_options:function(d){var a=$("#track_"+d+"_minval").val(),c=$("#track_"+d+"_maxval").val(),b=$("#track_"+d+"_mode option:selected").val();if(a!==this.prefs.min_value||c!==this.prefs.max_value||b!==this.pre fs.mode){this.prefs.min_value=parseFloat(a);this.prefs.max_value=parseFloat(c);this.prefs.mode=b;this.vertical_range=this.prefs.max_value-this.prefs.min_value;$("#linetrack_"+d+"_minval").text(this.prefs.min_value);$("#linetrack_"+d+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.draw()}}});var FeatureTrack=function(d,b,a,c){this.track_type="FeatureTrack";Track.call(this,d,b,b.viewport_container);TiledTrack.call(this);this.height_px=0;this.container_div.addClass("feature-track");this.dataset_id=a;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.vertical_detail_px=10;this.vertical_nodetail_px=3;this.default_font="9px Monaco, Lucida Console, monospace";this.inc_slots={};this.data_queue={};this.s_e_by_tile={};this.tile_cache=new Cache(CACHED_TILES_FEATURE);this.data_cache=new Cache(20);this.prefs={block_color:"black",label_color:"black",show_counts:false};if(c.block_color!==undefined){this.prefs.block_color=c.block_color}if(c.labe l_color!==undefined){this.prefs.label_color=c.label_color}if(c.show_counts!==undefined){this.prefs.show_counts=c.show_counts}};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b=a.view.max_low+"_"+a.view.max_high;a.mode="Auto";if(a.mode_div){a.mode_div.remove()}this.init_each({low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom,resolution:this.view.resolution},function(d){a.mode_div=$("<div class='right-float menubutton popup' />").text("Display Mode");a.header_div.append(a.mode_div);a.mode="Auto";var c=function(e){a.mode_div.text(e);a.mode=e;a.tile_cache.clear();a.draw()};make_popupmenu(a.mode_div,{Auto:function(){c("Auto")},Dense:function(){c("Dense")},Squish:function(){c("Squish")},Pack:function(){c("Pack")}});a.data_cache.set(b,d);a.draw()})},get_data:function(a,d){var b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.getJSON(data_url,{chrom:b.view.chrom,low:a,high:d,dataset_id:b.dataset_id,resolut ion:this.view.resolution,mode:this.mode},function(e){b.data_cache.set(c,e);delete b.data_queue[c];b.draw()})}},incremental_slots:function(a,h,c,r){if(!this.inc_slots[a]){this.inc_slots[a]={};this.inc_slots[a].w_scale=1/a;this.inc_slots[a].mode=r;this.s_e_by_tile[a]={}}var n=this.inc_slots[a].w_scale,z=[],l=0,b=$("<canvas></canvas>").get(0).getContext("2d"),o=this.view.max_low;var B=[];if(this.inc_slots[a].mode!==r){delete this.inc_slots[a];this.inc_slots[a]={mode:r,w_scale:n};delete this.s_e_by_tile[a];this.s_e_by_tile[a]={}}for(var w=0,x=h.length;w<x;w++){var g=h[w],m=g[0];if(this.inc_slots[a][m]!==undefined){l=Math.max(l,this.inc_slots[a][m]);B.push(this.inc_slots[a][m])}else{z.push(w)}}for(var w=0,x=z.length;w<x;w++){var g=h[z[w]],m=g[0],s=g[1],d=g[2],q=g[3],e=Math.floor((s-o)*n),f=Math.ceil((d-o)*n);if(q!==undefined&&!c){var t=b.measureText(q).width;if(e-t<0){f+=t}else{e-=t}}var v=0;while(true){var p=true;if(this.s_e_by_tile[a][v]!==undefined){for(var u=0,A=this.s_e_by_t ile[a][v].length;u<A;u++){var y=this.s_e_by_tile[a][v][u];if(f>y[0]&&e<y[1]){p=false;break}}}if(p){if(this.s_e_by_tile[a][v]===undefined){this.s_e_by_tile[a][v]=[]}this.s_e_by_tile[a][v].push([e,f]);this.inc_slots[a][m]=v;l=Math.max(l,v);break}v++}}return l},rect_or_text:function(n,o,f,m,b,d,k,e,h){n.textAlign="center";var j=Math.round(o/2);if((this.mode==="Pack"||this.mode==="Auto")&&d!==undefined&&o>PX_PER_CHAR){n.fillStyle=this.prefs.block_color;n.fillRect(k,h+1,e,9);n.fillStyle="#eee";for(var g=0,l=d.length;g<l;g++){if(b+g>=f&&b+g<=m){var a=Math.floor(Math.max(0,(b+g-f)*o));n.fillText(d[g],a+this.left_offset+j,h+9)}}}else{n.fillStyle=this.prefs.block_color;n.fillRect(k,h+4,e,3)}},draw_tile:function(X,h,n,ak){var E=h*DENSITY*X,ad=(h+1)*DENSITY*X,D=DENSITY*X;var ae=E+"_"+ad;var z=this.data_cache.get(ae);if(z===undefined){this.data_queue[[E,ad]]=true;this.get_data(E,ad);return}var a=Math.ceil(D*ak),L=$("<canvas class='tile'></canvas>"),Z=this.prefs.label_color,f=this.prefs. block_color,m=this.mode,V=(m==="Squish")||(m==="Dense")&&(m!=="Pack")||(m==="Auto"&&(z.extra_info==="no_detail")),P=this.left_offset,aj,s,al;if(z.dataset_type==="summary_tree"){s=30}else{if(m==="Dense"){s=15;al=10}else{al=(V?this.vertical_nodetail_px:this.vertical_detail_px);s=this.incremental_slots(this.view.zoom_res,z.data,V,m)*al+15;aj=this.inc_slots[this.view.zoom_res]}}L.css({position:"absolute",top:0,left:(E-this.view.low)*ak-P});L.get(0).width=a+P;L.get(0).height=s;n.parent().css("height",Math.max(this.height_px,s)+"px");var A=L.get(0).getContext("2d");A.fillStyle=f;A.font=this.default_font;A.textAlign="right";if(z.dataset_type=="summary_tree"){var K,H=55,ac=255-H,g=ac*2/3,R=z.data,C=z.max,l=z.avg;if(R.length>2){var b=Math.ceil((R[1][0]-R[0][0])*ak)}else{var b=50}for(var ag=0,w=R.length;ag<w;ag++){var T=Math.ceil((R[ag][0]-E)*ak);var S=R[ag][1];if(!S){continue}K=Math.floor(ac-(S/C)*ac);A.fillStyle="rgb("+K+","+K+","+K+")";A.fillRect(T+P,0,b,20);if(this.prefs.show_coun ts){if(K>g){A.fillStyle="black"}else{A.fillStyle="#ddd"}A.textAlign="center";A.fillText(R[ag][1],T+P+(b/2),12)}}n.append(L);return L}var ai=z.data;var af=0;for(var ag=0,w=ai.length;ag<w;ag++){var M=ai[ag],J=M[0],ah=M[1],U=M[2],F=M[3];if(ah<=ad&&U>=E){var W=Math.floor(Math.max(0,(ah-E)*ak)),B=Math.ceil(Math.min(a,Math.max(0,(U-E)*ak))),Q=(m==="Dense"?0:aj[J]*al);if(z.dataset_type==="bai"){A.fillStyle=f;if(M[4] instanceof Array){var t=Math.floor(Math.max(0,(M[4][0]-E)*ak)),I=Math.ceil(Math.min(a,Math.max(0,(M[4][1]-E)*ak))),r=Math.floor(Math.max(0,(M[5][0]-E)*ak)),p=Math.ceil(Math.min(a,Math.max(0,(M[5][1]-E)*ak)));if(M[4][1]>=E&&M[4][0]<=ad){this.rect_or_text(A,ak,E,ad,M[4][0],M[4][2],t+P,I-t,Q)}if(M[5][1]>=E&&M[5][0]<=ad){this.rect_or_text(A,ak,E,ad,M[5][0],M[5][2],r+P,p-r,Q)}if(r>I){A.fillStyle="#999";A.fillRect(I+P,Q+5,r-I,1)}}else{A.fillStyle=f;this.rect_or_text(A,ak,E,ad,ah,F,W+P,B-W,Q)}if(m!=="Dense"&&!V&&ah>E){A.fillStyle=this.prefs.label_color;if(h===0&&W-A.measureTex t(F).width<0){A.textAlign="left";A.fillText(J,B+2+P,Q+8)}else{A.textAlign="right";A.fillText(J,W-2+P,Q+8)}A.fillStyle=f}}else{if(z.dataset_type==="interval_index"){if(V){A.fillRect(W+P,Q+5,B-W,1)}else{var v=M[4],O=M[5],Y=M[6],e=M[7];var u,aa,G=null,am=null;if(O&&Y){G=Math.floor(Math.max(0,(O-E)*ak));am=Math.ceil(Math.min(a,Math.max(0,(Y-E)*ak)))}if(m!=="Dense"&&F!==undefined&&ah>E){A.fillStyle=Z;if(h===0&&W-A.measureText(F).width<0){A.textAlign="left";A.fillText(F,B+2+P,Q+8)}else{A.textAlign="right";A.fillText(F,W-2+P,Q+8)}A.fillStyle=f}if(e){if(v){if(v=="+"){A.fillStyle=RIGHT_STRAND}else{if(v=="-"){A.fillStyle=LEFT_STRAND}}A.fillRect(W+P,Q,B-W,10);A.fillStyle=f}for(var ae=0,d=e.length;ae<d;ae++){var o=e[ae],c=Math.floor(Math.max(0,(o[0]-E)*ak)),N=Math.ceil(Math.min(a,Math.max((o[1]-E)*ak)));if(c>N){continue}u=5;aa=3;A.fillRect(c+P,Q+aa,N-c,u);if(G!==undefined&&!(c>am||N<G)){u=9;aa=1;var ab=Math.max(c,G),q=Math.min(N,am);A.fillRect(ab+P,Q+aa,q-ab,u)}}}else{u=9;aa=1;A.fillRec t(W+P,Q+aa,B-W,u);if(M.strand){if(M.strand=="+"){A.fillStyle=RIGHT_STRAND_INV}else{if(M.strand=="-"){A.fillStyle=LEFT_STRAND_INV}}A.fillRect(W+P,Q,B-W,10);A.fillStyle=prefs.block_color}}}}}af++}}n.append(L);return L},gen_options:function(j){var a=$("<div />").addClass("form-row");var e="track_"+j+"_block_color",l=$("<label />").attr("for",e).text("Block color:"),m=$("<input />").attr("id",e).attr("name",e).val(this.prefs.block_color),k="track_"+j+"_label_color",g=$("<label />").attr("for",k).text("Text color:"),h=$("<input />").attr("id",k).attr("name",k).val(this.prefs.label_color),f="track_"+j+"_show_count",c=$("<label />").attr("for",f).text("Show summary counts"),b=$('<input type="checkbox" style="float:left;"></input>').attr("id",f).attr("name",f).attr("checked",this.prefs.show_counts),d=$("<div />").append(b).append(c);return a.append(l).append(m).append(g).append(h).append(d)},update_options:function(e){var b=$("#track_"+e+"_block_color").val(),d=$("#track_"+e+"_label _color").val(),c=$("#track_"+e+"_mode option:selected").val(),a=$("#track_"+e+"_show_count").attr("checked");if(b!==this.prefs.block_color||d!==this.prefs.label_color||a!==this.prefs.show_counts){this.prefs.block_color=b;this.prefs.label_color=d;this.prefs.show_counts=a;this.tile_cache.clear();this.draw()}}});var ReadTrack=function(d,b,a,c){FeatureTrack.call(this,d,b,a,c);this.track_type="ReadTrack";this.vertical_detail_px=10;this.vertical_nodetail_px=5};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{}); --- a/static/scripts/trackster.js +++ b/static/scripts/trackster.js @@ -69,7 +69,8 @@ var Cache = function( num_elements ) { } }); -var View = function( chrom, title, vis_id, dbkey ) { +var View = function( container, chrom, title, vis_id, dbkey ) { + this.container = container; this.vis_id = vis_id; this.dbkey = dbkey; this.title = title; @@ -82,22 +83,184 @@ var View = function( chrom, title, vis_i this.zoom_factor = 3; this.min_separation = 30; this.has_changes = false; + this.init(); this.reset(); }; $.extend( View.prototype, { - add_track: function ( track ) { + init: function() { + // Create DOM elements + var parent_element = this.container, + view = this; + + this.content_div = $("<div/>").addClass("content").css("position", "relative").appendTo(parent_element); + this.top_labeltrack = $("<div/>").addClass("top-labeltrack").appendTo(this.content_div); + this.viewport_container = $("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div); + this.viewport = $("<div/>").addClass("viewport").appendTo(this.viewport_container); + + this.nav_container = $("<div/>").addClass("nav-container").appendTo(parent_element); + this.nav_labeltrack = $("<div/>").addClass("nav-labeltrack").appendTo(this.nav_container); + this.nav = $("<div/>").addClass("nav").appendTo(this.nav_container); + this.overview = $("<div/>").addClass("overview").appendTo(this.nav); + this.overview_viewport = $("<div/>").addClass("overview-viewport").appendTo(this.overview); + this.overview_box = $("<div/>").addClass("overview-box").appendTo(this.overview_viewport); + + this.nav_controls = $("<div/>").addClass("nav-controls").appendTo(this.nav); + this.chrom_form = $("<form/>").attr("action", function() { void(0); } ).appendTo(this.nav_controls); + this.chrom_select = $("<select/>").attr({ "name": "chrom"}).css("width", "15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.chrom_form); + this.low_input = $("<input/>").addClass("low").css("width", "10em").appendTo(this.chrom_form); + $("<span/>").text(" - ").appendTo(this.chrom_form); + this.high_input = $("<input/>").addClass("high").css("width", "10em").appendTo(this.chrom_form); + this.hidden_input = $("<input/>").attr("type", "hidden").val(this.vis_id).appendTo(this.chrom_form); + this.zi_link = $("<a/>").click(function() { view.zoom_in(); view.redraw() }).html('<img src="/images/fugue/magnifier-zoom.png" />').appendTo(this.chrom_form); + this.zo_link = $("<a/>").click(function() { view.zoom_out(); view.redraw() }).html('<img src="/images/fugue/magnifier-zoom-out.png" />').appendTo(this.chrom_form);; + + var data_d = (this.vis_id !== undefined ? { vis_id: this.vis_id } : { dbkey: this.dbkey }); + + $.ajax({ + url: chrom_url, + data: data_d, + dataType: "json", + success: function ( result ) { + if (result['reference']) { + view.add_label_track( new ReferenceTrack(view) ); + } + view.chrom_data = result['chrom_info']; + var chrom_options = '<option value="">Select Chrom/Contig</option>'; + for (i in view.chrom_data) { + var chrom = view.chrom_data[i]['chrom']; + chrom_options += '<option value="' + chrom + '">' + chrom + '</option>'; + } + view.chrom_select.html(chrom_options); + view.chrom_select.bind( "change", function () { + view.chrom = view.chrom_select.val(); + var found = $.grep(view.chrom_data, function(v, i) { + return v.chrom === view.chrom; + })[0]; + view.max_high = found.len; + view.reset(); + view.redraw(true); + + for (var track_id in view.tracks) { + var track = view.tracks[track_id]; + if (track.init) { + track.init(); + } + } + view.redraw(); + }); + }, + error: function() { + alert( "Could not load chroms for this dbkey:", view.dbkey ); + } + }); + + this.content_div.bind("mousewheel", function( e, delta ) { + if (Math.abs(delta) < 0.5) { + return; + } + if (delta > 0) { + view.zoom_in(e.pageX, this.viewport_container); + } else { + view.zoom_out(); + } + e.preventDefault(); + }); + + this.content_div.bind("dblclick", function( e ) { + view.zoom_in(e.pageX, this.viewport_container); + }); + + // To let the overview box be draggable + this.overview_box.bind("dragstart", function( e ) { + this.current_x = e.offsetX; + }).bind("drag", function( e ) { + var delta = e.offsetX - this.current_x; + this.current_x = e.offsetX; + + var delta_chrom = Math.round(delta / view.viewport_container.width() * (view.high - view.low) ); + view.move_delta(-2*delta_chrom); + }); + + this.viewport_container.bind( "dragstart", function( e ) { + this.original_low = view.low; + this.current_height = e.clientY; + this.current_x = e.offsetX; + }).bind( "drag", function( e ) { + var container = $(this); + var delta = e.offsetX - this.current_x; + var new_scroll = container.scrollTop() - (e.clientY - this.current_height); + if ( new_scroll < container.get(0).scrollHeight - container.height() ) { + container.scrollTop(new_scroll); + } + this.current_height = e.clientY; + this.current_x = e.offsetX; + + var delta_chrom = Math.round(delta / view.viewport_container.width() * (view.high - view.low)); + view.move_delta(delta_chrom); + }); + + this.top_labeltrack.bind( "dragstart", function(e) { + this.drag_origin_x = e.clientX; + this.drag_origin_pos = e.clientX / view.viewport_container.width() * (view.high - view.low) + view.low; + this.drag_div = $("<div />").css( { + "height": view.content_div.height(), "top": "0px", "position": "absolute", + "background-color": "#cfc", "border": "1px solid #6a6", "opacity": 0.5 + } ).appendTo( $(this) ); + }).bind( "drag", function(e) { + var min = Math.min(e.clientX, this.drag_origin_x), + max = Math.max(e.clientX, this.drag_origin_x), + span = (view.high - view.low), + width = view.viewport_container.width(); + + view.low_input.val(commatize(Math.round(min / width * span) + view.low)); + view.high_input.val(commatize(Math.round(max / width * span) + view.low)); + this.drag_div.css( { "left": min + "px", "width": (max - min) + "px" } ); + }).bind( "dragend", function(e) { + var min = Math.min(e.clientX, this.drag_origin_x), + max = Math.max(e.clientX, this.drag_origin_x), + span = (view.high - view.low), + width = view.viewport_container.width(), + old_low = view.low; + + view.low = Math.round(min / width * span) + old_low; + view.high = Math.round(max / width * span) + old_low; + this.drag_div.remove(); + view.redraw(); + }); + + this.add_label_track( new LabelTrack( this, this.top_labeltrack ) ); + this.add_label_track( new LabelTrack( this, this.nav_labeltrack ) ); + + }, + move_delta: function(delta_chrom) { + var view = this; + var current_chrom_span = view.high - view.low; + // Check for left and right boundaries + if (view.low - delta_chrom < view.max_low) { + view.low = view.max_low; + view.high = view.max_low + current_chrom_span; + } else if (view.high - delta_chrom > view.max_high) { + view.high = view.max_high; + view.low = view.max_high - current_chrom_span; + } else { + view.high -= delta_chrom; + view.low -= delta_chrom; + } + view.redraw(); + }, + add_track: function(track) { track.view = this; track.track_id = this.track_id_counter; - this.tracks.push( track ); + this.tracks.push(track); if (track.init) { track.init(); } track.container_div.attr('id', 'track_' + track.track_id); this.track_id_counter += 1; }, - add_label_track: function ( label_track ) { + add_label_track: function (label_track) { label_track.view = this; - this.label_tracks.push( label_track ); + this.label_tracks.push(label_track); }, - remove_track: function( track ) { + remove_track: function(track) { this.has_changes = true; track.container_div.fadeOut('slow', function() { $(this).remove(); }); delete this.tracks[this.tracks.indexOf(track)]; @@ -107,7 +270,7 @@ var View = function( chrom, title, vis_i var sorted = $("ul#sortable-ul").sortable('toArray'); for (var id_i in sorted) { var id = sorted[id_i].split("_li")[0].split("track_")[1]; - $("#viewport").append( $("#track_" + id) ); + this.viewport.append( $("#track_" + id) ); } for (var track_id in view.tracks) { @@ -120,7 +283,7 @@ var View = function( chrom, title, vis_i reset: function() { this.low = this.max_low; this.high = this.max_high; - $(".yaxislabel").remove(); + this.viewport_container.find(".yaxislabel").remove(); }, redraw: function(nodraw) { var span = this.high - this.low, @@ -144,20 +307,20 @@ var View = function( chrom, title, vis_i this.zoom_res = Math.pow( FEATURE_LEVELS, Math.max(0,Math.ceil( Math.log( this.resolution, FEATURE_LEVELS ) / Math.log(FEATURE_LEVELS) ))); // Overview - $("#overview-box").css( { - left: ( this.low / (this.max_high - this.max_low) ) * $("#overview-viewport").width(), + this.overview_box.css( { + left: ( this.low / (this.max_high - this.max_low) ) * this.overview_viewport.width(), // Minimum width for usability - width: Math.max( 12, (this.high - this.low)/(this.max_high - this.max_low) * $("#overview-viewport").width() ) + width: Math.max( 12, (this.high - this.low)/(this.max_high - this.max_low) * this.overview_viewport.width() ) }).show(); - $("#low").val( commatize(this.low) ); - $("#high").val( commatize(this.high) ); + this.low_input.val( commatize(this.low) ); + this.high_input.val( commatize(this.high) ); if (!nodraw) { - for ( var i = 0, len = this.tracks.length; i < len; i++ ) { + for (var i = 0, len = this.tracks.length; i < len; i++) { if (this.tracks[i] && this.tracks[i].enabled) { this.tracks[i].draw(); } } - for ( var i = 0, len = this.label_tracks.length; i < len; i++ ) { + for (var i = 0, len = this.label_tracks.length; i < len; i++) { this.label_tracks[i].draw(); } } @@ -170,7 +333,7 @@ var View = function( chrom, title, vis_i cur_center = span / 2 + this.low, new_half = (span / this.zoom_factor) / 2; if (point) { - cur_center = point / container.width() * (this.high - this.low) + this.low; + cur_center = point / this.viewport_container.width() * (this.high - this.low) + this.low; } this.low = Math.round(cur_center - new_half); this.high = Math.round(cur_center + new_half); @@ -189,9 +352,10 @@ var View = function( chrom, title, vis_i } }); -var Track = function ( name, parent_element ) { +var Track = function (name, view, parent_element) { this.name = name; this.parent_element = parent_element; + this.view = view; this.init_global(); }; $.extend( Track.prototype, { @@ -307,8 +471,8 @@ var TiledTrack = function() { } }); -var LabelTrack = function ( parent_element ) { - Track.call( this, null, parent_element ); +var LabelTrack = function (view, parent_element) { + Track.call( this, null, view, parent_element ); this.track_type = "LabelTrack"; this.hidden = true; this.container_div.addClass( "label-track" ); @@ -335,9 +499,9 @@ var LabelTrack = function ( parent_eleme } }); -var ReferenceTrack = function () { +var ReferenceTrack = function (view) { this.track_type = "ReferenceTrack"; - Track.call( this, null, $("#top-labeltrack") ); + Track.call( this, null, view, view.nav_labeltrack ); TiledTrack.call( this ); this.hidden = true; @@ -404,9 +568,9 @@ var ReferenceTrack = function () { } }); -var LineTrack = function ( name, dataset_id, prefs ) { +var LineTrack = function ( name, view, dataset_id, prefs ) { this.track_type = "LineTrack"; - Track.call( this, name, $("#viewport") ); + Track.call( this, name, view, view.viewport_container ); TiledTrack.call( this ); this.height_px = 100; @@ -624,12 +788,12 @@ var LineTrack = function ( name, dataset } }); -var FeatureTrack = function ( name, dataset_id, prefs ) { +var FeatureTrack = function ( name, view, dataset_id, prefs ) { this.track_type = "FeatureTrack"; - Track.call( this, name, $("#viewport") ); + Track.call( this, name, view, view.viewport_container ); TiledTrack.call( this ); - this.height_px = 100; + this.height_px = 0; this.container_div.addClass( "feature-track" ); this.dataset_id = dataset_id; this.zo_slots = {}; @@ -1065,8 +1229,8 @@ var FeatureTrack = function ( name, data } }); -var ReadTrack = function ( name, dataset_id, prefs ) { - FeatureTrack.call( this, name, dataset_id, prefs ); +var ReadTrack = function ( name, view, dataset_id, prefs ) { + FeatureTrack.call( this, name, view, dataset_id, prefs ); this.track_type = "ReadTrack"; this.vertical_detail_px = 10; this.vertical_nodetail_px = 5; --- a/static/scripts/galaxy.base.js +++ b/static/scripts/galaxy.base.js @@ -156,12 +156,18 @@ function replace_big_select_inputs(min_l var select_elt = $(this); // Make sure that options is within range. var num_options = select_elt.find('option').length; - if ( (num_options < min_length) || (num_options > max_length) ) + if ( (num_options < min_length) || (num_options > max_length) ) { return; + } // Skip multi-select because widget cannot handle multi-select. - if (select_elt.attr('multiple') == true) + if (select_elt.attr('multiple') == true) { return; + } + + if (select_elt.hasClass("no-autocomplete")) { + return; + } // Replace select with text + autocomplete. var start_value = select_elt.attr('value'); --- a/lib/galaxy/web/controllers/visualization.py +++ b/lib/galaxy/web/controllers/visualization.py @@ -283,7 +283,16 @@ class VisualizationController( BaseContr @web.require_login("get item content asynchronously") def get_item_content_async( self, trans, id ): """ Returns item content in HTML format. """ - return "TODO: visualization content" + + # Get visualization, making sure it's accessible. + visualization = self.get_visualization( trans, id, False, True) + if visualization is None: + raise web.httpexceptions.HTTPNotFound() + + # Return content. + visualization_config = self.get_visualization_config( trans, visualization ) + return trans.fill_template_mako( "visualization/item_content.mako", encoded_id=trans.security.encode_id(visualization.id), + item=visualization, item_data=visualization_config, content_only=True ) @web.expose @web.require_login( "create visualizations" ) --- a/templates/tracks/browser.mako +++ b/templates/tracks/browser.mako @@ -15,6 +15,9 @@ ${h.css( "history", "autocomplete_tagging" )} <link rel="stylesheet" type="text/css" href="${h.url_for('/static/trackster.css')}" /><style type="text/css"> + #center { + overflow: auto; + } ul#sortable-ul { list-style: none; padding: 0; @@ -25,6 +28,12 @@ margin: 5px 0; background: #eee; } + .nav-container { + position: fixed; + width: 100%; + left: 0; + bottom: 0; + } </style></%def> @@ -36,37 +45,7 @@ <a id="refresh-button" class="panel-header-button right-float" href="javascript:void(0);" onclick="view.update_options();return false;">Refresh</a></div></div> -<div id="content"> - <div id="top-labeltrack" style="position: relative;"></div> - <div id="viewport-container" style="overflow-x: hidden; overflow-y: auto;"> - <div id="viewport"></div> - </div> -</div> -<div id="nav-container" style="width:100%;"> - <div id="nav-labeltrack"></div> - <div id="nav"> - <div id="overview"> - <div id="overview-viewport"> - <div id="overview-box"></div> - </div> - </div> - <div id="nav-controls"> - <form action="#"> - <select id="chrom" name="chrom" style="width: 15em;"> - <option value="">Loading</option> - </select> - <input id="low" size="12" />:<input id="high" size="12" /> - <input type="hidden" name="id" value="${config.get('vis_id', '')}" /> - <a href="#" onclick="javascript:view.zoom_in();view.redraw();"> - <img src="${h.url_for('/static/images/fugue/magnifier-zoom.png')}" /> - </a> - <a href="#" onclick="javascript:view.zoom_out();view.redraw();"> - <img src="${h.url_for('/static/images/fugue/magnifier-zoom-out.png')}" /> - </a> - </form> - </div> - </div> -</div> + </%def><%def name="right_panel()"> @@ -86,21 +65,22 @@ <%def name="javascripts()"> ${parent.javascripts()} -${h.js( 'galaxy.base', 'galaxy.panels', "json2", "jquery", "jquery.event.drag", "jquery.autocomplete", "jquery.mousewheel", "trackster", "ui.core", "ui.sortable" )} +${h.js( "galaxy.base", "galaxy.panels", "json2", "jquery", "jquery.event.drag", "jquery.autocomplete", "jquery.mousewheel", "trackster", "ui.core", "ui.sortable" )} <script type="text/javascript"> - var data_url = "${h.url_for( action='data' )}"; - var reference_url = "${h.url_for( action='reference' )}"; - var view; + var data_url = "${h.url_for( action='data' )}", + reference_url = "${h.url_for( action='reference' )}", + chrom_url = "${h.url_for( action='chroms' )}", + view; $(function() { %if config: - view = new View( "${config.get('chrom')}", "${config.get('title') | h}", "${config.get('vis_id')}", "${config.get('dbkey')}" ); + view = new View( $("#center"), "${config.get('chrom')}", "${config.get('title') | h}", "${config.get('vis_id')}", "${config.get('dbkey')}" ); %for track in config.get('tracks'): - view.add_track( - new ${track["track_type"]}( "${track['name'] | h}", ${track['dataset_id']}, ${track['prefs']} ) + view.add_track( + new ${track["track_type"]}( "${track['name'] | h}", view, ${track['dataset_id']}, ${track['prefs']} ) ); %endfor init(); @@ -124,14 +104,22 @@ } }); %endif + + $(document).bind( "redraw", function( e ) { + view.redraw(); + }); + + // To adjust the size of the viewport to fit the fixed-height footer + var refresh = function( e ) { + view.viewport_container.height( $(window).height() - 100 ); + view.nav_container.width( $("#center").width() ); + view.redraw(); + }; + $(window).bind( "resize", function(e) { refresh(e); } ); + $("#right-border").bind( "click dragend", function(e) { refresh(e); } ); + $(window).trigger( "resize" ); - window.onbeforeunload = function() { - if ( view.has_changes ) { - return "There are unsaved changes to your visualization which will be lost."; - } - }; - - // Execute this when everything is ready + // Execute initializer for EDITOR specific javascript function init() { $("#title").text(view.title + " (" + view.dbkey + ")"); $("ul#sortable-ul").sortable({ @@ -142,68 +130,11 @@ } }); - $(document).bind( "redraw", function( e ) { - view.redraw(); - }); - - $("#content").bind("mousewheel", function( e, delta ) { - if (Math.abs(delta) < 0.5) { - return; + window.onbeforeunload = function() { + if ( view.has_changes ) { + return "There are unsaved changes to your visualization which will be lost."; } - if (delta > 0) { - view.zoom_in(e.pageX, $("#viewport-container")); - } else { - view.zoom_out(); - } - e.preventDefault(); - }); - - $("#content").bind("dblclick", function( e ) { - view.zoom_in(e.pageX, $("#viewport-container")); - }); - - // To let the overview box be draggable - $("#overview-box").bind("dragstart", function( e ) { - this.current_x = e.offsetX; - }).bind("drag", function( e ) { - var delta = e.offsetX - this.current_x; - this.current_x = e.offsetX; - - var delta_chrom = Math.round(delta / $(document).width() * view.span); - view.high += delta_chrom; - view.low += delta_chrom; - view.redraw(); - }); - - // To adjust the size of the viewport to fit the fixed-height footer - var refresh = function( e ) { - $("#viewport-container").height( $(window).height() - 100 ); - $("#nav-container").width( $("#center").width() ); - view.redraw(); }; - $(window).bind( "resize", function(e) { refresh(e); } ); - $("#right-border").bind( "click dragend", function(e) { refresh(e); } ); - $(window).trigger( "resize" ); - - $("#viewport-container").bind( "dragstart", function( e ) { - this.original_low = view.low; - this.current_height = e.clientY; - this.current_x = e.offsetX; - }).bind( "drag", function( e ) { - var container = $(this); - var delta = e.offsetX - this.current_x; - var new_scroll = container.scrollTop() - (e.clientY - this.current_height); - if ( new_scroll < container.get(0).scrollHeight - container.height() ) { - container.scrollTop(new_scroll); - } - this.current_height = e.clientY; - this.current_x = e.offsetX; - - var delta_chrom = Math.round(delta / $("#viewport-container").width() * (view.high - view.low)); - view.high -= delta_chrom; - view.low -= delta_chrom; - view.redraw(); - }); // Use a popup grid to add more tracks $("#add-track").bind( "click", function(e) { @@ -222,20 +153,10 @@ dataType: "json", error: function() {}, success: function(track_data) { - var new_track; - var td = track_data; - switch(track_data.track_type) { - case "LineTrack": - new_track = new LineTrack( track_data.name, track_data.dataset_id, track_data.prefs ); - break; - case "FeatureTrack": - new_track = new FeatureTrack( track_data.name, track_data.dataset_id, track_data.prefs ); - break; - case "ReadTrack": - new_track = new ReadTrack( track_data.name, track_data.dataset_id, track_data.prefs ); - break; - } - view.add_track(new_track); + var td = track_data, + track_types = { "LineTrack": LineTrack, "FeatureTrack": FeatureTrack, "ReadTrack": ReadTrack }; + + view.add_track(new track_types[track_data.track_type]( track_data.name, view, track_data.dataset_id, track_data.prefs) ); view.has_changes = true; sidebar_box(new_track); } @@ -288,80 +209,6 @@ }); }); - view.add_label_track( new LabelTrack( $("#top-labeltrack") ) ); - view.add_label_track( new LabelTrack( $("#nav-labeltrack") ) ); - - $("#top-labeltrack").bind( "dragstart", function(e) { - this.drag_origin_x = e.clientX; - this.drag_origin_pos = e.clientX / $("#viewport-container").width() * (view.high - view.low) + view.low; - this.drag_div = $("<div />").css( { - "height": $("#viewport-container").height(), "top": "0px", "position": "absolute", - "background-color": "#cfc", "border": "1px solid #6a6", "opacity": 0.5 - } ).appendTo( $(this) ); - }).bind( "drag", function(e) { - var min = Math.min(e.clientX, this.drag_origin_x), - max = Math.max(e.clientX, this.drag_origin_x), - span = (view.high - view.low), - width = $("#viewport-container").width(); - - $("#low").val(commatize(Math.round(min / width * span) + view.low)); - $("#high").val(commatize(Math.round(max / width * span) + view.low)); - this.drag_div.css( { "left": min + "px", "width": (max - min) + "px" } ); - }).bind( "dragend", function(e) { - var min = Math.min(e.clientX, this.drag_origin_x), - max = Math.max(e.clientX, this.drag_origin_x), - span = (view.high - view.low), - width = $("#viewport-container").width(), - old_low = view.low; - - view.low = Math.round(min / width * span) + old_low; - view.high = Math.round(max / width * span) + old_low; - this.drag_div.remove(); - view.redraw(); - }); - - $.ajax({ - url: "${h.url_for( action='chroms' )}", - %if config.get('vis_id'): - data: { vis_id: view.vis_id }, - %else: - data: { dbkey: view.dbkey }, - %endif - dataType: "json", - success: function ( result ) { - if (result['reference']) { - view.add_label_track( new ReferenceTrack() ); - } - view.chrom_data = result['chrom_info']; - var chrom_options = '<option value="">Select Chrom/Contig</option>'; - for (i in view.chrom_data) { - var chrom = view.chrom_data[i]['chrom']; - chrom_options += '<option value="' + chrom + '">' + chrom + '</option>'; - } - $("#chrom").html(chrom_options); - $("#chrom").bind( "change", function () { - view.chrom = $("#chrom").val(); - var found = $.grep(view.chrom_data, function(v, i) { - return v.chrom === view.chrom; - })[0]; - view.max_high = found.len; - view.reset(); - view.redraw(true); - - for (var track_id in view.tracks) { - var track = view.tracks[track_id]; - if (track.init) { - track.init(); - } - } - view.redraw(); - }); - }, - error: function() { - alert( "Could not load chroms for this dbkey:", view.dbkey ); - } - }); - function sidebar_box(track) { if (!track.hidden) { var track_id = track.track_id, --- a/templates/history/display.mako +++ b/templates/history/display.mako @@ -39,8 +39,8 @@ <%def name="render_item_links( history )"><a - href="${h.url_for( controller='/history', action='imp', id=trans.security.encode_id(history.id) )}" - class="icon-button import" + href="${h.url_for( controller='/history', action='imp', id=trans.security.encode_id(history.id) )}" + class="icon-button import" ## Needed to overwide initial width so that link is floated left appropriately. style="width: 100%" title="Import history">Import history</a> --- a/static/trackster.css +++ b/static/trackster.css @@ -1,39 +1,32 @@ -#content { - width: 100%; -} - -#center { - overflow: auto; -} - -#nav-container { - position: fixed; - left: 0; - bottom: 0; +.viewport-container { + overflow-x: hidden; + overflow-y: auto; } /*canvas{ border-left: 1px solid green; border-right: 1px solid red; } /* debugging */ -#nav { +.nav { padding: 0 0; color:#333;font-weight:bold; } -#nav-controls { +.nav-controls { text-align: center; background:#cccccc; background-image:url(style/panel_header_bg.png); background-position:top center; background-repeat:repeat-x; - padding-bottom: 5px; + padding: 2px 0; +} +.nav-controls input { + margin: 0 5px; +} +.nav-controls a { + padding: 0 0.4em; } -#nav-controls a { - padding: 5px 0.4em; -} - -#overview { +.overview { width: 100%; margin: 0px; color: white; @@ -41,7 +34,7 @@ margin-bottom: -4px; } -#overview-viewport { +.overview-viewport { position: relative; height: 14px; /* border-top: solid #666 1px;*/ @@ -51,7 +44,7 @@ border-bottom: solid gray 1px; margin: 5px 0; } -#overview-box { +.overview-box { position: absolute; margin-top: 0px; height: 14px; @@ -59,14 +52,14 @@ /*border-style: outset;*/ } -#viewport { +.viewport { /* overflow-x: hidden;*/ background-color: #fff; /* overflow: scroll;*/ /* border-bottom: 2px solid black;*/ } -#viewport-canvas { +.viewport-canvas { width: 100%; height: 100px; } @@ -122,11 +115,11 @@ margin-left: 5px; } -#top-labeltrack { +.top-labeltrack { border-bottom: solid #999 1px; } -#nav-labeltrack { +.nav-labeltrack { border-top: solid #999 1px; border-bottom: solid #999 1px; }