diff --git a/client/galaxy/scripts/viz/circster.js b/client/galaxy/scripts/viz/circster.js index f21e9103742..e19fda11560 100644 --- a/client/galaxy/scripts/viz/circster.js +++ b/client/galaxy/scripts/viz/circster.js @@ -8,8 +8,6 @@ import "libs/farbtastic"; /** * Utility class for working with SVG. */ -// load css -mod_utils.cssLoadFile("static/style/circster.css"); var SVGUtils = Backbone.Model.extend({ /** @@ -1099,6 +1097,8 @@ var CircsterChromInteractionsTrackView = CircsterTrackView.extend({ // circster app loader var Circster = Backbone.View.extend({ initialize: function() { + // load css + mod_utils.cssLoadFile("static/style/circster.css"); // -- Configure visualization -- var genome = new visualization.Genome(galaxy_config.app.genome); diff --git a/client/galaxy/scripts/viz/trackster.js b/client/galaxy/scripts/viz/trackster.js index 9dbb864b678..11c7aa07d30 100644 --- a/client/galaxy/scripts/viz/trackster.js +++ b/client/galaxy/scripts/viz/trackster.js @@ -24,11 +24,6 @@ import "libs/farbtastic"; import "libs/jquery/jquery.form"; import "libs/jquery/jquery.rating"; import "ui/editable-text"; -mod_utils.cssLoadFile("static/style/jquery.rating.css"); -mod_utils.cssLoadFile("static/style/autocomplete_tagging.css"); -mod_utils.cssLoadFile("static/style/jquery-ui/smoothness/jquery-ui.css"); -mod_utils.cssLoadFile("static/style/library.css"); -mod_utils.cssLoadFile("static/style/trackster.css"); /** * Base Object/Model for inhertiance. */ @@ -44,6 +39,11 @@ Base.extend = Backbone.Model.extend; */ var TracksterUI = Base.extend({ initialize: function(baseURL) { + mod_utils.cssLoadFile("static/style/jquery.rating.css"); + mod_utils.cssLoadFile("static/style/autocomplete_tagging.css"); + mod_utils.cssLoadFile("static/style/jquery-ui/smoothness/jquery-ui.css"); + mod_utils.cssLoadFile("static/style/library.css"); + mod_utils.cssLoadFile("static/style/trackster.css"); this.baseURL = baseURL; }, diff --git a/client/galaxy/style/less/trackster.less b/client/galaxy/style/less/trackster.less index d68ccbb2553..d57dcb6edc6 100644 --- a/client/galaxy/style/less/trackster.less +++ b/client/galaxy/style/less/trackster.less @@ -508,6 +508,7 @@ input { float:right; } +/* .icon { display: inline-block; width: 16px; @@ -521,6 +522,7 @@ input { background: url('../images/fugue/arrow-transition-bw.png') no-repeat 0px 0px; } } +*/ .feature-popup { position: absolute; diff --git a/static/maps/viz/circster.js.map b/static/maps/viz/circster.js.map index aa858cd02f3..84662782876 100644 --- a/static/maps/viz/circster.js.map +++ b/static/maps/viz/circster.js.map @@ -1 +1 @@ -{"version":3,"sources":["viz/circster.js"],"names":["_","d3","_utils2","default","cssLoadFile","SVGUtils","Backbone","Model","extend","is_visible","svg_elt","svg","eltBRect","getBoundingClientRect","svgBRect","$","right","left","bottom","top","UsesTicks","drawTicks","parent_elt","data","dataHandler","textTransform","horizontal","ticks","append","selectAll","enter","attr","d","Math","PI","radius","tick_coords","text_coords","text_anchor","angle","style","text","label","formatNum","num","sigDigits","rval","abs","toPrecision","roundedNum","round","toFixed","CircsterLabelTrack","CircsterView","View","className","initialize","options","this","genome","label_arc_height","scale","circular_views","chords_views","model","get","on","add_track","remove_track","update_track_bounds","vis_config","get_circular_tracks","filter","track","get_tracks_bounds","dataset_arc_height","get_value","track_gap","min_dimension","min","$el","width","height","radius_start","circular_tracks","length","tracks_start_radii","render","self","chords_tracks","get_chord_tracks","range","tracks_bounds","select","zoom","event","translate","zoom_drag_timeout","call","map","index","view","CircsterBigWigTrackView","radius_bounds","total_gap","el","CircsterChromInteractionsTrackView","outermost_radius","track_bounds","label_track_view","CircsterChromLabelTrackView","new_track","innermost_radius_bounds","new_track_bounds","new_view","track_view","i","each","track_index","update_radius_bounds","tracks","splice","remove","CircsterTrackView","tagName","bg_stroke","bg_fill","chroms_layout","loading_bg_fill","_chroms_layout","data_bounds","get_fill_color","color","track_parent_elt","genome_arcs","arc","innerRadius","outerRadius","chroms_paths","arc_gen","chroms_elts","chrom","data_ready_deferred","data_manager","data_is_ready","when","then","_render_data","render_labels","new_d","_transition_labels","transition","duration","update_scale","_transition_chrom_data","new_scale","old_scale","utils","can_get_more_detailed_data","data_deferred","path_elt","get_chrom_region","_update_data_bounds","chrom_region","get_more_detailed_data","chrom_arc","find","layout","chrom_arcs","chrom_data_paths","num_paths","p_data","get_genome_wide_data","genome_wide_data","reject","chrom_data","path_fn","_get_path_function","new_bounds","old_bounds","path","path_data","silent","get_data_bounds","layout_and_data","rendered_deferred","chrom_info","set_value","zip","_render_chrom_data","chroms_info","pie_layout","resolve","init_arcs","pie","value","len","sort","gap_per_chrom","endAngle","new_endAngle","startAngle","prototype","min_arc_len","chromArcTicks","_update_min_max","c","visibleChroms","k","v","track_config","CircsterQuantitativeTrackView","_quantile","numbers","ascending","quantile","datum","linear","domain","clamp","tick","click","ConfigSettingCollectionView","render_in_modal","radial","interpolate","area","line","_data_bounds_ticks_fn","classed","_config2","new_data","chord_data","values","flatten","source","target","target_angle","max","chrom_layout","get_chroms_info","chrom_angle_data","cur_chrom","chrom_chord_data","_get_region_angle","source_angle","concat","type","hidden","chord","vis","viz_view","icon_class","position","on_click","title","Circster","_visualization2","Genome","galaxy_config","app","GenomeVisualization","viz_config","body","key","ajax","url","id","dbkey","vis_json","Galaxy","tooltip_config","placement","_iconButton2","create_icon_buttons_menu","tooltip","select_datasets","add_tracks","collection","modal","show","root","dataType","JSON","stringify","success","vis_info","hide","set","vis_id","error","buttons","Cancel","window","location","menu","GalaxyApp"],"mappings":"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","file":"../../scripts/viz/circster.js","sourcesContent":["import * as _ from \"libs/underscore\";\nimport * as d3 from \"libs/d3\";\nimport visualization from \"viz/visualization\";\nimport mod_utils from \"utils/utils\";\nimport config from \"utils/config\";\nimport mod_icon_btn from \"mvc/ui/icon-button\";\nimport \"libs/farbtastic\";\n/**\n * Utility class for working with SVG.\n */\n// load css\nmod_utils.cssLoadFile(\"static/style/circster.css\");\n\nvar SVGUtils = Backbone.Model.extend({\n /**\n * Returns true if element is visible.\n */\n is_visible: function(svg_elt, svg) {\n var eltBRect = svg_elt.getBoundingClientRect();\n var svgBRect = $(\"svg\")[0].getBoundingClientRect();\n\n if (\n // To the left of screen?\n eltBRect.right < 0 ||\n // To the right of screen?\n eltBRect.left > svgBRect.right ||\n // Above screen?\n eltBRect.bottom < 0 ||\n // Below screen?\n eltBRect.top > svgBRect.bottom\n ) {\n return false;\n }\n return true;\n }\n});\n\n/**\n * Mixin for using ticks.\n */\nvar UsesTicks = {\n drawTicks: function(parent_elt, data, dataHandler, textTransform, horizontal) {\n // Set up group elements for chroms and for each tick.\n var ticks = parent_elt\n .append(\"g\")\n .selectAll(\"g\")\n .data(data)\n .enter()\n .append(\"g\")\n .selectAll(\"g\")\n .data(dataHandler)\n .enter()\n .append(\"g\")\n .attr(\"class\", \"tick\")\n .attr(\"transform\", d => `rotate(${d.angle * 180 / Math.PI - 90})translate(${d.radius},0)`);\n\n // Add line + text for ticks.\n var tick_coords = [];\n\n var text_coords = [];\n\n var text_anchor = d => (d.angle > Math.PI ? \"end\" : null);\n\n if (horizontal) {\n tick_coords = [0, 0, 0, -4];\n text_coords = [4, 0, \"\", \".35em\"];\n text_anchor = null;\n } else {\n tick_coords = [1, 0, 4, 0];\n text_coords = [0, 4, \".35em\", \"\"];\n }\n\n ticks\n .append(\"line\")\n .attr(\"x1\", tick_coords[0])\n .attr(\"y1\", tick_coords[1])\n .attr(\"x2\", tick_coords[2])\n .attr(\"y1\", tick_coords[3])\n .style(\"stroke\", \"#000\");\n\n return ticks\n .append(\"text\")\n .attr(\"x\", text_coords[0])\n .attr(\"y\", text_coords[1])\n .attr(\"dx\", text_coords[2])\n .attr(\"dy\", text_coords[3])\n .attr(\"text-anchor\", text_anchor)\n .attr(\"transform\", textTransform)\n .text(d => d.label);\n },\n\n /**\n * Format number for display at a tick.\n */\n formatNum: function(num, sigDigits) {\n // Use default of 2 sig. digits.\n if (sigDigits === undefined) sigDigits = 2;\n\n // Verify input number\n if (num === null) return null;\n\n // Calculate return value\n var rval = null;\n if (Math.abs(num) < 1) {\n rval = num.toPrecision(sigDigits);\n } else {\n // Use round to turn string from toPrecision() back into a number.\n var roundedNum = Math.round(num.toPrecision(sigDigits));\n\n // Use abbreviations.\n num = Math.abs(num);\n if (num < 1000) {\n rval = roundedNum;\n } else if (num < 1000000) {\n // Use K.\n rval = `${Math.round((roundedNum / 1000).toPrecision(3)).toFixed(0)}K`;\n } else if (num < 1000000000) {\n // Use M.\n rval = `${Math.round((roundedNum / 1000000).toPrecision(3)).toFixed(0)}M`;\n }\n }\n\n return rval;\n }\n};\n\n/**\n * A label track.\n */\nvar CircsterLabelTrack = Backbone.Model.extend({});\n\n/**\n * Renders a full circster visualization.\n */\nvar CircsterView = Backbone.View.extend({\n className: \"circster\",\n\n initialize: function(options) {\n this.genome = options.genome;\n this.label_arc_height = 50;\n this.scale = 1;\n this.circular_views = null;\n this.chords_views = null;\n\n // When tracks added to/removed from model, update view.\n this.model.get(\"drawables\").on(\"add\", this.add_track, this);\n this.model.get(\"drawables\").on(\"remove\", this.remove_track, this);\n\n // When config settings change, update view.\n var vis_config = this.model.get(\"config\");\n vis_config.get(\"arc_dataset_height\").on(\"change:value\", this.update_track_bounds, this);\n vis_config.get(\"track_gap\").on(\"change:value\", this.update_track_bounds, this);\n },\n\n // HACKs: using track_type for circular/chord distinction in the functions below for now.\n\n /**\n * Returns tracks to be rendered using circular view.\n */\n get_circular_tracks: function() {\n return this.model.get(\"drawables\").filter(track => track.get(\"track_type\") !== \"DiagonalHeatmapTrack\");\n },\n\n /**\n * Returns tracks to be rendered using chords view.\n */\n get_chord_tracks: function() {\n return this.model.get(\"drawables\").filter(track => track.get(\"track_type\") === \"DiagonalHeatmapTrack\");\n },\n\n /**\n * Returns a list of circular tracks' radius bounds.\n */\n get_tracks_bounds: function() {\n var circular_tracks = this.get_circular_tracks();\n\n var dataset_arc_height = this.model.get(\"config\").get_value(\"arc_dataset_height\");\n\n var track_gap = this.model.get(\"config\").get_value(\"track_gap\");\n\n var // Subtract 20 to make sure chrom labels are on screen.\n min_dimension = Math.min(this.$el.width(), this.$el.height()) - 20;\n\n var // Compute radius start based on model, will be centered\n // and fit entirely inside element by default.\n radius_start =\n min_dimension / 2 -\n circular_tracks.length * (dataset_arc_height + track_gap) +\n // Add track_gap back in because no gap is needed for last track.\n track_gap -\n this.label_arc_height;\n\n var // Compute range of track starting radii.\n tracks_start_radii = d3.range(radius_start, min_dimension / 2, dataset_arc_height + track_gap);\n\n // Map from track start to bounds.\n var self = this;\n return _.map(tracks_start_radii, radius => [radius, radius + dataset_arc_height]);\n },\n\n /**\n * Renders circular tracks, chord tracks, and label tracks.\n */\n render: function() {\n var self = this;\n var width = self.$el.width();\n var height = self.$el.height();\n var circular_tracks = this.get_circular_tracks();\n var chords_tracks = this.get_chord_tracks();\n var total_gap = self.model.get(\"config\").get_value(\"total_gap\");\n var tracks_bounds = this.get_tracks_bounds();\n\n var // Set up SVG element.\n svg = d3\n .select(self.$el[0])\n .append(\"svg\")\n .attr(\"width\", width)\n .attr(\"height\", height)\n .attr(\"pointer-events\", \"all\")\n // Set up zooming, dragging.\n .append(\"svg:g\")\n .call(\n d3.behavior.zoom().on(\"zoom\", () => {\n // Do zoom, drag.\n var scale = d3.event.scale;\n svg.attr(\"transform\", `translate(${d3.event.translate}) scale(${scale})`);\n\n // Propagate scale changes to views.\n if (self.scale !== scale) {\n // Use timeout to wait for zooming/dragging to stop before rendering more detail.\n if (self.zoom_drag_timeout) {\n clearTimeout(self.zoom_drag_timeout);\n }\n self.zoom_drag_timeout = setTimeout(() => {\n // Render more detail in tracks' visible elements.\n // FIXME: do not do this right now; it is not fully implemented--e.g. data bounds\n // are not updated when new data is fetched--and fetching more detailed quantitative\n // data is not that useful.\n /*\n _.each(self.circular_views, function(view) {\n view.update_scale(scale);\n });\n */\n }, 400);\n }\n })\n )\n .attr(\"transform\", `translate(${width / 2},${height / 2})`)\n .append(\"svg:g\")\n .attr(\"class\", \"tracks\");\n\n // -- Render circular tracks. --\n\n // Create a view for each track in the visualization and render.\n this.circular_views = circular_tracks.map((track, index) => {\n var view = new CircsterBigWigTrackView({\n el: svg.append(\"g\")[0],\n track: track,\n radius_bounds: tracks_bounds[index],\n genome: self.genome,\n total_gap: total_gap\n });\n\n view.render();\n\n return view;\n });\n\n // -- Render chords tracks. --\n\n this.chords_views = chords_tracks.map(track => {\n var view = new CircsterChromInteractionsTrackView({\n el: svg.append(\"g\")[0],\n track: track,\n radius_bounds: tracks_bounds[0],\n genome: self.genome,\n total_gap: total_gap\n });\n\n view.render();\n\n return view;\n });\n\n // -- Render label track. --\n\n // Track bounds are:\n // (a) outer radius of last circular track;\n // (b)\n var outermost_radius = this.circular_views[this.circular_views.length - 1].radius_bounds[1];\n\n var track_bounds = [outermost_radius, outermost_radius + this.label_arc_height];\n\n this.label_track_view = new CircsterChromLabelTrackView({\n el: svg.append(\"g\")[0],\n track: new CircsterLabelTrack(),\n radius_bounds: track_bounds,\n genome: self.genome,\n total_gap: total_gap\n });\n\n this.label_track_view.render();\n },\n\n /**\n * Render a single track on the outside of the current visualization.\n */\n add_track: function(new_track) {\n var total_gap = this.model.get(\"config\").get_value(\"total_gap\");\n\n if (new_track.get(\"track_type\") === \"DiagonalHeatmapTrack\") {\n // Added chords track.\n var innermost_radius_bounds = this.circular_views[0].radius_bounds;\n\n var new_view = new CircsterChromInteractionsTrackView({\n el: d3.select(\"g.tracks\").append(\"g\")[0],\n track: new_track,\n radius_bounds: innermost_radius_bounds,\n genome: this.genome,\n total_gap: total_gap\n });\n\n new_view.render();\n this.chords_views.push(new_view);\n } else {\n // Added circular track.\n\n // Recompute and update circular track bounds.\n var new_track_bounds = this.get_tracks_bounds();\n _.each(this.circular_views, (track_view, i) => {\n track_view.update_radius_bounds(new_track_bounds[i]);\n });\n\n // Update chords tracks.\n _.each(this.chords_views, track_view => {\n track_view.update_radius_bounds(new_track_bounds[0]);\n });\n\n // Render new track.\n var track_index = this.circular_views.length;\n\n var track_view = new CircsterBigWigTrackView({\n el: d3.select(\"g.tracks\").append(\"g\")[0],\n track: new_track,\n radius_bounds: new_track_bounds[track_index],\n genome: this.genome,\n total_gap: total_gap\n });\n\n track_view.render();\n this.circular_views.push(track_view);\n\n // Update label track.\n /*\n FIXME: should never have to update label track because vis always expands to fit area\n within label track.\n var track_bounds = new_track_bounds[ new_track_bounds.length-1 ];\n track_bounds[1] = track_bounds[0];\n this.label_track_view.update_radius_bounds(track_bounds);\n */\n }\n },\n\n /**\n * Remove a track from the view.\n */\n remove_track: function(track, tracks, options) {\n // -- Remove track from view. --\n var track_view = this.circular_views[options.index];\n this.circular_views.splice(options.index, 1);\n track_view.$el.remove();\n\n // Recompute and update track bounds.\n var new_track_bounds = this.get_tracks_bounds();\n _.each(this.circular_views, (track_view, i) => {\n track_view.update_radius_bounds(new_track_bounds[i]);\n });\n },\n\n update_track_bounds: function() {\n // Recompute and update track bounds.\n var new_track_bounds = this.get_tracks_bounds();\n _.each(this.circular_views, (track_view, i) => {\n track_view.update_radius_bounds(new_track_bounds[i]);\n });\n\n // Update chords tracks.\n _.each(this.chords_views, track_view => {\n track_view.update_radius_bounds(new_track_bounds[0]);\n });\n }\n});\n\n/**\n * Renders a track in a Circster visualization.\n */\nvar CircsterTrackView = Backbone.View.extend({\n tagName: \"g\",\n\n /* ----------------------- Public Methods ------------------------- */\n\n initialize: function(options) {\n this.bg_stroke = \"#ddd\";\n // Fill color when loading data.\n this.loading_bg_fill = \"#ffc\";\n // Fill color when data has been loaded.\n this.bg_fill = \"#ddd\";\n this.total_gap = options.total_gap;\n this.track = options.track;\n this.radius_bounds = options.radius_bounds;\n this.genome = options.genome;\n this.chroms_layout = this._chroms_layout();\n this.data_bounds = [];\n this.scale = 1;\n this.parent_elt = d3.select(this.$el[0]);\n },\n\n /**\n * Get fill color from config.\n */\n get_fill_color: function() {\n var color = this.track.get(\"config\").get_value(\"block_color\");\n if (!color) {\n color = this.track.get(\"config\").get_value(\"color\");\n }\n return color;\n },\n\n /**\n * Render track's data by adding SVG elements to parent.\n */\n render: function() {\n // -- Create track group element. --\n var track_parent_elt = this.parent_elt;\n\n // -- Render background arcs. --\n var genome_arcs = this.chroms_layout;\n\n var arc_gen = d3.svg\n .arc()\n .innerRadius(this.radius_bounds[0])\n .outerRadius(this.radius_bounds[1]);\n\n var // Attach data to group element.\n chroms_elts = track_parent_elt\n .selectAll(\"g\")\n .data(genome_arcs)\n .enter()\n .append(\"svg:g\");\n\n var // Draw chrom arcs/paths.\n chroms_paths = chroms_elts\n .append(\"path\")\n .attr(\"d\", arc_gen)\n .attr(\"class\", \"chrom-background\")\n .style(\"stroke\", this.bg_stroke)\n .style(\"fill\", this.loading_bg_fill);\n\n // Append titles to paths.\n chroms_paths.append(\"title\").text(d => d.data.chrom);\n\n // -- Render track data and, when track data is rendered, apply preferences and update chrom_elts fill. --\n\n var self = this;\n\n var data_manager = self.track.get(\"data_manager\");\n\n var // If track has a data manager, get deferred that resolves when data is ready.\n data_ready_deferred = data_manager ? data_manager.data_is_ready() : true;\n\n // When data is ready, render track.\n $.when(data_ready_deferred).then(() => {\n $.when(self._render_data(track_parent_elt)).then(() => {\n chroms_paths.style(\"fill\", self.bg_fill);\n\n // Render labels after data is available so that data attributes are available.\n self.render_labels();\n });\n });\n },\n\n /**\n * Render track labels.\n */\n render_labels: function() {},\n\n /**\n * Update radius bounds.\n */\n update_radius_bounds: function(radius_bounds) {\n // Update bounds.\n this.radius_bounds = radius_bounds;\n\n // -- Update background arcs. --\n var new_d = d3.svg\n .arc()\n .innerRadius(this.radius_bounds[0])\n .outerRadius(this.radius_bounds[1]);\n\n this.parent_elt\n .selectAll(\"g>path.chrom-background\")\n .transition()\n .duration(1000)\n .attr(\"d\", new_d);\n\n this._transition_chrom_data();\n\n this._transition_labels();\n },\n\n /**\n * Update view scale. This fetches more data if scale is increased.\n */\n update_scale: function(new_scale) {\n // -- Update scale and return if new scale is less than old scale. --\n\n var old_scale = this.scale;\n this.scale = new_scale;\n if (new_scale <= old_scale) {\n return;\n }\n\n // -- Scale increased, so render visible data with more detail. --\n\n var self = this;\n\n var utils = new SVGUtils();\n\n // Select all chrom data and filter to operate on those that are visible.\n this.parent_elt\n .selectAll(\"path.chrom-data\")\n .filter(function(d, i) {\n return utils.is_visible(this);\n })\n .each(function(d, i) {\n // -- Now operating on a single path element representing chromosome data. --\n\n var path_elt = d3.select(this);\n\n var chrom = path_elt.attr(\"chrom\");\n var chrom_region = self.genome.get_chrom_region(chrom);\n var data_manager = self.track.get(\"data_manager\");\n var data_deferred;\n\n // If can't get more detailed data, return.\n if (!data_manager.can_get_more_detailed_data(chrom_region)) {\n return;\n }\n\n // -- Get more detailed data. --\n data_deferred = self.track\n .get(\"data_manager\")\n .get_more_detailed_data(chrom_region, \"Coverage\", 0, new_scale);\n\n // When more data is available, use new data to redraw path.\n $.when(data_deferred).then(data => {\n // Remove current data path.\n path_elt.remove();\n\n // Update data bounds with new data.\n self._update_data_bounds();\n\n // Find chromosome arc to draw data on.\n var chrom_arc = _.find(self.chroms_layout, layout => layout.data.chrom === chrom);\n\n // Add new data path and apply preferences.\n var color = self.get_fill_color();\n self\n ._render_chrom_data(self.parent_elt, chrom_arc, data)\n .style(\"stroke\", color)\n .style(\"fill\", color);\n });\n });\n\n return self;\n },\n\n /* ----------------------- Internal Methods ------------------------- */\n\n /**\n * Transitions chrom data to new values (e.g new radius or data bounds).\n */\n _transition_chrom_data: function() {\n var track = this.track;\n var chrom_arcs = this.chroms_layout;\n var chrom_data_paths = this.parent_elt.selectAll(\"g>path.chrom-data\");\n var num_paths = chrom_data_paths[0].length;\n\n if (num_paths > 0) {\n var self = this;\n $.when(track.get(\"data_manager\").get_genome_wide_data(this.genome)).then(genome_wide_data => {\n // Map chrom data to path data, filtering out null values.\n var path_data = _.reject(\n _.map(genome_wide_data, (chrom_data, i) => {\n var rval = null;\n\n var path_fn = self._get_path_function(chrom_arcs[i], chrom_data);\n\n if (path_fn) {\n rval = path_fn(chrom_data.data);\n }\n return rval;\n }),\n p_data => p_data === null\n );\n\n // Transition each path for data and color.\n var color = track.get(\"config\").get_value(\"color\");\n chrom_data_paths.each(function(path, index) {\n d3\n .select(this)\n .transition()\n .duration(1000)\n .style(\"stroke\", color)\n .style(\"fill\", color)\n .attr(\"d\", path_data[index]);\n });\n });\n }\n },\n\n /**\n * Transition labels to new values (e.g new radius or data bounds).\n */\n _transition_labels: function() {},\n\n /**\n * Update data bounds. If there are new_bounds, use them; otherwise use\n * default data bounds.\n */\n _update_data_bounds: function(new_bounds) {\n var old_bounds = this.data_bounds;\n this.data_bounds =\n new_bounds || this.get_data_bounds(this.track.get(\"data_manager\").get_genome_wide_data(this.genome));\n this._transition_chrom_data();\n },\n\n /**\n * Render data as elements attached to svg.\n */\n _render_data: function(svg) {\n var self = this;\n var chrom_arcs = this.chroms_layout;\n var track = this.track;\n var rendered_deferred = $.Deferred();\n\n // When genome-wide data is available, render data.\n $.when(track.get(\"data_manager\").get_genome_wide_data(this.genome)).then(genome_wide_data => {\n // Set bounds.\n self.data_bounds = self.get_data_bounds(genome_wide_data);\n\n // Set min, max value in config so that they can be adjusted. Make this silent\n // because these attributes are watched for changes and the viz is updated\n // accordingly (set up in initialize). Because we are setting up, we don't want\n // the watch to trigger events here.\n track.get(\"config\").set_value(\"min_value\", self.data_bounds[0], {\n silent: true\n });\n track.get(\"config\").set_value(\"max_value\", self.data_bounds[1], {\n silent: true\n });\n\n // Merge chroms layout with data.\n var layout_and_data = _.zip(chrom_arcs, genome_wide_data);\n\n // Render each chromosome's data.\n _.each(layout_and_data, chrom_info => {\n var chrom_arc = chrom_info[0];\n var data = chrom_info[1];\n return self._render_chrom_data(svg, chrom_arc, data);\n });\n\n // Apply prefs to all track data.\n var color = self.get_fill_color();\n self.parent_elt\n .selectAll(\"path.chrom-data\")\n .style(\"stroke\", color)\n .style(\"fill\", color);\n\n rendered_deferred.resolve(svg);\n });\n\n return rendered_deferred;\n },\n\n /**\n * Render a chromosome data and attach elements to svg.\n */\n _render_chrom_data: function(svg, chrom_arc, data) {},\n\n /**\n * Returns data for creating a path for the given data using chrom_arc and data bounds.\n */\n _get_path_function: function(chrom_arc, chrom_data) {},\n\n /**\n * Returns arc layouts for genome's chromosomes/contigs. Arcs are arranged in a circle\n * separated by gaps.\n */\n _chroms_layout: function() {\n // Setup chroms layout using pie.\n var chroms_info = this.genome.get_chroms_info();\n\n var pie_layout = d3.layout\n .pie()\n .value(d => d.len)\n .sort(null);\n\n var init_arcs = pie_layout(chroms_info);\n var gap_per_chrom = 2 * Math.PI * this.total_gap / chroms_info.length;\n\n var chrom_arcs = _.map(init_arcs, (arc, index) => {\n // For short chroms, endAngle === startAngle.\n var new_endAngle = arc.endAngle - gap_per_chrom;\n arc.endAngle = new_endAngle > arc.startAngle ? new_endAngle : arc.startAngle;\n return arc;\n });\n\n return chrom_arcs;\n }\n});\n\n/**\n * Render chromosome labels.\n */\nvar CircsterChromLabelTrackView = CircsterTrackView.extend({\n initialize: function(options) {\n CircsterTrackView.prototype.initialize.call(this, options);\n // Use a single arc for rendering data.\n this.innerRadius = this.radius_bounds[0];\n this.radius_bounds[0] = this.radius_bounds[1];\n this.bg_stroke = \"#fff\";\n this.bg_fill = \"#fff\";\n\n // Minimum arc distance for labels to be applied.\n this.min_arc_len = 0.05;\n },\n\n /**\n * Render labels.\n */\n _render_data: function(svg) {\n // -- Add chromosome label where it will fit; an alternative labeling mechanism\n // would be nice for small chromosomes. --\n var self = this;\n\n var chrom_arcs = svg.selectAll(\"g\");\n\n chrom_arcs.selectAll(\"path\").attr(\"id\", d => `label-${d.data.chrom}`);\n\n chrom_arcs\n .append(\"svg:text\")\n .filter(d => d.endAngle - d.startAngle > self.min_arc_len)\n .attr(\"text-anchor\", \"middle\")\n .append(\"svg:textPath\")\n .attr(\"class\", \"chrom-label\")\n .attr(\"xlink:href\", d => `#label-${d.data.chrom}`)\n .attr(\"startOffset\", \"25%\")\n .text(d => d.data.chrom);\n\n // -- Add ticks to denote chromosome length. --\n\n /** Returns an array of tick angles and labels, given a chrom arc. */\n var chromArcTicks = d => {\n var k = (d.endAngle - d.startAngle) / d.value;\n\n var ticks = d3.range(0, d.value, 25000000).map((v, i) => ({\n radius: self.innerRadius,\n angle: v * k + d.startAngle,\n label: i === 0 ? 0 : i % 3 ? null : self.formatNum(v)\n }));\n\n // If there are fewer that 4 ticks, label last tick so that at least one non-zero tick is labeled.\n if (ticks.length < 4) {\n ticks[ticks.length - 1].label = self.formatNum(\n Math.round((ticks[ticks.length - 1].angle - d.startAngle) / k)\n );\n }\n\n return ticks;\n };\n\n /** Rotate and move text as needed. */\n var textTransform = d => (d.angle > Math.PI ? \"rotate(180)translate(-16)\" : null);\n\n // Filter chroms for only those large enough for display.\n var visibleChroms = _.filter(this.chroms_layout, c => c.endAngle - c.startAngle > self.min_arc_len);\n\n this.drawTicks(this.parent_elt, visibleChroms, chromArcTicks, textTransform);\n }\n});\n_.extend(CircsterChromLabelTrackView.prototype, UsesTicks);\n\n/**\n * View for quantitative track in Circster.\n */\nvar CircsterQuantitativeTrackView = CircsterTrackView.extend({\n initialize: function(options) {\n CircsterTrackView.prototype.initialize.call(this, options);\n\n // When config settings change, update view.\n var track_config = this.track.get(\"config\");\n track_config.get(\"min_value\").on(\"change:value\", this._update_min_max, this);\n track_config.get(\"max_value\").on(\"change:value\", this._update_min_max, this);\n track_config.get(\"color\").on(\"change:value\", this._transition_chrom_data, this);\n },\n\n /**\n * Update track when min and/or max are changed.\n */\n _update_min_max: function() {\n var track_config = this.track.get(\"config\");\n\n var new_bounds = [track_config.get_value(\"min_value\"), track_config.get_value(\"max_value\")];\n\n this._update_data_bounds(new_bounds);\n\n // FIXME: this works to update tick/text bounds, but there's probably a better way to do this\n // by updating the data itself.\n this.parent_elt.selectAll(\".min_max\").text((d, i) => new_bounds[i]);\n },\n\n /**\n * Returns quantile for an array of numbers.\n */\n _quantile: function(numbers, quantile) {\n numbers.sort(d3.ascending);\n return d3.quantile(numbers, quantile);\n },\n\n /**\n * Renders quantitative data with the form [x, value] and assumes data is equally spaced across\n * chromosome. Attachs a dict with track and chrom name information to DOM element.\n */\n _render_chrom_data: function(svg, chrom_arc, chrom_data) {\n var path_data = this._get_path_function(chrom_arc, chrom_data);\n\n if (!path_data) {\n return null;\n }\n\n // There is path data, so render as path.\n var parent = svg.datum(chrom_data.data);\n\n var path = parent\n .append(\"path\")\n .attr(\"class\", \"chrom-data\")\n .attr(\"chrom\", chrom_arc.data.chrom)\n .attr(\"d\", path_data);\n\n return path;\n },\n\n /**\n * Returns function for creating a path across the chrom arc.\n */\n _get_path_function: function(chrom_arc, chrom_data) {\n // If no chrom data, return null.\n if (typeof chrom_data === \"string\" || !chrom_data.data || chrom_data.data.length === 0) {\n return null;\n }\n\n // Radius scaler.\n var radius = d3.scale\n .linear()\n .domain(this.data_bounds)\n .range(this.radius_bounds)\n .clamp(true);\n\n // Scaler for placing data points across arc.\n var angle = d3.scale\n .linear()\n .domain([0, chrom_data.data.length])\n .range([chrom_arc.startAngle, chrom_arc.endAngle]);\n\n // Use line generator to create area.\n var line = d3.svg.line\n .radial()\n .interpolate(\"linear\")\n .radius(d => radius(d[1]))\n .angle((d, i) => angle(i));\n\n return d3.svg.area\n .radial()\n .interpolate(line.interpolate())\n .innerRadius(radius(0))\n .outerRadius(line.radius())\n .angle(line.angle());\n },\n\n /**\n * Render track min, max using ticks.\n */\n render_labels: function() {\n var self = this;\n\n var // Keep counter of visible chroms.\n textTransform = () => \"rotate(90)\";\n\n // FIXME:\n // (1) using min_max class below is needed for _update_min_max, which could be improved.\n // (2) showing config on tick click should be replaced by proper track config icon.\n\n // Draw min, max on first chrom only.\n var ticks = this.drawTicks(\n this.parent_elt,\n [this.chroms_layout[0]],\n this._data_bounds_ticks_fn(),\n textTransform,\n true\n ).classed(\"min_max\", true);\n\n // Show config when ticks are clicked on.\n _.each(ticks, tick => {\n $(tick).click(() => {\n var view = new config.ConfigSettingCollectionView({\n collection: self.track.get(\"config\")\n });\n view.render_in_modal(\"Configure Track\");\n });\n });\n\n /*\n // Filter for visible chroms, then for every third chrom so that labels attached to only every\n // third chrom.\n var visibleChroms = _.filter(this.chroms_layout, function(c) { return c.endAngle - c.startAngle > 0.08; }),\n labeledChroms = _.filter(visibleChroms, function(c, i) { return i % 3 === 0; });\n this.drawTicks(this.parent_elt, labeledChroms, this._data_bounds_ticks_fn(), textTransform, true);\n */\n },\n\n /**\n * Transition labels to new values (e.g new radius or data bounds).\n */\n _transition_labels: function() {\n // FIXME: (a) pull out function for getting labeled chroms? and (b) function used in transition below\n // is copied from UseTicks mixin, so pull out and make generally available.\n\n // If there are no data bounds, nothing to transition.\n if (this.data_bounds.length === 0) {\n return;\n }\n\n // Transition labels to new radius bounds.\n var self = this;\n\n var visibleChroms = _.filter(this.chroms_layout, c => c.endAngle - c.startAngle > 0.08);\n\n var labeledChroms = _.filter(visibleChroms, (c, i) => i % 3 === 0);\n\n var new_data = _.flatten(_.map(labeledChroms, c => self._data_bounds_ticks_fn()(c)));\n\n this.parent_elt\n .selectAll(\"g.tick\")\n .data(new_data)\n .transition()\n .attr(\"transform\", d => `rotate(${d.angle * 180 / Math.PI - 90})translate(${d.radius},0)`);\n },\n\n /**\n * Get function for locating data bounds ticks.\n */\n _data_bounds_ticks_fn: function() {\n // Closure vars.\n var self = this;\n visibleChroms = 0;\n\n // Return function for locating ticks based on chrom arc data.\n return (\n d // Set up data to display min, max ticks.\n ) => [\n {\n radius: self.radius_bounds[0],\n angle: d.startAngle,\n label: self.formatNum(self.data_bounds[0])\n },\n {\n radius: self.radius_bounds[1],\n angle: d.startAngle,\n label: self.formatNum(self.data_bounds[1])\n }\n ];\n },\n\n /**\n * Returns an array with two values denoting the minimum and maximum\n * values for the track.\n */\n get_data_bounds: function(data) {}\n});\n_.extend(CircsterQuantitativeTrackView.prototype, UsesTicks);\n\n/**\n * Bigwig track view in Circster.\n */\nvar CircsterBigWigTrackView = CircsterQuantitativeTrackView.extend({\n get_data_bounds: function(data) {\n // Set max across dataset by extracting all values, flattening them into a\n // single array, and getting third quartile.\n var values = _.flatten(\n _.map(data, d => {\n if (d) {\n // Each data point has the form [position, value], so return all values.\n return _.map(\n d.data,\n (\n p // Null is used for a lack of data; resolve null to 0 for comparison.\n ) => parseInt(p[1], 10) || 0\n );\n } else {\n return 0;\n }\n })\n );\n\n // For max, use 98% quantile in attempt to avoid very large values. However, this max may be 0\n // for sparsely populated data, so use max in that case.\n return [_.min(values), this._quantile(values, 0.98) || _.max(values)];\n }\n});\n\n/**\n * Chromosome interactions track view in Circster.\n */\nvar CircsterChromInteractionsTrackView = CircsterTrackView.extend({\n render: function() {\n var self = this;\n\n // When data is ready, render track.\n $.when(self.track.get(\"data_manager\").data_is_ready()).then(() => {\n // When data has been fetched, render track.\n $.when(self.track.get(\"data_manager\").get_genome_wide_data(self.genome)).then(genome_wide_data => {\n var chord_data = [];\n var chroms_info = self.genome.get_chroms_info();\n // Convert chromosome data into chord data.\n _.each(genome_wide_data, (chrom_data, index) => {\n // Map each interaction into chord data.\n var cur_chrom = chroms_info[index].chrom;\n var chrom_chord_data = _.map(chrom_data.data, datum => {\n // Each datum is an interaction/chord.\n var source_angle = self._get_region_angle(cur_chrom, datum[1]);\n\n var target_angle = self._get_region_angle(datum[3], datum[4]);\n\n return {\n source: {\n startAngle: source_angle,\n endAngle: source_angle + 0.01\n },\n target: {\n startAngle: target_angle,\n endAngle: target_angle + 0.01\n }\n };\n });\n\n chord_data = chord_data.concat(chrom_chord_data);\n });\n\n self.parent_elt\n .append(\"g\")\n .attr(\"class\", \"chord\")\n .selectAll(\"path\")\n .data(chord_data)\n .enter()\n .append(\"path\")\n .style(\"fill\", self.get_fill_color())\n .attr(\"d\", d3.svg.chord().radius(self.radius_bounds[0]))\n .style(\"opacity\", 1);\n });\n });\n },\n\n update_radius_bounds: function(radius_bounds) {\n this.radius_bounds = radius_bounds;\n this.parent_elt\n .selectAll(\"path\")\n .transition()\n .attr(\"d\", d3.svg.chord().radius(this.radius_bounds[0]));\n },\n\n /**\n * Returns radians for a genomic position.\n */\n _get_region_angle: function(chrom, position) {\n // Find chrom angle data\n var chrom_angle_data = _.find(this.chroms_layout, chrom_layout => chrom_layout.data.chrom === chrom);\n\n // Return angle at position.\n return (\n chrom_angle_data.endAngle -\n (chrom_angle_data.endAngle - chrom_angle_data.startAngle) *\n (chrom_angle_data.data.len - position) /\n chrom_angle_data.data.len\n );\n }\n});\n\n// circster app loader\nvar Circster = Backbone.View.extend({\n initialize: function() {\n // -- Configure visualization --\n var genome = new visualization.Genome(galaxy_config.app.genome);\n\n var vis = new visualization.GenomeVisualization(galaxy_config.app.viz_config);\n\n // Add Circster-specific config options.\n vis.get(\"config\").add([\n {\n key: \"arc_dataset_height\",\n label: \"Arc Dataset Height\",\n type: \"int\",\n value: 25,\n view: \"circster\"\n },\n {\n key: \"track_gap\",\n label: \"Gap Between Tracks\",\n type: \"int\",\n value: 5,\n view: \"circster\"\n },\n {\n key: \"total_gap\",\n label: \"Gap [0-1]\",\n type: \"float\",\n value: 0.4,\n view: \"circster\",\n hidden: true\n }\n ]);\n\n var viz_view = new CircsterView({\n // view pane\n el: $(\"#center .unified-panel-body\"),\n genome: genome,\n model: vis\n });\n\n // Render vizualization\n viz_view.render();\n\n // setup title\n $(\"#center .unified-panel-header-inner\").append(\n `${galaxy_config.app.viz_config.title} ${galaxy_config.app.viz_config.dbkey}`\n );\n\n // setup menu\n var menu = mod_icon_btn.create_icon_buttons_menu(\n [\n {\n icon_class: \"plus-button\",\n title: \"Add tracks\",\n on_click: function() {\n visualization.select_datasets({ dbkey: vis.get(\"dbkey\") }, tracks => {\n vis.add_tracks(tracks);\n });\n }\n },\n {\n icon_class: \"gear\",\n title: \"Settings\",\n on_click: function() {\n var view = new config.ConfigSettingCollectionView({\n collection: vis.get(\"config\")\n });\n view.render_in_modal(\"Configure Visualization\");\n }\n },\n {\n icon_class: \"disk--arrow\",\n title: \"Save\",\n on_click: function() {\n // show saving dialog box\n Galaxy.modal.show({\n title: \"Saving...\",\n body: \"progress\"\n });\n\n // send to server\n $.ajax({\n url: `${Galaxy.root}visualization/save`,\n type: \"POST\",\n dataType: \"json\",\n data: {\n id: vis.get(\"vis_id\"),\n title: vis.get(\"title\"),\n dbkey: vis.get(\"dbkey\"),\n type: \"trackster\",\n vis_json: JSON.stringify(vis)\n }\n })\n .success(vis_info => {\n Galaxy.modal.hide();\n vis.set(\"vis_id\", vis_info.vis_id);\n })\n .error(() => {\n // show dialog\n Galaxy.modal.show({\n title: \"Could Not Save\",\n body: \"Could not save visualization. Please try again later.\",\n buttons: {\n Cancel: function() {\n Galaxy.modal.hide();\n }\n }\n });\n });\n }\n },\n {\n icon_class: \"cross-circle\",\n title: \"Close\",\n on_click: function() {\n window.location = `${Galaxy.root}visualizations/list`;\n }\n }\n ],\n { tooltip_config: { placement: \"bottom\" } }\n );\n\n // add menu\n menu.$el.attr(\"style\", \"float: right\");\n $(\"#center .unified-panel-header-inner\").append(menu.$el);\n\n // manual tooltip config because default gravity is S and cannot be changed\n $(\".menu-button\").tooltip({ placement: \"bottom\" });\n }\n});\n\n// Module exports.\nexport default {\n GalaxyApp: Circster\n};\n"]} \ No newline at end of file +{"version":3,"sources":["viz/circster.js"],"names":["_","d3","SVGUtils","Backbone","Model","extend","is_visible","svg_elt","svg","eltBRect","getBoundingClientRect","svgBRect","$","right","left","bottom","top","UsesTicks","drawTicks","parent_elt","data","dataHandler","textTransform","horizontal","ticks","append","selectAll","enter","attr","d","Math","PI","radius","tick_coords","text_coords","text_anchor","angle","style","text","label","formatNum","num","sigDigits","rval","abs","toPrecision","roundedNum","round","toFixed","CircsterLabelTrack","CircsterView","View","className","initialize","options","this","genome","label_arc_height","scale","circular_views","chords_views","model","get","on","add_track","remove_track","update_track_bounds","vis_config","get_circular_tracks","filter","track","get_tracks_bounds","dataset_arc_height","get_value","track_gap","min_dimension","min","$el","width","height","radius_start","circular_tracks","length","tracks_start_radii","render","self","chords_tracks","get_chord_tracks","range","tracks_bounds","select","zoom","event","translate","zoom_drag_timeout","call","map","index","view","CircsterBigWigTrackView","radius_bounds","total_gap","el","CircsterChromInteractionsTrackView","outermost_radius","track_bounds","label_track_view","CircsterChromLabelTrackView","new_track","innermost_radius_bounds","new_track_bounds","new_view","track_view","i","each","track_index","update_radius_bounds","tracks","splice","remove","CircsterTrackView","tagName","bg_stroke","bg_fill","chroms_layout","loading_bg_fill","_chroms_layout","data_bounds","get_fill_color","color","track_parent_elt","genome_arcs","arc","innerRadius","outerRadius","chroms_paths","arc_gen","chroms_elts","chrom","data_ready_deferred","data_manager","data_is_ready","when","then","_render_data","render_labels","new_d","_transition_labels","transition","duration","update_scale","_transition_chrom_data","new_scale","old_scale","utils","can_get_more_detailed_data","data_deferred","path_elt","get_chrom_region","_update_data_bounds","chrom_region","get_more_detailed_data","chrom_arc","find","layout","chrom_arcs","chrom_data_paths","num_paths","p_data","get_genome_wide_data","genome_wide_data","reject","chrom_data","path_fn","_get_path_function","new_bounds","old_bounds","path","path_data","silent","get_data_bounds","layout_and_data","rendered_deferred","chrom_info","set_value","zip","_render_chrom_data","chroms_info","pie_layout","resolve","init_arcs","pie","value","len","sort","gap_per_chrom","endAngle","new_endAngle","startAngle","prototype","min_arc_len","chromArcTicks","_update_min_max","c","visibleChroms","k","v","track_config","CircsterQuantitativeTrackView","_quantile","numbers","ascending","quantile","datum","linear","domain","clamp","tick","click","ConfigSettingCollectionView","render_in_modal","radial","interpolate","area","line","_data_bounds_ticks_fn","classed","_config2","default","new_data","chord_data","values","flatten","source","target","target_angle","max","chrom_layout","get_chroms_info","chrom_angle_data","cur_chrom","chrom_chord_data","_get_region_angle","source_angle","GenomeVisualization","add","concat","type","chord","hidden","position","icon_class","vis","add_tracks","Circster","_utils2","cssLoadFile","title","_visualization2","Genome","galaxy_config","app","viz_config","body","key","ajax","url","id","dbkey","vis_json","Galaxy","tooltip_config","placement","_iconButton2","create_icon_buttons_menu","tooltip","on_click","select_datasets","collection","modal","show","root","dataType","JSON","stringify","success","vis_info","hide","set","vis_id","error","buttons","Cancel","window","location","menu","GalaxyApp"],"mappings":"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","file":"../../scripts/viz/circster.js","sourcesContent":["import * as _ from \"libs/underscore\";\nimport * as d3 from \"libs/d3\";\nimport visualization from \"viz/visualization\";\nimport mod_utils from \"utils/utils\";\nimport config from \"utils/config\";\nimport mod_icon_btn from \"mvc/ui/icon-button\";\nimport \"libs/farbtastic\";\n/**\n * Utility class for working with SVG.\n */\n\nvar SVGUtils = Backbone.Model.extend({\n /**\n * Returns true if element is visible.\n */\n is_visible: function(svg_elt, svg) {\n var eltBRect = svg_elt.getBoundingClientRect();\n var svgBRect = $(\"svg\")[0].getBoundingClientRect();\n\n if (\n // To the left of screen?\n eltBRect.right < 0 ||\n // To the right of screen?\n eltBRect.left > svgBRect.right ||\n // Above screen?\n eltBRect.bottom < 0 ||\n // Below screen?\n eltBRect.top > svgBRect.bottom\n ) {\n return false;\n }\n return true;\n }\n});\n\n/**\n * Mixin for using ticks.\n */\nvar UsesTicks = {\n drawTicks: function(parent_elt, data, dataHandler, textTransform, horizontal) {\n // Set up group elements for chroms and for each tick.\n var ticks = parent_elt\n .append(\"g\")\n .selectAll(\"g\")\n .data(data)\n .enter()\n .append(\"g\")\n .selectAll(\"g\")\n .data(dataHandler)\n .enter()\n .append(\"g\")\n .attr(\"class\", \"tick\")\n .attr(\"transform\", d => `rotate(${d.angle * 180 / Math.PI - 90})translate(${d.radius},0)`);\n\n // Add line + text for ticks.\n var tick_coords = [];\n\n var text_coords = [];\n\n var text_anchor = d => (d.angle > Math.PI ? \"end\" : null);\n\n if (horizontal) {\n tick_coords = [0, 0, 0, -4];\n text_coords = [4, 0, \"\", \".35em\"];\n text_anchor = null;\n } else {\n tick_coords = [1, 0, 4, 0];\n text_coords = [0, 4, \".35em\", \"\"];\n }\n\n ticks\n .append(\"line\")\n .attr(\"x1\", tick_coords[0])\n .attr(\"y1\", tick_coords[1])\n .attr(\"x2\", tick_coords[2])\n .attr(\"y1\", tick_coords[3])\n .style(\"stroke\", \"#000\");\n\n return ticks\n .append(\"text\")\n .attr(\"x\", text_coords[0])\n .attr(\"y\", text_coords[1])\n .attr(\"dx\", text_coords[2])\n .attr(\"dy\", text_coords[3])\n .attr(\"text-anchor\", text_anchor)\n .attr(\"transform\", textTransform)\n .text(d => d.label);\n },\n\n /**\n * Format number for display at a tick.\n */\n formatNum: function(num, sigDigits) {\n // Use default of 2 sig. digits.\n if (sigDigits === undefined) sigDigits = 2;\n\n // Verify input number\n if (num === null) return null;\n\n // Calculate return value\n var rval = null;\n if (Math.abs(num) < 1) {\n rval = num.toPrecision(sigDigits);\n } else {\n // Use round to turn string from toPrecision() back into a number.\n var roundedNum = Math.round(num.toPrecision(sigDigits));\n\n // Use abbreviations.\n num = Math.abs(num);\n if (num < 1000) {\n rval = roundedNum;\n } else if (num < 1000000) {\n // Use K.\n rval = `${Math.round((roundedNum / 1000).toPrecision(3)).toFixed(0)}K`;\n } else if (num < 1000000000) {\n // Use M.\n rval = `${Math.round((roundedNum / 1000000).toPrecision(3)).toFixed(0)}M`;\n }\n }\n\n return rval;\n }\n};\n\n/**\n * A label track.\n */\nvar CircsterLabelTrack = Backbone.Model.extend({});\n\n/**\n * Renders a full circster visualization.\n */\nvar CircsterView = Backbone.View.extend({\n className: \"circster\",\n\n initialize: function(options) {\n this.genome = options.genome;\n this.label_arc_height = 50;\n this.scale = 1;\n this.circular_views = null;\n this.chords_views = null;\n\n // When tracks added to/removed from model, update view.\n this.model.get(\"drawables\").on(\"add\", this.add_track, this);\n this.model.get(\"drawables\").on(\"remove\", this.remove_track, this);\n\n // When config settings change, update view.\n var vis_config = this.model.get(\"config\");\n vis_config.get(\"arc_dataset_height\").on(\"change:value\", this.update_track_bounds, this);\n vis_config.get(\"track_gap\").on(\"change:value\", this.update_track_bounds, this);\n },\n\n // HACKs: using track_type for circular/chord distinction in the functions below for now.\n\n /**\n * Returns tracks to be rendered using circular view.\n */\n get_circular_tracks: function() {\n return this.model.get(\"drawables\").filter(track => track.get(\"track_type\") !== \"DiagonalHeatmapTrack\");\n },\n\n /**\n * Returns tracks to be rendered using chords view.\n */\n get_chord_tracks: function() {\n return this.model.get(\"drawables\").filter(track => track.get(\"track_type\") === \"DiagonalHeatmapTrack\");\n },\n\n /**\n * Returns a list of circular tracks' radius bounds.\n */\n get_tracks_bounds: function() {\n var circular_tracks = this.get_circular_tracks();\n\n var dataset_arc_height = this.model.get(\"config\").get_value(\"arc_dataset_height\");\n\n var track_gap = this.model.get(\"config\").get_value(\"track_gap\");\n\n var // Subtract 20 to make sure chrom labels are on screen.\n min_dimension = Math.min(this.$el.width(), this.$el.height()) - 20;\n\n var // Compute radius start based on model, will be centered\n // and fit entirely inside element by default.\n radius_start =\n min_dimension / 2 -\n circular_tracks.length * (dataset_arc_height + track_gap) +\n // Add track_gap back in because no gap is needed for last track.\n track_gap -\n this.label_arc_height;\n\n var // Compute range of track starting radii.\n tracks_start_radii = d3.range(radius_start, min_dimension / 2, dataset_arc_height + track_gap);\n\n // Map from track start to bounds.\n var self = this;\n return _.map(tracks_start_radii, radius => [radius, radius + dataset_arc_height]);\n },\n\n /**\n * Renders circular tracks, chord tracks, and label tracks.\n */\n render: function() {\n var self = this;\n var width = self.$el.width();\n var height = self.$el.height();\n var circular_tracks = this.get_circular_tracks();\n var chords_tracks = this.get_chord_tracks();\n var total_gap = self.model.get(\"config\").get_value(\"total_gap\");\n var tracks_bounds = this.get_tracks_bounds();\n\n var // Set up SVG element.\n svg = d3\n .select(self.$el[0])\n .append(\"svg\")\n .attr(\"width\", width)\n .attr(\"height\", height)\n .attr(\"pointer-events\", \"all\")\n // Set up zooming, dragging.\n .append(\"svg:g\")\n .call(\n d3.behavior.zoom().on(\"zoom\", () => {\n // Do zoom, drag.\n var scale = d3.event.scale;\n svg.attr(\"transform\", `translate(${d3.event.translate}) scale(${scale})`);\n\n // Propagate scale changes to views.\n if (self.scale !== scale) {\n // Use timeout to wait for zooming/dragging to stop before rendering more detail.\n if (self.zoom_drag_timeout) {\n clearTimeout(self.zoom_drag_timeout);\n }\n self.zoom_drag_timeout = setTimeout(() => {\n // Render more detail in tracks' visible elements.\n // FIXME: do not do this right now; it is not fully implemented--e.g. data bounds\n // are not updated when new data is fetched--and fetching more detailed quantitative\n // data is not that useful.\n /*\n _.each(self.circular_views, function(view) {\n view.update_scale(scale);\n });\n */\n }, 400);\n }\n })\n )\n .attr(\"transform\", `translate(${width / 2},${height / 2})`)\n .append(\"svg:g\")\n .attr(\"class\", \"tracks\");\n\n // -- Render circular tracks. --\n\n // Create a view for each track in the visualization and render.\n this.circular_views = circular_tracks.map((track, index) => {\n var view = new CircsterBigWigTrackView({\n el: svg.append(\"g\")[0],\n track: track,\n radius_bounds: tracks_bounds[index],\n genome: self.genome,\n total_gap: total_gap\n });\n\n view.render();\n\n return view;\n });\n\n // -- Render chords tracks. --\n\n this.chords_views = chords_tracks.map(track => {\n var view = new CircsterChromInteractionsTrackView({\n el: svg.append(\"g\")[0],\n track: track,\n radius_bounds: tracks_bounds[0],\n genome: self.genome,\n total_gap: total_gap\n });\n\n view.render();\n\n return view;\n });\n\n // -- Render label track. --\n\n // Track bounds are:\n // (a) outer radius of last circular track;\n // (b)\n var outermost_radius = this.circular_views[this.circular_views.length - 1].radius_bounds[1];\n\n var track_bounds = [outermost_radius, outermost_radius + this.label_arc_height];\n\n this.label_track_view = new CircsterChromLabelTrackView({\n el: svg.append(\"g\")[0],\n track: new CircsterLabelTrack(),\n radius_bounds: track_bounds,\n genome: self.genome,\n total_gap: total_gap\n });\n\n this.label_track_view.render();\n },\n\n /**\n * Render a single track on the outside of the current visualization.\n */\n add_track: function(new_track) {\n var total_gap = this.model.get(\"config\").get_value(\"total_gap\");\n\n if (new_track.get(\"track_type\") === \"DiagonalHeatmapTrack\") {\n // Added chords track.\n var innermost_radius_bounds = this.circular_views[0].radius_bounds;\n\n var new_view = new CircsterChromInteractionsTrackView({\n el: d3.select(\"g.tracks\").append(\"g\")[0],\n track: new_track,\n radius_bounds: innermost_radius_bounds,\n genome: this.genome,\n total_gap: total_gap\n });\n\n new_view.render();\n this.chords_views.push(new_view);\n } else {\n // Added circular track.\n\n // Recompute and update circular track bounds.\n var new_track_bounds = this.get_tracks_bounds();\n _.each(this.circular_views, (track_view, i) => {\n track_view.update_radius_bounds(new_track_bounds[i]);\n });\n\n // Update chords tracks.\n _.each(this.chords_views, track_view => {\n track_view.update_radius_bounds(new_track_bounds[0]);\n });\n\n // Render new track.\n var track_index = this.circular_views.length;\n\n var track_view = new CircsterBigWigTrackView({\n el: d3.select(\"g.tracks\").append(\"g\")[0],\n track: new_track,\n radius_bounds: new_track_bounds[track_index],\n genome: this.genome,\n total_gap: total_gap\n });\n\n track_view.render();\n this.circular_views.push(track_view);\n\n // Update label track.\n /*\n FIXME: should never have to update label track because vis always expands to fit area\n within label track.\n var track_bounds = new_track_bounds[ new_track_bounds.length-1 ];\n track_bounds[1] = track_bounds[0];\n this.label_track_view.update_radius_bounds(track_bounds);\n */\n }\n },\n\n /**\n * Remove a track from the view.\n */\n remove_track: function(track, tracks, options) {\n // -- Remove track from view. --\n var track_view = this.circular_views[options.index];\n this.circular_views.splice(options.index, 1);\n track_view.$el.remove();\n\n // Recompute and update track bounds.\n var new_track_bounds = this.get_tracks_bounds();\n _.each(this.circular_views, (track_view, i) => {\n track_view.update_radius_bounds(new_track_bounds[i]);\n });\n },\n\n update_track_bounds: function() {\n // Recompute and update track bounds.\n var new_track_bounds = this.get_tracks_bounds();\n _.each(this.circular_views, (track_view, i) => {\n track_view.update_radius_bounds(new_track_bounds[i]);\n });\n\n // Update chords tracks.\n _.each(this.chords_views, track_view => {\n track_view.update_radius_bounds(new_track_bounds[0]);\n });\n }\n});\n\n/**\n * Renders a track in a Circster visualization.\n */\nvar CircsterTrackView = Backbone.View.extend({\n tagName: \"g\",\n\n /* ----------------------- Public Methods ------------------------- */\n\n initialize: function(options) {\n this.bg_stroke = \"#ddd\";\n // Fill color when loading data.\n this.loading_bg_fill = \"#ffc\";\n // Fill color when data has been loaded.\n this.bg_fill = \"#ddd\";\n this.total_gap = options.total_gap;\n this.track = options.track;\n this.radius_bounds = options.radius_bounds;\n this.genome = options.genome;\n this.chroms_layout = this._chroms_layout();\n this.data_bounds = [];\n this.scale = 1;\n this.parent_elt = d3.select(this.$el[0]);\n },\n\n /**\n * Get fill color from config.\n */\n get_fill_color: function() {\n var color = this.track.get(\"config\").get_value(\"block_color\");\n if (!color) {\n color = this.track.get(\"config\").get_value(\"color\");\n }\n return color;\n },\n\n /**\n * Render track's data by adding SVG elements to parent.\n */\n render: function() {\n // -- Create track group element. --\n var track_parent_elt = this.parent_elt;\n\n // -- Render background arcs. --\n var genome_arcs = this.chroms_layout;\n\n var arc_gen = d3.svg\n .arc()\n .innerRadius(this.radius_bounds[0])\n .outerRadius(this.radius_bounds[1]);\n\n var // Attach data to group element.\n chroms_elts = track_parent_elt\n .selectAll(\"g\")\n .data(genome_arcs)\n .enter()\n .append(\"svg:g\");\n\n var // Draw chrom arcs/paths.\n chroms_paths = chroms_elts\n .append(\"path\")\n .attr(\"d\", arc_gen)\n .attr(\"class\", \"chrom-background\")\n .style(\"stroke\", this.bg_stroke)\n .style(\"fill\", this.loading_bg_fill);\n\n // Append titles to paths.\n chroms_paths.append(\"title\").text(d => d.data.chrom);\n\n // -- Render track data and, when track data is rendered, apply preferences and update chrom_elts fill. --\n\n var self = this;\n\n var data_manager = self.track.get(\"data_manager\");\n\n var // If track has a data manager, get deferred that resolves when data is ready.\n data_ready_deferred = data_manager ? data_manager.data_is_ready() : true;\n\n // When data is ready, render track.\n $.when(data_ready_deferred).then(() => {\n $.when(self._render_data(track_parent_elt)).then(() => {\n chroms_paths.style(\"fill\", self.bg_fill);\n\n // Render labels after data is available so that data attributes are available.\n self.render_labels();\n });\n });\n },\n\n /**\n * Render track labels.\n */\n render_labels: function() {},\n\n /**\n * Update radius bounds.\n */\n update_radius_bounds: function(radius_bounds) {\n // Update bounds.\n this.radius_bounds = radius_bounds;\n\n // -- Update background arcs. --\n var new_d = d3.svg\n .arc()\n .innerRadius(this.radius_bounds[0])\n .outerRadius(this.radius_bounds[1]);\n\n this.parent_elt\n .selectAll(\"g>path.chrom-background\")\n .transition()\n .duration(1000)\n .attr(\"d\", new_d);\n\n this._transition_chrom_data();\n\n this._transition_labels();\n },\n\n /**\n * Update view scale. This fetches more data if scale is increased.\n */\n update_scale: function(new_scale) {\n // -- Update scale and return if new scale is less than old scale. --\n\n var old_scale = this.scale;\n this.scale = new_scale;\n if (new_scale <= old_scale) {\n return;\n }\n\n // -- Scale increased, so render visible data with more detail. --\n\n var self = this;\n\n var utils = new SVGUtils();\n\n // Select all chrom data and filter to operate on those that are visible.\n this.parent_elt\n .selectAll(\"path.chrom-data\")\n .filter(function(d, i) {\n return utils.is_visible(this);\n })\n .each(function(d, i) {\n // -- Now operating on a single path element representing chromosome data. --\n\n var path_elt = d3.select(this);\n\n var chrom = path_elt.attr(\"chrom\");\n var chrom_region = self.genome.get_chrom_region(chrom);\n var data_manager = self.track.get(\"data_manager\");\n var data_deferred;\n\n // If can't get more detailed data, return.\n if (!data_manager.can_get_more_detailed_data(chrom_region)) {\n return;\n }\n\n // -- Get more detailed data. --\n data_deferred = self.track\n .get(\"data_manager\")\n .get_more_detailed_data(chrom_region, \"Coverage\", 0, new_scale);\n\n // When more data is available, use new data to redraw path.\n $.when(data_deferred).then(data => {\n // Remove current data path.\n path_elt.remove();\n\n // Update data bounds with new data.\n self._update_data_bounds();\n\n // Find chromosome arc to draw data on.\n var chrom_arc = _.find(self.chroms_layout, layout => layout.data.chrom === chrom);\n\n // Add new data path and apply preferences.\n var color = self.get_fill_color();\n self\n ._render_chrom_data(self.parent_elt, chrom_arc, data)\n .style(\"stroke\", color)\n .style(\"fill\", color);\n });\n });\n\n return self;\n },\n\n /* ----------------------- Internal Methods ------------------------- */\n\n /**\n * Transitions chrom data to new values (e.g new radius or data bounds).\n */\n _transition_chrom_data: function() {\n var track = this.track;\n var chrom_arcs = this.chroms_layout;\n var chrom_data_paths = this.parent_elt.selectAll(\"g>path.chrom-data\");\n var num_paths = chrom_data_paths[0].length;\n\n if (num_paths > 0) {\n var self = this;\n $.when(track.get(\"data_manager\").get_genome_wide_data(this.genome)).then(genome_wide_data => {\n // Map chrom data to path data, filtering out null values.\n var path_data = _.reject(\n _.map(genome_wide_data, (chrom_data, i) => {\n var rval = null;\n\n var path_fn = self._get_path_function(chrom_arcs[i], chrom_data);\n\n if (path_fn) {\n rval = path_fn(chrom_data.data);\n }\n return rval;\n }),\n p_data => p_data === null\n );\n\n // Transition each path for data and color.\n var color = track.get(\"config\").get_value(\"color\");\n chrom_data_paths.each(function(path, index) {\n d3\n .select(this)\n .transition()\n .duration(1000)\n .style(\"stroke\", color)\n .style(\"fill\", color)\n .attr(\"d\", path_data[index]);\n });\n });\n }\n },\n\n /**\n * Transition labels to new values (e.g new radius or data bounds).\n */\n _transition_labels: function() {},\n\n /**\n * Update data bounds. If there are new_bounds, use them; otherwise use\n * default data bounds.\n */\n _update_data_bounds: function(new_bounds) {\n var old_bounds = this.data_bounds;\n this.data_bounds =\n new_bounds || this.get_data_bounds(this.track.get(\"data_manager\").get_genome_wide_data(this.genome));\n this._transition_chrom_data();\n },\n\n /**\n * Render data as elements attached to svg.\n */\n _render_data: function(svg) {\n var self = this;\n var chrom_arcs = this.chroms_layout;\n var track = this.track;\n var rendered_deferred = $.Deferred();\n\n // When genome-wide data is available, render data.\n $.when(track.get(\"data_manager\").get_genome_wide_data(this.genome)).then(genome_wide_data => {\n // Set bounds.\n self.data_bounds = self.get_data_bounds(genome_wide_data);\n\n // Set min, max value in config so that they can be adjusted. Make this silent\n // because these attributes are watched for changes and the viz is updated\n // accordingly (set up in initialize). Because we are setting up, we don't want\n // the watch to trigger events here.\n track.get(\"config\").set_value(\"min_value\", self.data_bounds[0], {\n silent: true\n });\n track.get(\"config\").set_value(\"max_value\", self.data_bounds[1], {\n silent: true\n });\n\n // Merge chroms layout with data.\n var layout_and_data = _.zip(chrom_arcs, genome_wide_data);\n\n // Render each chromosome's data.\n _.each(layout_and_data, chrom_info => {\n var chrom_arc = chrom_info[0];\n var data = chrom_info[1];\n return self._render_chrom_data(svg, chrom_arc, data);\n });\n\n // Apply prefs to all track data.\n var color = self.get_fill_color();\n self.parent_elt\n .selectAll(\"path.chrom-data\")\n .style(\"stroke\", color)\n .style(\"fill\", color);\n\n rendered_deferred.resolve(svg);\n });\n\n return rendered_deferred;\n },\n\n /**\n * Render a chromosome data and attach elements to svg.\n */\n _render_chrom_data: function(svg, chrom_arc, data) {},\n\n /**\n * Returns data for creating a path for the given data using chrom_arc and data bounds.\n */\n _get_path_function: function(chrom_arc, chrom_data) {},\n\n /**\n * Returns arc layouts for genome's chromosomes/contigs. Arcs are arranged in a circle\n * separated by gaps.\n */\n _chroms_layout: function() {\n // Setup chroms layout using pie.\n var chroms_info = this.genome.get_chroms_info();\n\n var pie_layout = d3.layout\n .pie()\n .value(d => d.len)\n .sort(null);\n\n var init_arcs = pie_layout(chroms_info);\n var gap_per_chrom = 2 * Math.PI * this.total_gap / chroms_info.length;\n\n var chrom_arcs = _.map(init_arcs, (arc, index) => {\n // For short chroms, endAngle === startAngle.\n var new_endAngle = arc.endAngle - gap_per_chrom;\n arc.endAngle = new_endAngle > arc.startAngle ? new_endAngle : arc.startAngle;\n return arc;\n });\n\n return chrom_arcs;\n }\n});\n\n/**\n * Render chromosome labels.\n */\nvar CircsterChromLabelTrackView = CircsterTrackView.extend({\n initialize: function(options) {\n CircsterTrackView.prototype.initialize.call(this, options);\n // Use a single arc for rendering data.\n this.innerRadius = this.radius_bounds[0];\n this.radius_bounds[0] = this.radius_bounds[1];\n this.bg_stroke = \"#fff\";\n this.bg_fill = \"#fff\";\n\n // Minimum arc distance for labels to be applied.\n this.min_arc_len = 0.05;\n },\n\n /**\n * Render labels.\n */\n _render_data: function(svg) {\n // -- Add chromosome label where it will fit; an alternative labeling mechanism\n // would be nice for small chromosomes. --\n var self = this;\n\n var chrom_arcs = svg.selectAll(\"g\");\n\n chrom_arcs.selectAll(\"path\").attr(\"id\", d => `label-${d.data.chrom}`);\n\n chrom_arcs\n .append(\"svg:text\")\n .filter(d => d.endAngle - d.startAngle > self.min_arc_len)\n .attr(\"text-anchor\", \"middle\")\n .append(\"svg:textPath\")\n .attr(\"class\", \"chrom-label\")\n .attr(\"xlink:href\", d => `#label-${d.data.chrom}`)\n .attr(\"startOffset\", \"25%\")\n .text(d => d.data.chrom);\n\n // -- Add ticks to denote chromosome length. --\n\n /** Returns an array of tick angles and labels, given a chrom arc. */\n var chromArcTicks = d => {\n var k = (d.endAngle - d.startAngle) / d.value;\n\n var ticks = d3.range(0, d.value, 25000000).map((v, i) => ({\n radius: self.innerRadius,\n angle: v * k + d.startAngle,\n label: i === 0 ? 0 : i % 3 ? null : self.formatNum(v)\n }));\n\n // If there are fewer that 4 ticks, label last tick so that at least one non-zero tick is labeled.\n if (ticks.length < 4) {\n ticks[ticks.length - 1].label = self.formatNum(\n Math.round((ticks[ticks.length - 1].angle - d.startAngle) / k)\n );\n }\n\n return ticks;\n };\n\n /** Rotate and move text as needed. */\n var textTransform = d => (d.angle > Math.PI ? \"rotate(180)translate(-16)\" : null);\n\n // Filter chroms for only those large enough for display.\n var visibleChroms = _.filter(this.chroms_layout, c => c.endAngle - c.startAngle > self.min_arc_len);\n\n this.drawTicks(this.parent_elt, visibleChroms, chromArcTicks, textTransform);\n }\n});\n_.extend(CircsterChromLabelTrackView.prototype, UsesTicks);\n\n/**\n * View for quantitative track in Circster.\n */\nvar CircsterQuantitativeTrackView = CircsterTrackView.extend({\n initialize: function(options) {\n CircsterTrackView.prototype.initialize.call(this, options);\n\n // When config settings change, update view.\n var track_config = this.track.get(\"config\");\n track_config.get(\"min_value\").on(\"change:value\", this._update_min_max, this);\n track_config.get(\"max_value\").on(\"change:value\", this._update_min_max, this);\n track_config.get(\"color\").on(\"change:value\", this._transition_chrom_data, this);\n },\n\n /**\n * Update track when min and/or max are changed.\n */\n _update_min_max: function() {\n var track_config = this.track.get(\"config\");\n\n var new_bounds = [track_config.get_value(\"min_value\"), track_config.get_value(\"max_value\")];\n\n this._update_data_bounds(new_bounds);\n\n // FIXME: this works to update tick/text bounds, but there's probably a better way to do this\n // by updating the data itself.\n this.parent_elt.selectAll(\".min_max\").text((d, i) => new_bounds[i]);\n },\n\n /**\n * Returns quantile for an array of numbers.\n */\n _quantile: function(numbers, quantile) {\n numbers.sort(d3.ascending);\n return d3.quantile(numbers, quantile);\n },\n\n /**\n * Renders quantitative data with the form [x, value] and assumes data is equally spaced across\n * chromosome. Attachs a dict with track and chrom name information to DOM element.\n */\n _render_chrom_data: function(svg, chrom_arc, chrom_data) {\n var path_data = this._get_path_function(chrom_arc, chrom_data);\n\n if (!path_data) {\n return null;\n }\n\n // There is path data, so render as path.\n var parent = svg.datum(chrom_data.data);\n\n var path = parent\n .append(\"path\")\n .attr(\"class\", \"chrom-data\")\n .attr(\"chrom\", chrom_arc.data.chrom)\n .attr(\"d\", path_data);\n\n return path;\n },\n\n /**\n * Returns function for creating a path across the chrom arc.\n */\n _get_path_function: function(chrom_arc, chrom_data) {\n // If no chrom data, return null.\n if (typeof chrom_data === \"string\" || !chrom_data.data || chrom_data.data.length === 0) {\n return null;\n }\n\n // Radius scaler.\n var radius = d3.scale\n .linear()\n .domain(this.data_bounds)\n .range(this.radius_bounds)\n .clamp(true);\n\n // Scaler for placing data points across arc.\n var angle = d3.scale\n .linear()\n .domain([0, chrom_data.data.length])\n .range([chrom_arc.startAngle, chrom_arc.endAngle]);\n\n // Use line generator to create area.\n var line = d3.svg.line\n .radial()\n .interpolate(\"linear\")\n .radius(d => radius(d[1]))\n .angle((d, i) => angle(i));\n\n return d3.svg.area\n .radial()\n .interpolate(line.interpolate())\n .innerRadius(radius(0))\n .outerRadius(line.radius())\n .angle(line.angle());\n },\n\n /**\n * Render track min, max using ticks.\n */\n render_labels: function() {\n var self = this;\n\n var // Keep counter of visible chroms.\n textTransform = () => \"rotate(90)\";\n\n // FIXME:\n // (1) using min_max class below is needed for _update_min_max, which could be improved.\n // (2) showing config on tick click should be replaced by proper track config icon.\n\n // Draw min, max on first chrom only.\n var ticks = this.drawTicks(\n this.parent_elt,\n [this.chroms_layout[0]],\n this._data_bounds_ticks_fn(),\n textTransform,\n true\n ).classed(\"min_max\", true);\n\n // Show config when ticks are clicked on.\n _.each(ticks, tick => {\n $(tick).click(() => {\n var view = new config.ConfigSettingCollectionView({\n collection: self.track.get(\"config\")\n });\n view.render_in_modal(\"Configure Track\");\n });\n });\n\n /*\n // Filter for visible chroms, then for every third chrom so that labels attached to only every\n // third chrom.\n var visibleChroms = _.filter(this.chroms_layout, function(c) { return c.endAngle - c.startAngle > 0.08; }),\n labeledChroms = _.filter(visibleChroms, function(c, i) { return i % 3 === 0; });\n this.drawTicks(this.parent_elt, labeledChroms, this._data_bounds_ticks_fn(), textTransform, true);\n */\n },\n\n /**\n * Transition labels to new values (e.g new radius or data bounds).\n */\n _transition_labels: function() {\n // FIXME: (a) pull out function for getting labeled chroms? and (b) function used in transition below\n // is copied from UseTicks mixin, so pull out and make generally available.\n\n // If there are no data bounds, nothing to transition.\n if (this.data_bounds.length === 0) {\n return;\n }\n\n // Transition labels to new radius bounds.\n var self = this;\n\n var visibleChroms = _.filter(this.chroms_layout, c => c.endAngle - c.startAngle > 0.08);\n\n var labeledChroms = _.filter(visibleChroms, (c, i) => i % 3 === 0);\n\n var new_data = _.flatten(_.map(labeledChroms, c => self._data_bounds_ticks_fn()(c)));\n\n this.parent_elt\n .selectAll(\"g.tick\")\n .data(new_data)\n .transition()\n .attr(\"transform\", d => `rotate(${d.angle * 180 / Math.PI - 90})translate(${d.radius},0)`);\n },\n\n /**\n * Get function for locating data bounds ticks.\n */\n _data_bounds_ticks_fn: function() {\n // Closure vars.\n var self = this;\n visibleChroms = 0;\n\n // Return function for locating ticks based on chrom arc data.\n return (\n d // Set up data to display min, max ticks.\n ) => [\n {\n radius: self.radius_bounds[0],\n angle: d.startAngle,\n label: self.formatNum(self.data_bounds[0])\n },\n {\n radius: self.radius_bounds[1],\n angle: d.startAngle,\n label: self.formatNum(self.data_bounds[1])\n }\n ];\n },\n\n /**\n * Returns an array with two values denoting the minimum and maximum\n * values for the track.\n */\n get_data_bounds: function(data) {}\n});\n_.extend(CircsterQuantitativeTrackView.prototype, UsesTicks);\n\n/**\n * Bigwig track view in Circster.\n */\nvar CircsterBigWigTrackView = CircsterQuantitativeTrackView.extend({\n get_data_bounds: function(data) {\n // Set max across dataset by extracting all values, flattening them into a\n // single array, and getting third quartile.\n var values = _.flatten(\n _.map(data, d => {\n if (d) {\n // Each data point has the form [position, value], so return all values.\n return _.map(\n d.data,\n (\n p // Null is used for a lack of data; resolve null to 0 for comparison.\n ) => parseInt(p[1], 10) || 0\n );\n } else {\n return 0;\n }\n })\n );\n\n // For max, use 98% quantile in attempt to avoid very large values. However, this max may be 0\n // for sparsely populated data, so use max in that case.\n return [_.min(values), this._quantile(values, 0.98) || _.max(values)];\n }\n});\n\n/**\n * Chromosome interactions track view in Circster.\n */\nvar CircsterChromInteractionsTrackView = CircsterTrackView.extend({\n render: function() {\n var self = this;\n\n // When data is ready, render track.\n $.when(self.track.get(\"data_manager\").data_is_ready()).then(() => {\n // When data has been fetched, render track.\n $.when(self.track.get(\"data_manager\").get_genome_wide_data(self.genome)).then(genome_wide_data => {\n var chord_data = [];\n var chroms_info = self.genome.get_chroms_info();\n // Convert chromosome data into chord data.\n _.each(genome_wide_data, (chrom_data, index) => {\n // Map each interaction into chord data.\n var cur_chrom = chroms_info[index].chrom;\n var chrom_chord_data = _.map(chrom_data.data, datum => {\n // Each datum is an interaction/chord.\n var source_angle = self._get_region_angle(cur_chrom, datum[1]);\n\n var target_angle = self._get_region_angle(datum[3], datum[4]);\n\n return {\n source: {\n startAngle: source_angle,\n endAngle: source_angle + 0.01\n },\n target: {\n startAngle: target_angle,\n endAngle: target_angle + 0.01\n }\n };\n });\n\n chord_data = chord_data.concat(chrom_chord_data);\n });\n\n self.parent_elt\n .append(\"g\")\n .attr(\"class\", \"chord\")\n .selectAll(\"path\")\n .data(chord_data)\n .enter()\n .append(\"path\")\n .style(\"fill\", self.get_fill_color())\n .attr(\"d\", d3.svg.chord().radius(self.radius_bounds[0]))\n .style(\"opacity\", 1);\n });\n });\n },\n\n update_radius_bounds: function(radius_bounds) {\n this.radius_bounds = radius_bounds;\n this.parent_elt\n .selectAll(\"path\")\n .transition()\n .attr(\"d\", d3.svg.chord().radius(this.radius_bounds[0]));\n },\n\n /**\n * Returns radians for a genomic position.\n */\n _get_region_angle: function(chrom, position) {\n // Find chrom angle data\n var chrom_angle_data = _.find(this.chroms_layout, chrom_layout => chrom_layout.data.chrom === chrom);\n\n // Return angle at position.\n return (\n chrom_angle_data.endAngle -\n (chrom_angle_data.endAngle - chrom_angle_data.startAngle) *\n (chrom_angle_data.data.len - position) /\n chrom_angle_data.data.len\n );\n }\n});\n\n// circster app loader\nvar Circster = Backbone.View.extend({\n initialize: function() {\n // load css\n mod_utils.cssLoadFile(\"static/style/circster.css\");\n // -- Configure visualization --\n var genome = new visualization.Genome(galaxy_config.app.genome);\n\n var vis = new visualization.GenomeVisualization(galaxy_config.app.viz_config);\n\n // Add Circster-specific config options.\n vis.get(\"config\").add([\n {\n key: \"arc_dataset_height\",\n label: \"Arc Dataset Height\",\n type: \"int\",\n value: 25,\n view: \"circster\"\n },\n {\n key: \"track_gap\",\n label: \"Gap Between Tracks\",\n type: \"int\",\n value: 5,\n view: \"circster\"\n },\n {\n key: \"total_gap\",\n label: \"Gap [0-1]\",\n type: \"float\",\n value: 0.4,\n view: \"circster\",\n hidden: true\n }\n ]);\n\n var viz_view = new CircsterView({\n // view pane\n el: $(\"#center .unified-panel-body\"),\n genome: genome,\n model: vis\n });\n\n // Render vizualization\n viz_view.render();\n\n // setup title\n $(\"#center .unified-panel-header-inner\").append(\n `${galaxy_config.app.viz_config.title} ${galaxy_config.app.viz_config.dbkey}`\n );\n\n // setup menu\n var menu = mod_icon_btn.create_icon_buttons_menu(\n [\n {\n icon_class: \"plus-button\",\n title: \"Add tracks\",\n on_click: function() {\n visualization.select_datasets({ dbkey: vis.get(\"dbkey\") }, tracks => {\n vis.add_tracks(tracks);\n });\n }\n },\n {\n icon_class: \"gear\",\n title: \"Settings\",\n on_click: function() {\n var view = new config.ConfigSettingCollectionView({\n collection: vis.get(\"config\")\n });\n view.render_in_modal(\"Configure Visualization\");\n }\n },\n {\n icon_class: \"disk--arrow\",\n title: \"Save\",\n on_click: function() {\n // show saving dialog box\n Galaxy.modal.show({\n title: \"Saving...\",\n body: \"progress\"\n });\n\n // send to server\n $.ajax({\n url: `${Galaxy.root}visualization/save`,\n type: \"POST\",\n dataType: \"json\",\n data: {\n id: vis.get(\"vis_id\"),\n title: vis.get(\"title\"),\n dbkey: vis.get(\"dbkey\"),\n type: \"trackster\",\n vis_json: JSON.stringify(vis)\n }\n })\n .success(vis_info => {\n Galaxy.modal.hide();\n vis.set(\"vis_id\", vis_info.vis_id);\n })\n .error(() => {\n // show dialog\n Galaxy.modal.show({\n title: \"Could Not Save\",\n body: \"Could not save visualization. Please try again later.\",\n buttons: {\n Cancel: function() {\n Galaxy.modal.hide();\n }\n }\n });\n });\n }\n },\n {\n icon_class: \"cross-circle\",\n title: \"Close\",\n on_click: function() {\n window.location = `${Galaxy.root}visualizations/list`;\n }\n }\n ],\n { tooltip_config: { placement: \"bottom\" } }\n );\n\n // add menu\n menu.$el.attr(\"style\", \"float: right\");\n $(\"#center .unified-panel-header-inner\").append(menu.$el);\n\n // manual tooltip config because default gravity is S and cannot be changed\n $(\".menu-button\").tooltip({ placement: \"bottom\" });\n }\n});\n\n// Module exports.\nexport default {\n GalaxyApp: Circster\n};\n"]} \ No newline at end of file diff --git a/static/maps/viz/trackster.js.map b/static/maps/viz/trackster.js.map index 10d19b682ee..e2f86cdcef2 100644 --- a/static/maps/viz/trackster.js.map +++ b/static/maps/viz/trackster.js.map @@ -1 +1 @@ -{"version":3,"sources":["viz/trackster.js"],"names":["_","ui","view","_utils2","default","cssLoadFile","Base","this","initialize","apply","arguments","extend","Backbone","Model","TracksterUI","baseURL","save_viz","Galaxy","modal","show","title","body","bookmarks","$","position","children","text","annotation","overview_track_name","overview_drawable","config","get_value","viz_config","chrom","start","low","end","high","overview","ajax","url","root","type","dbkey","vis_json","JSON","stringify","success","vis_info","hide","to_dict","vis_id","viewport","window","location","hash","error","menu","_iconButton2","create_icon_buttons_menu","icon_class","select_datasets","new_tracks","each","track","add_drawable","_tracks2","object_from_template","on_click","DrawableGroup","name","css","self","handle_unsaved_changes","placement","buttonMenu","add_bookmark","editable","bookmarks_container","new_bookmark","addClass","appendTo","position_div","click","go_to","delete_icon_container","prependTo","remove","has_changes","annotation_div","num_rows","help_text","make_text_editable","use_textarea","create_visualization","view_config","viewport_config","drawables_config","bookmarks_config","header","editor","when","load_chroms_deferred","undefined","overview_drawable_name","change_chrom","chrom_info","i","length","drawables","set_overview","bookmark","set_up_router","options","_visualization2","TrackBrowserRouter","history","init_keyboard_nav","document","keyup","e","srcElement","is","which","move_fraction","Math","round","viewport_container","height","scrollTop","buttons","Cancel","Save","then","TracksterView","View","createButtonMenu","$el","attr","append","galaxy_config","force_right_panel","app","id","view_existing","choose_existing_or_new","get","listTracksParams","dataset_id","hda_ldda","gene_region","dataset_params","_queryStringParsing2","View in saved visualization","view_in_saved","tracks_grid","_gridView2","embedded","Add to visualization","parent","find","val","param","view_new","data","init_editor","alert","response","default_dbkey","Create","create_browser","select2","dbkeys_in_genomes","map","r","contains","template_view_new","focus","html","container","add_dataset","GalaxyApp","data_type","dataType","track_data","on"],"mappings":"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","file":"../../scripts/viz/trackster.js","sourcesContent":["/**\n * Top-level trackster code, used for creating/loading visualizations and user interface elements.\n */\n\n// global variables\nvar ui = null;\nvar view = null;\nvar browser_router = null;\n\n// trackster viewer\nimport * as _ from \"libs/underscore\";\nimport tracks from \"viz/trackster/tracks\";\nimport visualization from \"viz/visualization\";\nimport mod_icon_btn from \"mvc/ui/icon-button\";\nimport query_string from \"utils/query-string-parsing\";\nimport GridView from \"mvc/grid/grid-view\";\nimport mod_utils from \"utils/utils\";\nimport \"libs/jquery/jquery.event.drag\";\nimport \"libs/jquery/jquery.event.hover\";\nimport \"libs/jquery/jquery.mousewheel\";\nimport \"libs/jquery/jquery-ui\";\nimport \"libs/jquery/select2\";\nimport \"libs/farbtastic\";\nimport \"libs/jquery/jquery.form\";\nimport \"libs/jquery/jquery.rating\";\nimport \"ui/editable-text\";\nmod_utils.cssLoadFile(\"static/style/jquery.rating.css\");\nmod_utils.cssLoadFile(\"static/style/autocomplete_tagging.css\");\nmod_utils.cssLoadFile(\"static/style/jquery-ui/smoothness/jquery-ui.css\");\nmod_utils.cssLoadFile(\"static/style/library.css\");\nmod_utils.cssLoadFile(\"static/style/trackster.css\");\n/**\n * Base Object/Model for inhertiance.\n */\nvar Base = function() {\n if (this.initialize) {\n this.initialize.apply(this, arguments);\n }\n};\nBase.extend = Backbone.Model.extend;\n\n/**\n * User interface controls for trackster\n */\nvar TracksterUI = Base.extend({\n initialize: function(baseURL) {\n this.baseURL = baseURL;\n },\n\n /**\n * Save visualization, returning a Deferred object for the remote call to save.\n */\n save_viz: function() {\n // show dialog\n Galaxy.modal.show({ title: \"Saving...\", body: \"progress\" });\n\n // Save bookmarks.\n var bookmarks = [];\n $(\".bookmark\").each(function() {\n bookmarks.push({\n position: $(this)\n .children(\".position\")\n .text(),\n annotation: $(this)\n .children(\".annotation\")\n .text()\n });\n });\n\n // FIXME: give unique IDs to Drawables and save overview as ID.\n var overview_track_name = view.overview_drawable ? view.overview_drawable.config.get_value(\"name\") : null;\n\n var viz_config = {\n view: view.to_dict(),\n viewport: {\n chrom: view.chrom,\n start: view.low,\n end: view.high,\n overview: overview_track_name\n },\n bookmarks: bookmarks\n };\n\n // Make call to save visualization.\n return $.ajax({\n url: `${Galaxy.root}visualization/save`,\n type: \"POST\",\n dataType: \"json\",\n data: {\n id: view.vis_id,\n title: view.config.get_value(\"name\"),\n dbkey: view.dbkey,\n type: \"trackster\",\n vis_json: JSON.stringify(viz_config)\n }\n })\n .success(vis_info => {\n Galaxy.modal.hide();\n view.vis_id = vis_info.vis_id;\n view.has_changes = false;\n\n // Needed to set URL when first saving a visualization.\n window.history.pushState({}, \"\", vis_info.url + window.location.hash);\n })\n .error(() => {\n // show dialog\n Galaxy.modal.show({\n title: \"Could Not Save\",\n body: \"Could not save visualization. Please try again later.\",\n buttons: {\n Cancel: function() {\n Galaxy.modal.hide();\n }\n }\n });\n });\n },\n\n /**\n * Create button menu\n */\n createButtonMenu: function() {\n var self = this;\n\n var menu = mod_icon_btn.create_icon_buttons_menu(\n [\n {\n icon_class: \"plus-button\",\n title: \"Add tracks\",\n on_click: function() {\n visualization.select_datasets({ dbkey: view.dbkey }, new_tracks => {\n _.each(new_tracks, track => {\n view.add_drawable(tracks.object_from_template(track, view, view));\n });\n });\n }\n },\n {\n icon_class: \"block--plus\",\n title: \"Add group\",\n on_click: function() {\n view.add_drawable(\n new tracks.DrawableGroup(view, view, {\n name: \"New Group\"\n })\n );\n }\n },\n {\n icon_class: \"bookmarks\",\n title: \"Bookmarks\",\n on_click: function() {\n // HACK -- use style to determine if panel is hidden and hide/show accordingly.\n force_right_panel($(\"div#right\").css(\"right\") == \"0px\" ? \"hide\" : \"show\");\n }\n },\n {\n icon_class: \"globe\",\n title: \"Circster\",\n on_click: function() {\n window.location = `${self.baseURL}visualization/circster?id=${view.vis_id}`;\n }\n },\n {\n icon_class: \"disk--arrow\",\n title: \"Save\",\n on_click: function() {\n self.save_viz();\n }\n },\n {\n icon_class: \"cross-circle\",\n title: \"Close\",\n on_click: function() {\n self.handle_unsaved_changes(view);\n }\n }\n ],\n {\n tooltip_config: { placement: \"bottom\" }\n }\n );\n\n this.buttonMenu = menu;\n return menu;\n },\n\n /**\n * Add bookmark.\n */\n add_bookmark: function(position, annotation, editable) {\n // Create HTML.\n var bookmarks_container = $(\"#right .unified-panel-body\");\n\n var new_bookmark = $(\"
\")\n .addClass(\"bookmark\")\n .appendTo(bookmarks_container);\n\n var position_div = $(\"
\")\n .addClass(\"position\")\n .appendTo(new_bookmark);\n\n var position_link = $(\"\")\n .text(position)\n .appendTo(position_div)\n .click(() => {\n view.go_to(position);\n return false;\n });\n\n var annotation_div = $(\"
\")\n .text(annotation)\n .appendTo(new_bookmark);\n\n // If editable, enable bookmark deletion and annotation editing.\n if (editable) {\n var delete_icon_container = $(\"
\")\n .addClass(\"delete-icon-container\")\n .prependTo(new_bookmark)\n .click(() => {\n // Remove bookmark.\n new_bookmark.slideUp(\"fast\");\n new_bookmark.remove();\n view.has_changes = true;\n return false;\n });\n\n var delete_icon = $(\"\")\n .addClass(\"icon-button delete\")\n .appendTo(delete_icon_container);\n\n annotation_div\n .make_text_editable({\n num_rows: 3,\n use_textarea: true,\n help_text: \"Edit bookmark note\"\n })\n .addClass(\"annotation\");\n }\n\n view.has_changes = true;\n return new_bookmark;\n },\n\n /**\n * Create a complete Trackster visualization. Returns view.\n */\n create_visualization: function(view_config, viewport_config, drawables_config, bookmarks_config, editable) {\n // Create view.\n var self = this;\n\n var view = new tracks.TracksterView(_.extend(view_config, { header: false }));\n\n view.editor = true;\n $.when(view.load_chroms_deferred).then(chrom_info => {\n // Viewport config.\n if (viewport_config) {\n var chrom = viewport_config.chrom;\n var start = viewport_config.start;\n var end = viewport_config.end;\n var overview_drawable_name = viewport_config.overview;\n\n if (chrom && start !== undefined && end) {\n view.change_chrom(chrom, start, end);\n } else {\n // No valid viewport, so use first chromosome.\n view.change_chrom(chrom_info[0].chrom);\n }\n } else {\n // No viewport, so use first chromosome.\n view.change_chrom(chrom_info[0].chrom);\n }\n\n // Add drawables to view.\n if (drawables_config) {\n // FIXME: can from_dict() be used to create view and add drawables?\n var drawable_config;\n\n var drawable_type;\n var drawable;\n for (var i = 0; i < drawables_config.length; i++) {\n view.add_drawable(tracks.object_from_template(drawables_config[i], view, view));\n }\n }\n\n // Set overview.\n var overview_drawable;\n for (var i = 0; i < view.drawables.length; i++) {\n if (view.drawables[i].config.get_value(\"name\") === overview_drawable_name) {\n view.set_overview(view.drawables[i]);\n break;\n }\n }\n\n // Load bookmarks.\n if (bookmarks_config) {\n var bookmark;\n for (var i = 0; i < bookmarks_config.length; i++) {\n bookmark = bookmarks_config[i];\n self.add_bookmark(bookmark[\"position\"], bookmark[\"annotation\"], editable);\n }\n }\n\n // View has no changes as of yet.\n view.has_changes = false;\n });\n\n // Final initialization.\n this.set_up_router({ view: view });\n\n return view;\n },\n\n /**\n * Set up location router to use hashes as track browser locations.\n */\n set_up_router: function(options) {\n new visualization.TrackBrowserRouter(options);\n Backbone.history.start();\n },\n\n /**\n * Set up keyboard navigation for a visualization.\n */\n init_keyboard_nav: function(view) {\n // Keyboard navigation. Scroll ~7% of height when scrolling up/down.\n $(document).keyup(e => {\n // Do not navigate if arrow keys used in input element.\n if ($(e.srcElement).is(\":input\")) {\n return;\n }\n\n // Key codes: left == 37, up == 38, right == 39, down == 40\n switch (e.which) {\n case 37:\n view.move_fraction(0.25);\n break;\n case 38:\n var change = Math.round(view.viewport_container.height() / 15.0);\n view.viewport_container.scrollTop(view.viewport_container.scrollTop() - 20);\n break;\n case 39:\n view.move_fraction(-0.25);\n break;\n case 40:\n var change = Math.round(view.viewport_container.height() / 15.0);\n view.viewport_container.scrollTop(view.viewport_container.scrollTop() + 20);\n break;\n }\n });\n },\n\n /**\n * Handle unsaved changes in visualization.\n */\n handle_unsaved_changes: function(view) {\n if (view.has_changes) {\n var self = this;\n Galaxy.modal.show({\n title: \"Close visualization\",\n body: \"There are unsaved changes to your visualization which will be lost if you do not save them.\",\n buttons: {\n Cancel: function() {\n Galaxy.modal.hide();\n },\n \"Leave without Saving\": function() {\n $(window).off(\"beforeunload\");\n window.location = `${Galaxy.root}visualization`;\n },\n Save: function() {\n $.when(self.save_viz()).then(() => {\n window.location = `${Galaxy.root}visualization`;\n });\n }\n }\n });\n } else {\n window.location = `${Galaxy.root}visualization`;\n }\n }\n});\n\nvar TracksterView = Backbone.View.extend({\n // initalize trackster\n initialize: function() {\n // load ui\n ui = new TracksterUI(Galaxy.root);\n\n // create button menu\n ui.createButtonMenu();\n\n // attach the button menu to the panel header and float it left\n ui.buttonMenu.$el.attr(\"style\", \"float: right\");\n\n // add to center panel\n $(\"#center .unified-panel-header-inner\").append(ui.buttonMenu.$el);\n\n // configure right panel\n $(\"#right .unified-panel-title\").append(\"Bookmarks\");\n $(\"#right .unified-panel-icons\").append(\n \"\"\n );\n\n // resize view when showing/hiding right panel (bookmarks for now).\n $(\"#right-border\").click(() => {\n view.resize_window();\n });\n\n // hide right panel\n force_right_panel(\"hide\");\n\n // check if id is available\n if (galaxy_config.app.id) {\n this.view_existing();\n } else if (query_string.get(\"dataset_id\")) {\n this.choose_existing_or_new();\n } else {\n this.view_new();\n }\n },\n\n choose_existing_or_new: function() {\n var self = this;\n var dbkey = query_string.get(\"dbkey\");\n var listTracksParams = {};\n\n var dataset_params = {\n dbkey: dbkey,\n dataset_id: query_string.get(\"dataset_id\"),\n hda_ldda: query_string.get(\"hda_ldda\"),\n gene_region: query_string.get(\"gene_region\")\n };\n\n if (dbkey) {\n listTracksParams[\"f-dbkey\"] = dbkey;\n }\n\n Galaxy.modal.show({\n title: \"View Data in a New or Saved Visualization?\",\n // either have text in here or have to remove body and the header/footer margins\n body: `

    You can add this dataset as:
  • a new track to one of your existing, saved Trackster sessions if they share the genome build: ${dbkey ||\n \"Not available.\"}
  • or create a new session with this dataset as the only track

`,\n buttons: {\n Cancel: function() {\n window.location = `${Galaxy.root}visualizations/list`;\n },\n \"View in saved visualization\": function() {\n self.view_in_saved(dataset_params);\n },\n \"View in new visualization\": function() {\n self.view_new();\n }\n }\n });\n },\n\n // view\n view_in_saved: function(dataset_params) {\n var tracks_grid = new GridView({\n url_base: `${Galaxy.root}visualization/list_tracks`,\n dict_format: true,\n embedded: true\n });\n Galaxy.modal.show({\n title: \"Add Data to Saved Visualization\",\n body: tracks_grid.$el,\n buttons: {\n Cancel: function() {\n window.location = `${Galaxy.root}visualizations/list`;\n },\n \"Add to visualization\": function() {\n $(parent.document)\n .find(\"input[name=id]:checked\")\n .each(function() {\n dataset_params.id = $(this).val();\n window.location = `${Galaxy.root}visualization/trackster?${$.param(dataset_params)}`;\n });\n }\n }\n });\n },\n\n // view\n view_existing: function() {\n // get config\n var viz_config = galaxy_config.app.viz_config;\n\n // view\n view = ui.create_visualization(\n {\n container: $(\"#center .unified-panel-body\"),\n name: viz_config.title,\n vis_id: viz_config.vis_id,\n dbkey: viz_config.dbkey\n },\n viz_config.viewport,\n viz_config.tracks,\n viz_config.bookmarks,\n true\n );\n\n // initialize editor\n this.init_editor();\n },\n\n // view\n view_new: function() {\n // reference this\n var self = this;\n\n // ajax\n $.ajax({\n url: `${Galaxy.root}api/genomes?chrom_info=True`,\n data: {},\n error: function() {\n alert(\"Couldn't create new browser.\");\n },\n success: function(response) {\n // show dialog\n Galaxy.modal.show({\n title: \"New Visualization\",\n body: self.template_view_new(response),\n buttons: {\n Cancel: function() {\n window.location = `${Galaxy.root}visualizations/list`;\n },\n Create: function() {\n self.create_browser($(\"#new-title\").val(), $(\"#new-dbkey\").val());\n Galaxy.modal.hide();\n }\n }\n });\n\n // select default\n var dbkeys_in_genomes = response.map(r => r[1]);\n if (galaxy_config.app.default_dbkey && _.contains(dbkeys_in_genomes, galaxy_config.app.default_dbkey)) {\n $(\"#new-dbkey\").val(galaxy_config.app.default_dbkey);\n }\n\n // change focus\n $(\"#new-title\").focus();\n $(\"select[name='dbkey']\").select2();\n\n // to support the large number of options for dbkey, enable scrolling in overlay.\n $(\"#overlay\").css(\"overflow\", \"auto\");\n }\n });\n },\n\n // new browser form\n template_view_new: function(response) {\n // start template\n var html =\n '
' +\n '
' +\n '' +\n '
' +\n '' +\n \"
\" +\n '
' +\n \"
\" +\n '
' +\n '' +\n '
' +\n '
Is the build not listed here? Add a Custom Build
`;\n\n // return\n return html;\n },\n\n // create\n create_browser: function(name, dbkey) {\n $(document).trigger(\"convert_to_values\");\n\n view = ui.create_visualization(\n {\n container: $(\"#center .unified-panel-body\"),\n name: name,\n dbkey: dbkey\n },\n galaxy_config.app.gene_region\n );\n\n // initialize editor\n this.init_editor();\n\n // modify view setting\n view.editor = true;\n },\n\n // initialization for editor-specific functions.\n init_editor: function() {\n // set title\n $(\"#center .unified-panel-title\").text(`${view.config.get_value(\"name\")} (${view.dbkey})`);\n\n // add dataset\n if (galaxy_config.app.add_dataset)\n $.ajax({\n url: `${Galaxy.root}api/datasets/${galaxy_config.app.add_dataset}`,\n data: { hda_ldda: \"hda\", data_type: \"track_config\" },\n dataType: \"json\",\n success: function(track_data) {\n view.add_drawable(tracks.object_from_template(track_data, view, view));\n }\n });\n\n // initialize icons\n $(\"#add-bookmark-button\").click(() => {\n // add new bookmark.\n var position = `${view.chrom}:${view.low}-${view.high}`;\n\n var annotation = \"Bookmark description\";\n return ui.add_bookmark(position, annotation, true);\n });\n\n // initialize keyboard\n ui.init_keyboard_nav(view);\n\n $(window).on(\"beforeunload\", () => {\n if (view.has_changes) {\n return \"There are unsaved changes to your visualization that will be lost if you leave this page.\";\n }\n });\n }\n});\n\nexport default {\n TracksterUI: TracksterUI,\n GalaxyApp: TracksterView\n};\n"]} \ No newline at end of file +{"version":3,"sources":["viz/trackster.js"],"names":["_","ui","view","Base","this","initialize","apply","arguments","extend","Backbone","Model","TracksterUI","baseURL","_utils2","default","cssLoadFile","save_viz","Galaxy","modal","show","title","body","bookmarks","each","position","children","text","annotation","overview_track_name","overview_drawable","config","get_value","viz_config","to_dict","viewport","chrom","start","low","end","high","overview","$","ajax","url","root","type","dbkey","vis_json","JSON","stringify","success","vis_info","hide","vis_id","window","location","hash","error","menu","_iconButton2","create_icon_buttons_menu","icon_class","select_datasets","new_tracks","track","add_drawable","_tracks2","object_from_template","on_click","DrawableGroup","name","css","self","handle_unsaved_changes","placement","buttonMenu","add_bookmark","editable","bookmarks_container","new_bookmark","addClass","appendTo","position_div","click","go_to","delete_icon_container","prependTo","remove","has_changes","annotation_div","num_rows","help_text","make_text_editable","use_textarea","create_visualization","view_config","viewport_config","drawables_config","bookmarks_config","header","editor","when","load_chroms_deferred","undefined","overview_drawable_name","change_chrom","chrom_info","i","length","drawables","set_overview","bookmark","set_up_router","options","_visualization2","TrackBrowserRouter","history","init_keyboard_nav","document","keyup","e","srcElement","is","which","move_fraction","Math","round","viewport_container","height","scrollTop","buttons","Cancel","Save","then","TracksterView","View","createButtonMenu","$el","attr","append","galaxy_config","force_right_panel","app","id","view_existing","choose_existing_or_new","get","listTracksParams","dataset_id","hda_ldda","gene_region","dataset_params","_queryStringParsing2","View in saved visualization","view_in_saved","tracks_grid","_gridView2","embedded","Add to visualization","parent","find","val","param","view_new","data","init_editor","alert","response","default_dbkey","Create","create_browser","select2","dbkeys_in_genomes","map","r","contains","template_view_new","focus","html","container","add_dataset","GalaxyApp","data_type","dataType","track_data","on"],"mappings":"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","file":"../../scripts/viz/trackster.js","sourcesContent":["/**\n * Top-level trackster code, used for creating/loading visualizations and user interface elements.\n */\n\n// global variables\nvar ui = null;\nvar view = null;\nvar browser_router = null;\n\n// trackster viewer\nimport * as _ from \"libs/underscore\";\nimport tracks from \"viz/trackster/tracks\";\nimport visualization from \"viz/visualization\";\nimport mod_icon_btn from \"mvc/ui/icon-button\";\nimport query_string from \"utils/query-string-parsing\";\nimport GridView from \"mvc/grid/grid-view\";\nimport mod_utils from \"utils/utils\";\nimport \"libs/jquery/jquery.event.drag\";\nimport \"libs/jquery/jquery.event.hover\";\nimport \"libs/jquery/jquery.mousewheel\";\nimport \"libs/jquery/jquery-ui\";\nimport \"libs/jquery/select2\";\nimport \"libs/farbtastic\";\nimport \"libs/jquery/jquery.form\";\nimport \"libs/jquery/jquery.rating\";\nimport \"ui/editable-text\";\n/**\n * Base Object/Model for inhertiance.\n */\nvar Base = function() {\n if (this.initialize) {\n this.initialize.apply(this, arguments);\n }\n};\nBase.extend = Backbone.Model.extend;\n\n/**\n * User interface controls for trackster\n */\nvar TracksterUI = Base.extend({\n initialize: function(baseURL) {\n mod_utils.cssLoadFile(\"static/style/jquery.rating.css\");\n mod_utils.cssLoadFile(\"static/style/autocomplete_tagging.css\");\n mod_utils.cssLoadFile(\"static/style/jquery-ui/smoothness/jquery-ui.css\");\n mod_utils.cssLoadFile(\"static/style/library.css\");\n mod_utils.cssLoadFile(\"static/style/trackster.css\");\n this.baseURL = baseURL;\n },\n\n /**\n * Save visualization, returning a Deferred object for the remote call to save.\n */\n save_viz: function() {\n // show dialog\n Galaxy.modal.show({ title: \"Saving...\", body: \"progress\" });\n\n // Save bookmarks.\n var bookmarks = [];\n $(\".bookmark\").each(function() {\n bookmarks.push({\n position: $(this)\n .children(\".position\")\n .text(),\n annotation: $(this)\n .children(\".annotation\")\n .text()\n });\n });\n\n // FIXME: give unique IDs to Drawables and save overview as ID.\n var overview_track_name = view.overview_drawable ? view.overview_drawable.config.get_value(\"name\") : null;\n\n var viz_config = {\n view: view.to_dict(),\n viewport: {\n chrom: view.chrom,\n start: view.low,\n end: view.high,\n overview: overview_track_name\n },\n bookmarks: bookmarks\n };\n\n // Make call to save visualization.\n return $.ajax({\n url: `${Galaxy.root}visualization/save`,\n type: \"POST\",\n dataType: \"json\",\n data: {\n id: view.vis_id,\n title: view.config.get_value(\"name\"),\n dbkey: view.dbkey,\n type: \"trackster\",\n vis_json: JSON.stringify(viz_config)\n }\n })\n .success(vis_info => {\n Galaxy.modal.hide();\n view.vis_id = vis_info.vis_id;\n view.has_changes = false;\n\n // Needed to set URL when first saving a visualization.\n window.history.pushState({}, \"\", vis_info.url + window.location.hash);\n })\n .error(() => {\n // show dialog\n Galaxy.modal.show({\n title: \"Could Not Save\",\n body: \"Could not save visualization. Please try again later.\",\n buttons: {\n Cancel: function() {\n Galaxy.modal.hide();\n }\n }\n });\n });\n },\n\n /**\n * Create button menu\n */\n createButtonMenu: function() {\n var self = this;\n\n var menu = mod_icon_btn.create_icon_buttons_menu(\n [\n {\n icon_class: \"plus-button\",\n title: \"Add tracks\",\n on_click: function() {\n visualization.select_datasets({ dbkey: view.dbkey }, new_tracks => {\n _.each(new_tracks, track => {\n view.add_drawable(tracks.object_from_template(track, view, view));\n });\n });\n }\n },\n {\n icon_class: \"block--plus\",\n title: \"Add group\",\n on_click: function() {\n view.add_drawable(\n new tracks.DrawableGroup(view, view, {\n name: \"New Group\"\n })\n );\n }\n },\n {\n icon_class: \"bookmarks\",\n title: \"Bookmarks\",\n on_click: function() {\n // HACK -- use style to determine if panel is hidden and hide/show accordingly.\n force_right_panel($(\"div#right\").css(\"right\") == \"0px\" ? \"hide\" : \"show\");\n }\n },\n {\n icon_class: \"globe\",\n title: \"Circster\",\n on_click: function() {\n window.location = `${self.baseURL}visualization/circster?id=${view.vis_id}`;\n }\n },\n {\n icon_class: \"disk--arrow\",\n title: \"Save\",\n on_click: function() {\n self.save_viz();\n }\n },\n {\n icon_class: \"cross-circle\",\n title: \"Close\",\n on_click: function() {\n self.handle_unsaved_changes(view);\n }\n }\n ],\n {\n tooltip_config: { placement: \"bottom\" }\n }\n );\n\n this.buttonMenu = menu;\n return menu;\n },\n\n /**\n * Add bookmark.\n */\n add_bookmark: function(position, annotation, editable) {\n // Create HTML.\n var bookmarks_container = $(\"#right .unified-panel-body\");\n\n var new_bookmark = $(\"
\")\n .addClass(\"bookmark\")\n .appendTo(bookmarks_container);\n\n var position_div = $(\"
\")\n .addClass(\"position\")\n .appendTo(new_bookmark);\n\n var position_link = $(\"\")\n .text(position)\n .appendTo(position_div)\n .click(() => {\n view.go_to(position);\n return false;\n });\n\n var annotation_div = $(\"
\")\n .text(annotation)\n .appendTo(new_bookmark);\n\n // If editable, enable bookmark deletion and annotation editing.\n if (editable) {\n var delete_icon_container = $(\"
\")\n .addClass(\"delete-icon-container\")\n .prependTo(new_bookmark)\n .click(() => {\n // Remove bookmark.\n new_bookmark.slideUp(\"fast\");\n new_bookmark.remove();\n view.has_changes = true;\n return false;\n });\n\n var delete_icon = $(\"\")\n .addClass(\"icon-button delete\")\n .appendTo(delete_icon_container);\n\n annotation_div\n .make_text_editable({\n num_rows: 3,\n use_textarea: true,\n help_text: \"Edit bookmark note\"\n })\n .addClass(\"annotation\");\n }\n\n view.has_changes = true;\n return new_bookmark;\n },\n\n /**\n * Create a complete Trackster visualization. Returns view.\n */\n create_visualization: function(view_config, viewport_config, drawables_config, bookmarks_config, editable) {\n // Create view.\n var self = this;\n\n var view = new tracks.TracksterView(_.extend(view_config, { header: false }));\n\n view.editor = true;\n $.when(view.load_chroms_deferred).then(chrom_info => {\n // Viewport config.\n if (viewport_config) {\n var chrom = viewport_config.chrom;\n var start = viewport_config.start;\n var end = viewport_config.end;\n var overview_drawable_name = viewport_config.overview;\n\n if (chrom && start !== undefined && end) {\n view.change_chrom(chrom, start, end);\n } else {\n // No valid viewport, so use first chromosome.\n view.change_chrom(chrom_info[0].chrom);\n }\n } else {\n // No viewport, so use first chromosome.\n view.change_chrom(chrom_info[0].chrom);\n }\n\n // Add drawables to view.\n if (drawables_config) {\n // FIXME: can from_dict() be used to create view and add drawables?\n var drawable_config;\n\n var drawable_type;\n var drawable;\n for (var i = 0; i < drawables_config.length; i++) {\n view.add_drawable(tracks.object_from_template(drawables_config[i], view, view));\n }\n }\n\n // Set overview.\n var overview_drawable;\n for (var i = 0; i < view.drawables.length; i++) {\n if (view.drawables[i].config.get_value(\"name\") === overview_drawable_name) {\n view.set_overview(view.drawables[i]);\n break;\n }\n }\n\n // Load bookmarks.\n if (bookmarks_config) {\n var bookmark;\n for (var i = 0; i < bookmarks_config.length; i++) {\n bookmark = bookmarks_config[i];\n self.add_bookmark(bookmark[\"position\"], bookmark[\"annotation\"], editable);\n }\n }\n\n // View has no changes as of yet.\n view.has_changes = false;\n });\n\n // Final initialization.\n this.set_up_router({ view: view });\n\n return view;\n },\n\n /**\n * Set up location router to use hashes as track browser locations.\n */\n set_up_router: function(options) {\n new visualization.TrackBrowserRouter(options);\n Backbone.history.start();\n },\n\n /**\n * Set up keyboard navigation for a visualization.\n */\n init_keyboard_nav: function(view) {\n // Keyboard navigation. Scroll ~7% of height when scrolling up/down.\n $(document).keyup(e => {\n // Do not navigate if arrow keys used in input element.\n if ($(e.srcElement).is(\":input\")) {\n return;\n }\n\n // Key codes: left == 37, up == 38, right == 39, down == 40\n switch (e.which) {\n case 37:\n view.move_fraction(0.25);\n break;\n case 38:\n var change = Math.round(view.viewport_container.height() / 15.0);\n view.viewport_container.scrollTop(view.viewport_container.scrollTop() - 20);\n break;\n case 39:\n view.move_fraction(-0.25);\n break;\n case 40:\n var change = Math.round(view.viewport_container.height() / 15.0);\n view.viewport_container.scrollTop(view.viewport_container.scrollTop() + 20);\n break;\n }\n });\n },\n\n /**\n * Handle unsaved changes in visualization.\n */\n handle_unsaved_changes: function(view) {\n if (view.has_changes) {\n var self = this;\n Galaxy.modal.show({\n title: \"Close visualization\",\n body: \"There are unsaved changes to your visualization which will be lost if you do not save them.\",\n buttons: {\n Cancel: function() {\n Galaxy.modal.hide();\n },\n \"Leave without Saving\": function() {\n $(window).off(\"beforeunload\");\n window.location = `${Galaxy.root}visualization`;\n },\n Save: function() {\n $.when(self.save_viz()).then(() => {\n window.location = `${Galaxy.root}visualization`;\n });\n }\n }\n });\n } else {\n window.location = `${Galaxy.root}visualization`;\n }\n }\n});\n\nvar TracksterView = Backbone.View.extend({\n // initalize trackster\n initialize: function() {\n // load ui\n ui = new TracksterUI(Galaxy.root);\n\n // create button menu\n ui.createButtonMenu();\n\n // attach the button menu to the panel header and float it left\n ui.buttonMenu.$el.attr(\"style\", \"float: right\");\n\n // add to center panel\n $(\"#center .unified-panel-header-inner\").append(ui.buttonMenu.$el);\n\n // configure right panel\n $(\"#right .unified-panel-title\").append(\"Bookmarks\");\n $(\"#right .unified-panel-icons\").append(\n \"\"\n );\n\n // resize view when showing/hiding right panel (bookmarks for now).\n $(\"#right-border\").click(() => {\n view.resize_window();\n });\n\n // hide right panel\n force_right_panel(\"hide\");\n\n // check if id is available\n if (galaxy_config.app.id) {\n this.view_existing();\n } else if (query_string.get(\"dataset_id\")) {\n this.choose_existing_or_new();\n } else {\n this.view_new();\n }\n },\n\n choose_existing_or_new: function() {\n var self = this;\n var dbkey = query_string.get(\"dbkey\");\n var listTracksParams = {};\n\n var dataset_params = {\n dbkey: dbkey,\n dataset_id: query_string.get(\"dataset_id\"),\n hda_ldda: query_string.get(\"hda_ldda\"),\n gene_region: query_string.get(\"gene_region\")\n };\n\n if (dbkey) {\n listTracksParams[\"f-dbkey\"] = dbkey;\n }\n\n Galaxy.modal.show({\n title: \"View Data in a New or Saved Visualization?\",\n // either have text in here or have to remove body and the header/footer margins\n body: `

    You can add this dataset as:
  • a new track to one of your existing, saved Trackster sessions if they share the genome build: ${dbkey ||\n \"Not available.\"}
  • or create a new session with this dataset as the only track

`,\n buttons: {\n Cancel: function() {\n window.location = `${Galaxy.root}visualizations/list`;\n },\n \"View in saved visualization\": function() {\n self.view_in_saved(dataset_params);\n },\n \"View in new visualization\": function() {\n self.view_new();\n }\n }\n });\n },\n\n // view\n view_in_saved: function(dataset_params) {\n var tracks_grid = new GridView({\n url_base: `${Galaxy.root}visualization/list_tracks`,\n dict_format: true,\n embedded: true\n });\n Galaxy.modal.show({\n title: \"Add Data to Saved Visualization\",\n body: tracks_grid.$el,\n buttons: {\n Cancel: function() {\n window.location = `${Galaxy.root}visualizations/list`;\n },\n \"Add to visualization\": function() {\n $(parent.document)\n .find(\"input[name=id]:checked\")\n .each(function() {\n dataset_params.id = $(this).val();\n window.location = `${Galaxy.root}visualization/trackster?${$.param(dataset_params)}`;\n });\n }\n }\n });\n },\n\n // view\n view_existing: function() {\n // get config\n var viz_config = galaxy_config.app.viz_config;\n\n // view\n view = ui.create_visualization(\n {\n container: $(\"#center .unified-panel-body\"),\n name: viz_config.title,\n vis_id: viz_config.vis_id,\n dbkey: viz_config.dbkey\n },\n viz_config.viewport,\n viz_config.tracks,\n viz_config.bookmarks,\n true\n );\n\n // initialize editor\n this.init_editor();\n },\n\n // view\n view_new: function() {\n // reference this\n var self = this;\n\n // ajax\n $.ajax({\n url: `${Galaxy.root}api/genomes?chrom_info=True`,\n data: {},\n error: function() {\n alert(\"Couldn't create new browser.\");\n },\n success: function(response) {\n // show dialog\n Galaxy.modal.show({\n title: \"New Visualization\",\n body: self.template_view_new(response),\n buttons: {\n Cancel: function() {\n window.location = `${Galaxy.root}visualizations/list`;\n },\n Create: function() {\n self.create_browser($(\"#new-title\").val(), $(\"#new-dbkey\").val());\n Galaxy.modal.hide();\n }\n }\n });\n\n // select default\n var dbkeys_in_genomes = response.map(r => r[1]);\n if (galaxy_config.app.default_dbkey && _.contains(dbkeys_in_genomes, galaxy_config.app.default_dbkey)) {\n $(\"#new-dbkey\").val(galaxy_config.app.default_dbkey);\n }\n\n // change focus\n $(\"#new-title\").focus();\n $(\"select[name='dbkey']\").select2();\n\n // to support the large number of options for dbkey, enable scrolling in overlay.\n $(\"#overlay\").css(\"overflow\", \"auto\");\n }\n });\n },\n\n // new browser form\n template_view_new: function(response) {\n // start template\n var html =\n '
' +\n '
' +\n '' +\n '
' +\n '' +\n \"
\" +\n '
' +\n \"
\" +\n '
' +\n '' +\n '
' +\n '
Is the build not listed here? Add a Custom Build
`;\n\n // return\n return html;\n },\n\n // create\n create_browser: function(name, dbkey) {\n $(document).trigger(\"convert_to_values\");\n\n view = ui.create_visualization(\n {\n container: $(\"#center .unified-panel-body\"),\n name: name,\n dbkey: dbkey\n },\n galaxy_config.app.gene_region\n );\n\n // initialize editor\n this.init_editor();\n\n // modify view setting\n view.editor = true;\n },\n\n // initialization for editor-specific functions.\n init_editor: function() {\n // set title\n $(\"#center .unified-panel-title\").text(`${view.config.get_value(\"name\")} (${view.dbkey})`);\n\n // add dataset\n if (galaxy_config.app.add_dataset)\n $.ajax({\n url: `${Galaxy.root}api/datasets/${galaxy_config.app.add_dataset}`,\n data: { hda_ldda: \"hda\", data_type: \"track_config\" },\n dataType: \"json\",\n success: function(track_data) {\n view.add_drawable(tracks.object_from_template(track_data, view, view));\n }\n });\n\n // initialize icons\n $(\"#add-bookmark-button\").click(() => {\n // add new bookmark.\n var position = `${view.chrom}:${view.low}-${view.high}`;\n\n var annotation = \"Bookmark description\";\n return ui.add_bookmark(position, annotation, true);\n });\n\n // initialize keyboard\n ui.init_keyboard_nav(view);\n\n $(window).on(\"beforeunload\", () => {\n if (view.has_changes) {\n return \"There are unsaved changes to your visualization that will be lost if you leave this page.\";\n }\n });\n }\n});\n\nexport default {\n TracksterUI: TracksterUI,\n GalaxyApp: TracksterView\n};\n"]} \ No newline at end of file diff --git a/static/scripts/bundled/libs.bundled.js b/static/scripts/bundled/libs.bundled.js index 5a21b6b1472..4879b30d6a4 100644 --- a/static/scripts/bundled/libs.bundled.js +++ b/static/scripts/bundled/libs.bundled.js @@ -48,5 +48,5 @@ return s&&(r.length<4&&n("jQuery.fn.attr( props, pass ) is deprecated"),e&&!u.te * @license MIT | GPL | Apache 2.0, see LICENSE.txt * @see https://github.com/dyve/jquery-autocomplete */ -!function(t){"use strict";t.fn.autocomplete_verheul=function(e){var i;arguments.length>1?(i=e,e=arguments[1],e.url=i):"string"==typeof e&&(i=e,e={url:i});var n=t.extend({},t.fn.autocomplete_verheul.defaults,e);return this.each(function(){var e=t(this);e.data("autocompleter",new t.Autocompleter(e,t.meta?t.extend({},n,e.data()):n))})},t.fn.autocomplete_verheul.defaults={inputClass:"acInput",loadingClass:"acLoading",resultsClass:"acResults",selectClass:"acSelect",queryParamName:"q",extraParams:{},remoteDataType:!1,lineSeparator:"\n",cellSeparator:"|",minChars:2,maxItemsToShow:10,delay:400,useCache:!0,maxCacheLength:10,matchSubset:!0,matchCase:!1,matchInside:!0,mustMatch:!1,selectFirst:!1,selectOnly:!1,showResult:null,preventDefaultReturn:1,preventDefaultTab:0,autoFill:!1,filterResults:!0,filter:!0,sortResults:!0,sortFunction:null,onItemSelect:null,onNoMatch:null,onFinish:null,matchStringConverter:null,beforeUseConverter:null,autoWidth:"min-width",useDelimiter:!1,delimiterChar:",",delimiterKeyCode:188,processData:null,onError:null,enabled:!0};var e=function(e){var i,n,a=typeof e;return"string"===a?(i=e,n={}):t.isArray(e)?(i=e[0],n=e.slice(1)):"object"===a&&(i=e.value,n=e.data),i=String(i),"object"!=typeof n&&(n={}),{value:i,data:n}},i=function(t,e,i){var n=parseInt(t,10);return i=i||{},(isNaN(n)||i.min&&ne?1:t
").hide().addClass(this.options.resultsClass).css({position:"absolute"}),t("body").append(this.dom.$results),e.keydown(function(t){switch(a.lastKeyPressed_=t.keyCode,a.lastKeyPressed_){case a.options.delimiterKeyCode:a.options.useDelimiter&&a.active_&&a.selectCurrent();break;case 35:case 36:case 16:case 17:case 18:case 37:case 39:break;case 38:return t.preventDefault(),a.active_?a.focusPrev():a.activate(),!1;case 40:return t.preventDefault(),a.active_?a.focusNext():a.activate(),!1;case 9:if(a.active_&&(a.selectCurrent(),a.options.preventDefaultTab))return t.preventDefault(),!1;if(2===a.options.preventDefaultTab)return t.preventDefault(),!1;break;case 13:if(a.active_&&(a.selectCurrent(),a.options.preventDefaultReturn))return t.preventDefault(),!1;if(2===a.options.preventDefaultReturn)return t.preventDefault(),!1;break;case 27:if(a.active_)return t.preventDefault(),a.deactivate(!0),!1;break;default:a.activate()}}),e.on("paste",function(){a.activate()});var s=function(){a.deactivate(!0)};e.blur(function(){a.finishOnBlur_&&(a.finishTimeout_=setTimeout(s,200))}),e.parents("form").on("submit",s)},t.Autocompleter.prototype.position=function(){var e=this.dom.$elem.offset(),i=this.dom.$results.outerHeight(),n=t(window).outerHeight(),a=e.top+this.dom.$elem.outerHeight(),s=a+i,o={top:a,left:e.left};if(s>n){var r=e.top-i;r>=0&&(o.top=r)}this.dom.$results.css(o)},t.Autocompleter.prototype.cacheRead=function(t){var e,i,n,a,s;if(this.options.useCache)for(t=String(t),e=t.length,i=this.options.matchSubset?1:e;i<=e;){for(a=this.options.matchInside?e-i:0,s=0;s<=a;){if(n=t.substr(0,i),void 0!==this.cacheData_[n])return this.cacheData_[n];s++}i++}return!1},t.Autocompleter.prototype.cacheWrite=function(t,e){return!!this.options.useCache&&(this.cacheLength_>=this.options.maxCacheLength&&this.cacheFlush(),t=String(t),void 0!==this.cacheData_[t]&&this.cacheLength_++,this.cacheData_[t]=e,this.cacheData_[t])},t.Autocompleter.prototype.cacheFlush=function(){this.cacheData_={},this.cacheLength_=0},t.Autocompleter.prototype.callHook=function(e,i){var n=this.options[e];return!(!n||!t.isFunction(n))&&n(i,this)},t.Autocompleter.prototype.activate=function(){if(this.options.enabled){var t=this;this.keyTimeout_&&clearTimeout(this.keyTimeout_),this.keyTimeout_=setTimeout(function(){t.activateNow()},this.options.delay)}},t.Autocompleter.prototype.activateNow=function(){var t=this.beforeUseConverter(this.dom.$elem.val());t!==this.lastProcessedValue_&&t!==this.lastSelectedValue_&&this.fetchData(t)},t.Autocompleter.prototype.fetchData=function(t){var e=this,i=function(t,i){e.options.processData&&(t=e.options.processData(t)),e.showResults(e.filterResults(t,i),i)};this.lastProcessedValue_=t,t.length-1:0===a}return!0},t.Autocompleter.prototype.filterResult=function(e,i){return!1===this.options.filter||(t.isFunction(this.options.filter)?this.options.filter(e,i):this.defaultFilter(e,i))},t.Autocompleter.prototype.filterResults=function(t,i){var n,a,s=[];for(n=0;n0&&this.options.maxItemsToShow");return n.html(this.showResult(e.value,e.data)),n.data({value:e.value,data:e.data}).click(function(){i.selectItem(n)}).mousedown(i.disableFinishOnBlur).mouseup(i.enableFinishOnBlur),n},t.Autocompleter.prototype.getItems=function(){return t(">ul>li",this.dom.$results)},t.Autocompleter.prototype.showResults=function(e,i){var n,a,s,o,r=e.length,l=this,h=t("
    "),c=!1,u=!1;if(r){for(n=0;n

    ").text(e).html()},t.Autocompleter.prototype.autoFill=function(t,e){var i,n,a,s;if(this.options.autoFill&&8!==this.lastKeyPressed_&&(i=String(t).toLowerCase(),n=String(e).toLowerCase(),a=t.length,s=e.length,i.substr(0,s)===n)){var o=this.getDelimiterOffsets(),r=o.start?" ":"";this.setValue(r+t);var l=s+o.start+r.length,h=a+o.start+r.length;return this.selectRange(l,h),!0}return!1},t.Autocompleter.prototype.focusNext=function(){this.focusMove(1)},t.Autocompleter.prototype.focusPrev=function(){this.focusMove(-1)},t.Autocompleter.prototype.focusMove=function(e){var n=this.getItems();if(e=i(e,0))for(var a=0;a=n.length&&(e=n.length-1),i=t(n[e])):i=t(e),i&&i.addClass(this.selectClass_).addClass(this.options.selectClass))},t.Autocompleter.prototype.selectCurrent=function(){var e=t("li."+this.selectClass_,this.dom.$results);1===e.length?this.selectItem(e):this.deactivate(!1)},t.Autocompleter.prototype.selectItem=function(t){var e=t.data("value"),i=t.data("data"),n=this.displayValue(e,i),a=this.beforeUseConverter(n);this.lastProcessedValue_=a,this.lastSelectedValue_=a;var s=this.getDelimiterOffsets(),o=this.options.delimiterChar,r=this.dom.$elem,l=0;this.options.useDelimiter&&(r.val().substring(s.start-1,s.start)==o&&" "!=o&&(n=" "+n),r.val().substring(s.end,s.end+1)!=o&&this.lastKeyPressed_!=this.options.delimiterKeyCode?n+=o:l=1),this.setValue(n),this.setCaret(s.start+n.length+l),this.callHook("onItemSelect",{value:e,data:i}),this.deactivate(!0),r.focus()},t.Autocompleter.prototype.displayValue=function(e,i){return t.isFunction(this.options.displayValue)?this.options.displayValue(e,i):e},t.Autocompleter.prototype.hideResults=function(){this.dom.$results.hide()},t.Autocompleter.prototype.deactivate=function(t){this.finishTimeout_&&clearTimeout(this.finishTimeout_),this.keyTimeout_&&clearTimeout(this.keyTimeout_),t&&(this.lastProcessedValue_!==this.lastSelectedValue_&&(this.options.mustMatch&&this.setValue(""),this.callHook("onNoMatch")),this.active_&&this.callHook("onFinish"),this.lastKeyPressed_=null,this.lastProcessedValue_=null,this.lastSelectedValue_=null,this.active_=!1),this.hideResults()},t.Autocompleter.prototype.selectRange=function(t,e){var i=this.dom.$elem.get(0);if(i.setSelectionRange)i.focus(),i.setSelectionRange(t,e);else if(i.createTextRange){var n=i.createTextRange();n.collapse(!0),n.moveEnd("character",e),n.moveStart("character",t),n.select()}},t.Autocompleter.prototype.setCaret=function(t){this.selectRange(t,t)},t.Autocompleter.prototype.getCaret=function(){var t,e,i,n,a,s,o=this.dom.$elem,r=o[0];return r.createTextRange?(e=document.selection,"textarea"!=r.tagName.toLowerCase()?(t=o.val(),i=e.createRange().duplicate(),i.moveEnd("character",t.length),n=""===i.text?t.length:t.lastIndexOf(i.text),i=e.createRange().duplicate(),i.moveStart("character",-t.length),a=i.text.length):(i=e.createRange(),s=i.duplicate(),s.moveToElementText(r),s.setEndPoint("EndToEnd",i),n=s.text.length-i.text.length,a=n+i.text.length)):(n=o[0].selectionStart,a=o[0].selectionEnd),{start:n,end:a}},t.Autocompleter.prototype.setValue=function(t){if(this.options.useDelimiter){var e=this.dom.$elem.val(),i=this.getDelimiterOffsets();t=e.substring(0,i.start)+t+e.substring(i.end)}this.dom.$elem.val(t)},t.Autocompleter.prototype.getValue=function(t){if(this.options.useDelimiter){var e=this.getDelimiterOffsets();return t.substring(e.start,e.end).trim()}return t},t.Autocompleter.prototype.getDelimiterOffsets=function(){var t=this.dom.$elem.val();if(this.options.useDelimiter){var e=t.substring(0,this.getCaret().start),i=e.lastIndexOf(this.options.delimiterChar)+1,n=t.substring(this.getCaret().start),a=n.indexOf(this.options.delimiterChar);-1==a&&(a=t.length),a+=this.getCaret().start}else i=0,a=t.length;return{start:i,end:a}}}(t)}).call(e,i(0))},function(t,e,i){var n,a,s;!function(o,r,l){!function(o){a=[i(0)],n=o,void 0!==(s="function"==typeof n?n.apply(e,a):n)&&(t.exports=s)}(function(t){"use strict";var e,i,n,a,s,l,h,c,u,d,f,p,g,m,v,_,b,y,w,x,k,C,S,T,E,A,M,O,R,$,D,P={},j=0;e=function(){return{common:{type:"line",lineColor:"#00f",fillColor:"#cdf",defaultPixelsPerValue:3,width:"auto",height:"auto",composite:!1,tagValuesAttribute:"values",tagOptionsPrefix:"spark",enableTagOptions:!1,enableHighlight:!0,highlightLighten:1.4,tooltipSkipNull:!0,tooltipPrefix:"",tooltipSuffix:"",disableHiddenCheck:!1,numberFormatter:!1,numberDigitGroupCount:3,numberDigitGroupSep:",",numberDecimalMark:".",disableTooltips:!1,disableInteraction:!1},line:{spotColor:"#f80",highlightSpotColor:"#5f5",highlightLineColor:"#f22",spotRadius:1.5,minSpotColor:"#f80",maxSpotColor:"#f80",lineWidth:1,normalRangeMin:void 0,normalRangeMax:void 0,normalRangeColor:"#ccc",drawNormalOnTop:!1,chartRangeMin:void 0,chartRangeMax:void 0,chartRangeMinX:void 0,chartRangeMaxX:void 0,tooltipFormat:new n('● {{prefix}}{{y}}{{suffix}}')},bar:{barColor:"#3366cc",negBarColor:"#f44",stackedBarColor:["#3366cc","#dc3912","#ff9900","#109618","#66aa00","#dd4477","#0099c6","#990099"],zeroColor:void 0,nullColor:void 0,zeroAxis:!0,barWidth:4,barSpacing:1,chartRangeMax:void 0,chartRangeMin:void 0,chartRangeClip:!1,colorMap:void 0,tooltipFormat:new n('● {{prefix}}{{value}}{{suffix}}')},tristate:{barWidth:4,barSpacing:1,posBarColor:"#6f6",negBarColor:"#f44",zeroBarColor:"#999",colorMap:{},tooltipFormat:new n('● {{value:map}}'),tooltipValueLookups:{map:{"-1":"Loss",0:"Draw",1:"Win"}}},discrete:{lineHeight:"auto",thresholdColor:void 0,thresholdValue:0,chartRangeMax:void 0,chartRangeMin:void 0,chartRangeClip:!1,tooltipFormat:new n("{{prefix}}{{value}}{{suffix}}")},bullet:{targetColor:"#f33",targetWidth:3,performanceColor:"#33f",rangeColors:["#d3dafe","#a8b6ff","#7f94ff"],base:void 0,tooltipFormat:new n("{{fieldkey:fields}} - {{value}}"),tooltipValueLookups:{fields:{r:"Range",p:"Performance",t:"Target"}}},pie:{offset:0,sliceColors:["#3366cc","#dc3912","#ff9900","#109618","#66aa00","#dd4477","#0099c6","#990099"],borderWidth:0,borderColor:"#000",tooltipFormat:new n('● {{value}} ({{percent.1}}%)')},box:{raw:!1,boxLineColor:"#000",boxFillColor:"#cdf",whiskerColor:"#000",outlierLineColor:"#333",outlierFillColor:"#fff",medianColor:"#f00",showOutliers:!0,outlierIQR:1.5,spotRadius:1.5,target:void 0,targetColor:"#4a2",chartRangeMax:void 0,chartRangeMin:void 0,tooltipFormat:new n("{{field:fields}}: {{value}}"),tooltipFormatFieldlistKey:"field",tooltipValueLookups:{fields:{lq:"Lower Quartile",med:"Median",uq:"Upper Quartile",lo:"Left Outlier",ro:"Right Outlier",lw:"Left Whisker",rw:"Right Whisker"}}}}},E='.jqstooltip { position: absolute;left: 0px;top: 0px;visibility: hidden;background: rgb(0, 0, 0) transparent;background-color: rgba(0,0,0,0.6);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)";color: white;font: 10px arial, san serif;text-align: left;white-space: nowrap;padding: 5px;border: 1px solid white;z-index: 10000;}.jqsfield { color: white;font: 10px arial, san serif;text-align: left;}',i=function(){var e,i;return e=function(){this.init.apply(this,arguments)},arguments.length>1?(arguments[0]?(e.prototype=t.extend(new arguments[0],arguments[arguments.length-1]),e._super=arguments[0].prototype):e.prototype=arguments[arguments.length-1],arguments.length>2&&(i=Array.prototype.slice.call(arguments,1,-1),i.unshift(e.prototype),t.extend.apply(t,i))):e.prototype=arguments[0],e.prototype.cls=e,e},t.SPFormatClass=n=i({fre:/\{\{([\w.]+?)(:(.+?))?\}\}/g,precre:/(\w+)\.(\d+)/,init:function(t,e){this.format=t,this.fclass=e},render:function(t,e,i){var n,a,s,o,r,l=this,h=t;return this.format.replace(this.fre,function(){var t;return a=arguments[1],s=arguments[3],n=l.precre.exec(a),n?(r=n[2],a=n[1]):r=!1,void 0===(o=h[a])?"":s&&e&&e[s]?(t=e[s],t.get?e[s].get(o)||o:e[s][o]||o):(u(o)&&(o=i.get("numberFormatter")?i.get("numberFormatter")(o):g(o,r,i.get("numberDigitGroupCount"),i.get("numberDigitGroupSep"),i.get("numberDecimalMark"))),o)})}}),t.spformat=function(t,e){return new n(t,e)},a=function(t,e,i){return ti?i:t},s=function(t,e){var i;return 2===e?(i=r.floor(t.length/2),t.length%2?t[i]:(t[i-1]+t[i])/2):t.length%2?(i=(t.length*e+e)/4,i%1?(t[r.floor(i)]+t[r.floor(i)-1])/2:t[i-1]):(i=(t.length*e+2)/4,i%1?(t[r.floor(i)]+t[r.floor(i)-1])/2:t[i-1])},l=function(t){var e;switch(t){case"undefined":t=void 0;break;case"null":t=null;break;case"true":t=!0;break;case"false":t=!1;break;default:e=parseFloat(t),t==e&&(t=e)}return t},h=function(t){var e,i=[];for(e=t.length;e--;)i[e]=l(t[e]);return i},c=function(t,e){var i,n,a=[];for(i=0,n=t.length;i0;r-=n)e.splice(r,0,a);return e.join("")},d=function(t,e,i){var n;for(n=e.length;n--;)if((!i||null!==e[n])&&e[n]!==t)return!1;return!0},p=function(e){return t.isArray(e)?e:[e]},f=function(t){var e;o.createStyleSheet?o.createStyleSheet().cssText=t:(e=o.createElement("style"),e.type="text/css",o.getElementsByTagName("head")[0].appendChild(e),e["string"==typeof o.body.style.WebkitAppearance?"innerText":"innerHTML"]=t)},t.fn.simpledraw=function(e,i,n,a){var s,r;if(n&&(s=this.data("_jqs_vcanvas")))return s;if(!1===t.fn.sparkline.canvas)return!1;if(void 0===t.fn.sparkline.canvas){var l=o.createElement("canvas");if(l.getContext&&l.getContext("2d"))t.fn.sparkline.canvas=function(t,e,i,n){return new R(t,e,i,n)};else{if(!o.namespaces||o.namespaces.v)return t.fn.sparkline.canvas=!1,!1;o.namespaces.add("v","urn:schemas-microsoft-com:vml","#default#VML"),t.fn.sparkline.canvas=function(t,e,i,n){return new $(t,e,i)}}}return void 0===e&&(e=t(this).innerWidth()),void 0===i&&(i=t(this).innerHeight()),s=t.fn.sparkline.canvas(e,i,this,a),r=t(this).data("_jqs_mhandler"),r&&r.registerCanvas(s),s},t.fn.cleardraw=function(){var t=this.data("_jqs_vcanvas");t&&t.reset()},t.RangeMapClass=m=i({init:function(t){var e,i,n=[];for(e in t)t.hasOwnProperty(e)&&"string"==typeof e&&e.indexOf(":")>-1&&(i=e.split(":"),i[0]=0===i[0].length?-1/0:parseFloat(i[0]),i[1]=0===i[1].length?1/0:parseFloat(i[1]),i[2]=t[e],n.push(i));this.map=t,this.rangelist=n||!1},get:function(t){var e,i,n,a=this.rangelist;if(void 0!==(n=this.map[t]))return n;if(a)for(e=a.length;e--;)if(i=a[e],i[0]<=t&&i[1]>=t)return i[2]}}),t.range_map=function(t){return new m(t)},v=i({init:function(e,i){var n=t(e);this.$el=n,this.options=i,this.currentPageX=0,this.currentPageY=0,this.el=e,this.splist=[],this.tooltip=null,this.over=!1,this.displayTooltips=!i.get("disableTooltips"),this.highlightEnabled=!i.get("disableHighlight")},registerSparkline:function(t){this.splist.push(t),this.over&&this.updateDisplay()},registerCanvas:function(e){var i=t(e.canvas);this.canvas=e,this.$canvas=i,i.mouseenter(t.proxy(this.mouseenter,this)),i.mouseleave(t.proxy(this.mouseleave,this)),i.click(t.proxy(this.mouseclick,this))},reset:function(t){this.splist=[],this.tooltip&&t&&(this.tooltip.remove(),this.tooltip=void 0)},mouseclick:function(e){var i=t.Event("sparklineClick");i.originalEvent=e,i.sparklines=this.splist,this.$el.trigger(i)},mouseenter:function(e){t(o.body).unbind("mousemove.jqs"),t(o.body).bind("mousemove.jqs",t.proxy(this.mousemove,this)),this.over=!0,this.currentPageX=e.pageX,this.currentPageY=e.pageY,this.currentEl=e.target,!this.tooltip&&this.displayTooltips&&(this.tooltip=new _(this.options),this.tooltip.updatePosition(e.pageX,e.pageY)),this.updateDisplay()},mouseleave:function(){t(o.body).unbind("mousemove.jqs");var e,i,n=this.splist,a=n.length,s=!1;for(this.over=!1,this.currentEl=null,this.tooltip&&(this.tooltip.remove(),this.tooltip=null),i=0;i
    '}),e.prototype=t.extend({},t.fn.tooltip.Constructor.prototype),e.prototype.constructor=e,e.prototype.getDefaults=function(){return e.DEFAULTS},e.prototype.setContent=function(){var t=this.tip(),e=this.getTitle(),i=this.getContent();t.find(".popover-title")[this.options.html?"html":"text"](e),t.find(".popover-content")[this.options.html?"html":"text"](i),t.removeClass("fade top bottom left right in"),t.find(".popover-title").html()||t.find(".popover-title").hide()},e.prototype.hasContent=function(){return this.getTitle()||this.getContent()},e.prototype.getContent=function(){var t=this.$element,e=this.options;return t.attr("data-content")||("function"==typeof e.content?e.content.call(t[0]):e.content)},e.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},e.prototype.tip=function(){return this.$tip||(this.$tip=t(this.options.template)),this.$tip};var i=t.fn.popover;t.fn.popover=function(i){return this.each(function(){var n=t(this),a=n.data("bs.popover"),s="object"==typeof i&&i;a||n.data("bs.popover",a=new e(this,s)),"string"==typeof i&&a[i]()})},t.fn.popover.Constructor=e,t.fn.popover.noConflict=function(){return t.fn.popover=i,this}}(e)}).call(e,i(0),i(0))},function(t,e){var i;i=function(){return this}();try{i=i||Function("return this")()||(0,eval)("this")}catch(t){"object"==typeof window&&(i=window)}t.exports=i},function(t,e){t.exports=function(){throw new Error("define cannot be used indirect")}},function(t,e,i){"use strict";(function(t,e,n,a,s){function o(t){return t&&t.__esModule?t:{default:t}}function r(e,i,n){function a(t){var e=s(t),i={placeholder:"Click to select",closeOnSelect:!e.is("[MULTIPLE]"),dropdownAutoWidth:!0,containerCssClass:"select2-minwidth"};return t.select2(i)}t.fn.select2&&(void 0===e&&(e=20),void 0===i&&(i=3e3),n=n||s("select"),n.each(function(){var t=s(this).not("[multiple]"),n=t.find("option").length;ni||t.hasClass("no-autocomplete")||a(t)}))}function l(){s("select[refresh_on_change='true']").off("change").change(function(){var t=s(this),e=t.val(),i=t.attr("refresh_on_change_values");if(i){i=i.split(",");var n=t.attr("last_selected_value");if(-1===s.inArray(e,i)&&-1===s.inArray(n,i))return}s(window).trigger("refresh_on_change"),s(document).trigger("convert_to_values"),t.get(0).form.submit()}),s(":checkbox[refresh_on_change='true']").off("click").click(function(){var t=s(this),e=t.val(),i=t.attr("refresh_on_change_values");if(i){i=i.split(",");var n=t.attr("last_selected_value");if(-1===s.inArray(e,i)&&-1===s.inArray(n,i))return}s(window).trigger("refresh_on_change"),t.get(0).form.submit()}),s("a[confirm]").off("click").click(function(){return confirm(s(this).attr("confirm"))})}var h=i(23),c=o(h),u=i(56),d=o(u),f=i(100),p=o(f),g=i(101),m=o(g),v=i(55),_=o(v),b=i(57),y=o(b),w=i(8);o(w);window.$=t,window._=n,window.Backbone=a,window.panels=c.default,n.extend(window,d.default),window.async_save_text=p.default,window.make_popupmenu=m.default.make_popupmenu,window.make_popup_menus=m.default.make_popup_menus,window.init_tag_click_function=_.default,window.init_refresh_on_change=l,s(document).ready(function(){function t(){void 0!==Galaxy.root?s.getJSON(Galaxy.root+"api/webhooks/onload/all",function(t){n.each(t,function(t){t.activate&&t.script&&(s("