trackster:

- Can save configs
- Make track configs look like history items instead of tool configs
- Small performance tweaks
- Implemented "Add Track" grid (doesn't actually add track yet)

Grids:
- Lowercase when sorting so that we sort strings case-independent
- Can click on text to toggle appropriate checkbox
This commit is contained in:
Kanwei Li
2010-01-29 17:10:34 -05:00
parent 33068ed973
commit cba2c2220c
11 changed files with 246 additions and 110 deletions
+3 -3
View File
@@ -7,13 +7,14 @@ import pkg_resources; pkg_resources.require( "pysam" )
from pysam import csamtools
from math import floor, ceil, log
import logging
# log = logging.getLogger(__name__)
class BamDataProvider( object ):
"""
Provides access to intervals from a sorted indexed BAM file.
"""
def __init__( self, index, original_dataset ):
# self.log = logging.getLogger(__name__)
self.index = index
self.original_dataset = original_dataset
@@ -27,8 +28,7 @@ class BamDataProvider( object ):
try:
data = bamfile.fetch(start=start, end=end, reference=chrom)
except ValueError, e:
# Some BAM files do not prefix chromosome names with chr, try
# without
# Some BAM files do not prefix chromosome names with chr, try without
if chrom.startswith( 'chr' ):
data = bamfile.fetch( start=start, end=end, reference=chrom[3:] )
else:
+76 -8
View File
@@ -19,6 +19,7 @@ log = logging.getLogger(__name__)
from galaxy.util.json import to_json_string
from galaxy.web.base.controller import *
from galaxy.web.framework import simplejson
from galaxy.web.framework.helpers import time_ago, grids
from galaxy.util.bunch import Bunch
from galaxy.visualization.tracks.data.array_tree import ArrayTreeDataProvider
@@ -43,12 +44,40 @@ dataset_type_to_data_provider = {
"bai": BamDataProvider
}
class DatasetSelectionGrid( grids.Grid ):
# Grid definition.
available_tracks = None
title = "Add Tracks"
template = "/tracks/add_tracks.mako"
async_template = "/page/select_histories_grid_async.mako"
model_class = model.HistoryDatasetAssociation
default_filter = { "deleted" : "False" , "shared" : "All" }
default_sort_key = "name"
use_async = True
use_paging = False
columns = [
grids.TextColumn( "Name", key="name", model_class=model.HistoryDatasetAssociation ),
# grids.IndividualTagsColumn( "Tags", "tags", model.History, model.HistoryTagAssociation, filterable="advanced"),
grids.GridColumn( "Filetype", key="extension" ),
# Columns that are valid for filtering but are not visible.
# SharingColumn( "Shared", key="shared", visible=False, filterable="advanced" )
]
def apply_default_filter( self, trans, query, **kwargs ):
if self.available_tracks is None:
self.available_tracks = trans.app.datatypes_registry.get_available_tracks()
return query.select_from( model.HistoryDatasetAssociation.table \
.join( model.History.table ) ) \
.filter( model.History.user == trans.user ) \
.filter( model.HistoryDatasetAssociation.extension.in_(self.available_tracks) )
class TracksController( BaseController ):
"""
Controller for track browser interface. Handles building a new browser from
datasets in the current history, and display of the resulting browser.
"""
available_tracks = None
@web.expose
def index( self, trans ):
return trans.fill_template( "tracks/index.mako" )
@@ -98,12 +127,13 @@ class TracksController( BaseController ):
# Find all datasets in the current history that are of that dbkey
# and can be displayed
datasets = {}
available_tracks = trans.app.datatypes_registry.get_available_tracks()
if self.available_tracks is None:
self.available_tracks = trans.app.datatypes_registry.get_available_tracks()
for dataset in session.query( model.HistoryDatasetAssociation ).filter_by( deleted=False, history_id=trans.history.id ):
if dataset.metadata.dbkey == dbkey and dataset.extension in available_tracks:
if dataset.metadata.dbkey == dbkey and dataset.extension in self.available_tracks:
datasets[dataset.id] = (dataset.extension, dataset.name)
# Render the template
return trans.fill_template( "tracks/new_browser.mako", available_tracks=available_tracks, dbkey=dbkey, dbkey_set=dbkey_set, datasets=datasets )
return trans.fill_template( "tracks/new_browser.mako", available_tracks=self.available_tracks, dbkey=dbkey, dbkey_set=dbkey_set, datasets=datasets )
@web.expose
def browser(self, trans, id, chrom=""):
@@ -118,13 +148,18 @@ class TracksController( BaseController ):
hda_query = session.query( model.HistoryDatasetAssociation )
for t in vis.latest_revision.config['tracks']:
dataset_id = t['dataset_id']
try:
prefs = t['prefs']
except KeyError:
prefs = {}
dataset = hda_query.get( dataset_id )
track_type, indexer = dataset.datatype.get_track_type()
tracks.append( {
"type": track_type,
"track_type": track_type,
"indexer": indexer,
"name": dataset.name,
"dataset_id": dataset.id
"dataset_id": dataset.id,
"prefs": simplejson.dumps(prefs),
} )
dbkey = dataset.dbkey
chrom_lengths = self._chroms( trans, dbkey )
@@ -252,7 +287,40 @@ class TracksController( BaseController ):
return new_dataset
@web.json
def update_config( self, trans, **kwargs ):
raise RuntimeError
def save( self, trans, **kwargs ):
decoded_id = trans.security.decode_id( kwargs['id'] )
session = trans.sa_session
vis = session.query( model.Visualization ).get( decoded_id )
decoded_payload = simplejson.loads( kwargs['payload'] )
vis_rev = model.VisualizationRevision()
vis_rev.visualization = vis
vis_rev.title = vis.title
tracks = []
for track in decoded_payload:
tracks.append( { "dataset_id": str(track['dataset_id']),
"name": track['name'],
"indexer": track['indexer'],
"track_type": track['track_type'],
"prefs": track['prefs']
} )
vis_rev.config = { "tracks": tracks }
vis.latest_revision = vis_rev
session.add( vis_rev )
session.flush()
data_grid = DatasetSelectionGrid()
@web.expose
@web.require_login( "see all available datasets" )
def list_datasets( self, trans, **kwargs ):
"""List all datasets that can be added as tracks"""
# Render the list view
# return trans.fill_template( 'tracks/add_tracks.mako', grid=data_grid( trans, status=status, message=message, **kwargs ) )
return self.data_grid( trans, **kwargs )
#
+4 -4
View File
@@ -12,7 +12,7 @@ log = logging.getLogger( __name__ )
class Grid( object ):
"""
Specifieds the content and format of a grid (data table).
Specifies the content and format of a grid (data table).
"""
title = ""
exposed = True
@@ -157,10 +157,10 @@ class Grid( object ):
if sort_key.startswith( "-" ):
sort_key = sort_key[1:]
sort_order = 'desc'
query = query.order_by( self.model_class.table.c.get( sort_key ).desc() )
query = query.order_by( func.lower( self.model_class.table.c.get( sort_key ) ).desc() )
else:
sort_order = 'asc'
query = query.order_by( self.model_class.table.c.get( sort_key ).asc() )
query = query.order_by( func.lower( self.model_class.table.c.get( sort_key ) ).asc() )
extra_url_args['sort'] = encoded_sort_key
# There might be a current row
@@ -230,7 +230,7 @@ class Grid( object ):
else:
new_kwargs[ 'id' ] = trans.security.encode_id( id )
return url_for( **new_kwargs )
async_request = ( ( self.use_async ) and ( 'async' in kwargs ) and ( kwargs['async'] in [ 'True', 'true'] ) )
return trans.fill_template( iff( async_request, self.async_template, self.template),
grid=self,
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+88 -62
View File
@@ -94,7 +94,18 @@ $.extend( View.prototype, {
this.tracks.push( track );
if (track.init) { track.init(); }
},
redraw: function () {
remove_track: function( track ) {
delete this.tracks[track];
},
update_options: function() {
for (var track_id in view.tracks) {
var track = view.tracks[track_id];
if (track.update_options) {
track.update_options(track_id);
}
}
},
redraw: function() {
var span = this.span / Math.pow(this.zoom_factor, this.zoom_level),
low = this.center - (span / 2),
high = low + span;
@@ -252,23 +263,22 @@ $.extend( LabelTrack.prototype, Track.prototype, {
}
});
var LineTrack = function ( name, dataset_id, indexer, height, minval, maxval ) {
var LineTrack = function ( name, dataset_id, indexer, prefs ) {
this.track_type = "LineTrack";
this.tile_cache = new Cache(CACHED_TILES_LINE);
Track.call( this, name, $("#viewport") );
TiledTrack.call( this );
this.indexer = indexer;
this.height_px = (height ? height : 100);
this.height_px = 100;
this.container_div.addClass( "line-track" );
this.dataset_id = dataset_id;
this.data_queue = {};
this.data_cache = new Cache(CACHED_DATA); // We need to cache some data because of
// asynchronous calls
if (minval !== undefined && maxval !== undefined) {
this.min_value = minval;
this.max_value = maxval;
this.vertical_range = maxval - minval;
}
this.prefs = { 'min_value': undefined, 'max_value': undefined };
if (prefs.min_value !== undefined) { this.prefs.min_value = prefs.min_value; }
if (prefs.max_value !== undefined) { this.prefs.max_value = prefs.max_value; }
};
$.extend( LineTrack.prototype, TiledTrack.prototype, {
init: function() {
@@ -293,19 +303,19 @@ $.extend( LineTrack.prototype, TiledTrack.prototype, {
track.content_div.text("");
track.content_div.css( "height", track.height_px + "px" );
if (track.min_value === undefined || track.max_value === undefined) {
track.min_value = data.min;
track.max_value = data.max;
track.vertical_range = track.max_value - track.min_value;
if (track.prefs.min_value === undefined || track.prefs.max_value === undefined) {
track.prefs.min_value = data.min;
track.prefs.max_value = data.max;
// Update the config
$('#track_' + track_id + '_minval').val(track.min_value);
$('#track_' + track_id + '_maxval').val(track.max_value);
$('#track_' + track_id + '_minval').val(track.prefs.min_value);
$('#track_' + track_id + '_maxval').val(track.prefs.max_value);
}
track.vertical_range = track.prefs.max_value - track.prefs.min_value;
// Draw y-axis labels
var min_label = $("<div></div>").addClass('yaxislabel').attr("id", 'linetrack_' + track_id + '_minval').text(track.min_value);
var max_label = $("<div></div>").addClass('yaxislabel').attr("id", 'linetrack_' + track_id + '_maxval').text(track.max_value);
var min_label = $("<div></div>").addClass('yaxislabel').attr("id", 'linetrack_' + track_id + '_minval').text(track.prefs.min_value);
var max_label = $("<div></div>").addClass('yaxislabel').attr("id", 'linetrack_' + track_id + '_maxval').text(track.prefs.max_value);
max_label.css({ position: "relative", top: "25px" });
max_label.prependTo(track.container_div);
@@ -358,8 +368,13 @@ $.extend( LineTrack.prototype, TiledTrack.prototype, {
canvas.get(0).width = Math.ceil( tile_length * w_scale );
canvas.get(0).height = this.height_px;
var ctx = canvas.get(0).getContext("2d");
var in_path = false;
var ctx = canvas.get(0).getContext("2d"),
in_path = false,
min_value = this.prefs.min_value,
max_value = this.prefs.max_value,
vertical_range = this.vertical_range,
height_px = this.height_px;
ctx.beginPath();
for ( var i = 0; i < data.length - 1; i++ ) {
var x = data[i][0] - tile_low;
@@ -371,12 +386,12 @@ $.extend( LineTrack.prototype, TiledTrack.prototype, {
// Translate
x = x * w_scale;
// console.log(y, this.min_value, this.vertical_range, (y - this.min_value) / this.vertical_range * this.height_px);
if (y <= this.min_value) {
y = this.min_value;
} else if (y >= this.max_value) {
y = this.max_value;
if (y <= min_value) {
y = min_value;
} else if (y >= max_value) {
y = max_value;
}
y = Math.round( this.height_px - (y - this.min_value) / this.vertical_range * this.height_px );
y = Math.round( height_px - (y - min_value) / vertical_range * height_px );
// console.log(canvas.get(0).height, canvas.get(0).width);
if ( in_path ) {
ctx.lineTo( x, y );
@@ -395,33 +410,37 @@ $.extend( LineTrack.prototype, TiledTrack.prototype, {
var minval = 'track_' + track_id + '_minval',
maxval = 'track_' + track_id + '_maxval',
min_label = $('<label></label>').attr("for", minval).text("Min value:"),
min_input = $('<input></input>').attr("id", minval).val(this.min_value || ""),
min_val = (this.prefs.min_value === undefined ? "" : this.prefs.min_value),
min_input = $('<input></input>').attr("id", minval).val(min_val),
max_label = $('<label></label>').attr("for", maxval).text("Max value:"),
max_input = $('<input></input>').attr("id", maxval).val(this.max_value || "");
max_val = (this.prefs.max_value === undefined ? "" : this.prefs.max_value),
max_input = $('<input></input>').attr("id", maxval).val(max_val);
return container.append(min_label).append(min_input).append(max_label).append(max_input);
}, update_options: function(track_id) {
var min_value = $('#track_' + track_id + '_minval').val(),
max_value = $('#track_' + track_id + '_maxval').val();
if ( min_value !== this.min_value || max_value !== this.max_value) {
this.min_value = parseFloat(min_value);
this.max_value = parseFloat(max_value);
this.vertical_range = this.max_value - this.min_value;
$('#linetrack_' + track_id + '_minval').text(this.min_value);
$('#linetrack_' + track_id + '_maxval').text(this.max_value);
if ( min_value !== this.prefs.min_value || max_value !== this.prefs.max_value) {
this.prefs.min_value = parseFloat(min_value);
this.prefs.max_value = parseFloat(max_value);
this.vertical_range = this.prefs.max_value - this.prefs.min_value;
// Update the y-axis
$('#linetrack_' + track_id + '_minval').text(this.prefs.min_value);
$('#linetrack_' + track_id + '_maxval').text(this.prefs.max_value);
this.tile_cache.clear();
this.draw();
}
}
});
var FeatureTrack = function ( name, dataset_id, indexer, height ) {
var FeatureTrack = function ( name, dataset_id, indexer, prefs ) {
this.track_type = "FeatureTrack";
this.tile_cache = new Cache(CACHED_TILES_FEATURE);
Track.call( this, name, $("#viewport") );
TiledTrack.call( this );
this.indexer = indexer;
this.height_px = (height ? height : 100);
this.height_px = 100;
this.container_div.addClass( "feature-track" );
this.dataset_id = dataset_id;
this.zo_slots = {};
@@ -429,14 +448,16 @@ var FeatureTrack = function ( name, dataset_id, indexer, height ) {
this.showing_details = false;
this.vertical_detail_px = 10;
this.vertical_nodetail_px = 3;
this.block_color = "black";
this.label_color = "black";
this.default_font = "9px Monaco, Lucida Console, monospace";
this.left_offset = 200;
this.inc_slots = {};
this.data_queue = {};
this.s_e_by_tile = {};
this.data_cache = new Cache(20);
this.prefs = { 'block_color': 'black', 'label_color': 'black' };
if (prefs.block_color !== undefined) { this.prefs.block_color = prefs.block_color; }
if (prefs.label_color !== undefined) { this.prefs.label_color = prefs.label_color; }
};
$.extend( FeatureTrack.prototype, TiledTrack.prototype, {
init: function() {
@@ -609,18 +630,23 @@ $.extend( FeatureTrack.prototype, TiledTrack.prototype, {
// console.log(tile_low, tile_high, tile_length, w_scale);
var width = Math.ceil( tile_span * w_scale ),
new_canvas = $("<canvas class='tile'></canvas>");
new_canvas = $("<canvas class='tile'></canvas>"),
label_color = this.prefs.label_color,
block_color = this.prefs.block_color,
left_offset = this.left_offset,
showing_details = this.showing_details,
y_scale = (this.showing_details ? this.vertical_detail_px : this.vertical_nodetail_px);
new_canvas.css({
position: "absolute",
top: 0,
left: ( tile_low - this.view.low ) * w_scale - this.left_offset
left: ( tile_low - this.view.low ) * w_scale - left_offset
});
new_canvas.get(0).width = width + this.left_offset;
new_canvas.get(0).width = width + left_offset;
new_canvas.get(0).height = required_height;
// console.log(( tile_low - this.view.low ) * w_scale, tile_index, w_scale);
var ctx = new_canvas.get(0).getContext("2d");
ctx.fillStyle = this.block_color;
ctx.fillStyle = this.prefs.block_color;
ctx.font = this.default_font;
ctx.textAlign = "right";
@@ -630,22 +656,22 @@ $.extend( FeatureTrack.prototype, TiledTrack.prototype, {
if (feature.start <= tile_high && feature.end >= tile_low) {
var f_start = Math.floor( Math.max(0, (feature.start - tile_low) * w_scale) ),
f_end = Math.ceil( Math.min(width, (feature.end - tile_low) * w_scale) ),
y_center = slots[feature.uid] * (this.showing_details ? this.vertical_detail_px : this.vertical_nodetail_px);
y_center = slots[feature.uid] * y_scale;
var thickness, y_start, thick_start = null, thick_end = null;
if (feature.thick_start && feature.thick_end) {
thick_start = Math.floor( Math.max(0, (feature.thick_start - tile_low) * w_scale) );
thick_end = Math.ceil( Math.min(width, (feature.thick_end - tile_low) * w_scale) );
}
if (!this.showing_details) {
if (!showing_details) {
// Non-detail levels
ctx.fillRect(f_start + this.left_offset, y_center + 5, f_end - f_start, 1);
ctx.fillRect(f_start + left_offset, y_center + 5, f_end - f_start, 1);
} else {
// Showing labels, blocks, details
if (feature.start > tile_low) {
ctx.fillStyle = this.label_color;
ctx.fillText(feature.name, f_start - 1 + this.left_offset, y_center + 8);
ctx.fillStyle = this.block_color;
ctx.fillStyle = label_color;
ctx.fillText(feature.name, f_start - 1 + left_offset, y_center + 8);
ctx.fillStyle = block_color;
}
var blocks = feature.blocks;
if (blocks) {
@@ -656,8 +682,8 @@ $.extend( FeatureTrack.prototype, TiledTrack.prototype, {
} else if (feature.strand == "-") {
ctx.fillStyle = LEFT_STRAND;
}
ctx.fillRect(f_start + this.left_offset, y_center, f_end - f_start, 10);
ctx.fillStyle = this.block_color;
ctx.fillRect(f_start + left_offset, y_center, f_end - f_start, 10);
ctx.fillStyle = block_color;
}
for (var k = 0, k_len = blocks.length; k < k_len; k++) {
@@ -668,7 +694,7 @@ $.extend( FeatureTrack.prototype, TiledTrack.prototype, {
// Draw the block
thickness = 5;
y_start = 3;
ctx.fillRect(block_start + this.left_offset, y_center + y_start, block_end - block_start, thickness);
ctx.fillRect(block_start + left_offset, y_center + y_start, block_end - block_start, thickness);
// Draw thick regions: check if block intersects with thick region
if (thick_start !== undefined && !(block_start > thick_end || block_end < thick_start) ) {
@@ -676,7 +702,7 @@ $.extend( FeatureTrack.prototype, TiledTrack.prototype, {
y_start = 1;
var block_thick_start = Math.max(block_start, thick_start),
block_thick_end = Math.min(block_end, thick_end);
ctx.fillRect(block_thick_start + this.left_offset, y_center + y_start, block_thick_end - block_thick_start, thickness);
ctx.fillRect(block_thick_start + left_offset, y_center + y_start, block_thick_end - block_thick_start, thickness);
}
}
@@ -684,15 +710,15 @@ $.extend( FeatureTrack.prototype, TiledTrack.prototype, {
// If there are no blocks, we treat the feature as one big exon
thickness = 9;
y_start = 1;
ctx.fillRect(f_start + this.left_offset, y_center + y_start, f_end - f_start, thickness);
ctx.fillRect(f_start + left_offset, y_center + y_start, f_end - f_start, thickness);
if ( feature.strand ) {
if (feature.strand == "+") {
ctx.fillStyle = RIGHT_STRAND_INV;
} else if (feature.strand == "-") {
ctx.fillStyle = LEFT_STRAND_INV;
}
ctx.fillRect(f_start + this.left_offset, y_center, f_end - f_start, 10);
ctx.fillStyle = this.block_color;
ctx.fillRect(f_start + left_offset, y_center, f_end - f_start, 10);
ctx.fillStyle = prefs.block_color;
}
}
}
@@ -707,29 +733,29 @@ $.extend( FeatureTrack.prototype, TiledTrack.prototype, {
var block_color = 'track_' + track_id + '_block_color',
block_color_label = $('<label></label>').attr("for", block_color).text("Block color:"),
block_color_input = $('<input></input>').attr("id", block_color).attr("name", block_color).val(this.block_color),
block_color_input = $('<input></input>').attr("id", block_color).attr("name", block_color).val(this.prefs.block_color),
label_color = 'track_' + track_id + '_label_color',
label_color_label = $('<label></label>').attr("for", label_color).text("Label color:"),
label_color_input = $('<input></input>').attr("id", label_color).attr("name", label_color).val(this.label_color);
label_color_input = $('<input></input>').attr("id", label_color).attr("name", label_color).val(this.prefs.label_color);
return container.append(block_color_label).append(block_color_input).append(label_color_label).append(label_color_input);
}, update_options: function(track_id) {
var block_color = $('#track_' + track_id + '_block_color').val(),
label_color = $('#track_' + track_id + '_label_color').val();
if (block_color !== this.block_color || label_color !== this.label_color) {
this.block_color = block_color;
this.label_color = label_color;
if (block_color !== this.prefs.block_color || label_color !== this.prefs.label_color) {
this.prefs.block_color = block_color;
this.prefs.label_color = label_color;
this.tile_cache.clear();
this.draw();
}
}
});
var ReadTrack = function ( name, dataset_id, indexer, height ) {
var ReadTrack = function ( name, dataset_id, indexer, prefs ) {
this.track_type = "ReadTrack";
this.tile_cache = new Cache(CACHED_TILES_FEATURE);
Track.call( this, name, $("#viewport") );
TiledTrack.call( this );
FeatureTrack.call( this, name, dataset_id, indexer, height );
this.default_font = "9px Monaco, Lucida Console, monospace";
FeatureTrack.call( this, name, dataset_id, indexer, prefs );
};
$.extend( ReadTrack.prototype, TiledTrack.prototype, FeatureTrack.prototype, {
@@ -760,7 +786,7 @@ $.extend( ReadTrack.prototype, TiledTrack.prototype, FeatureTrack.prototype, {
new_canvas.get(0).height = required_height;
// console.log(( tile_low - this.view.low ) * w_scale, tile_index, w_scale);
var ctx = new_canvas.get(0).getContext("2d");
ctx.fillStyle = this.block_color;
ctx.fillStyle = this.prefs.block_color;
ctx.font = this.default_font;
ctx.textAlign = "right";
var px_per_char = ctx.measureText("A").width;
-17
View File
@@ -1,16 +1,3 @@
body, html {
height: 100%;
}
body {
margin: 0 0;
padding: 0;
font-family: verdana;
font-size: 12px;
overflow: hidden;
background: #eeeeee;
}
#content {
width: 100%;
}
@@ -24,10 +11,6 @@ body {
bottom: 0;
}
input {
font-size: 100%;
}
/*canvas{
border-left: 1px solid green;
border-right: 1px solid red; } /* debugging */
+6 -4
View File
@@ -205,6 +205,7 @@
var grid = this;
var checkboxes = $(this).find("input.grid-row-select-checkbox");
var update = $(this).find( "span.grid-selected-count" );
update.text("");
$(checkboxes).each( function() {
$(this).change( function() {
var n = $(checkboxes).filter("[checked]").size();
@@ -834,6 +835,7 @@
<% num_rows_rendered = 1 %>
%endif
%for i, item in enumerate( query ):
<% encoded_id = trans.security.encode_id( item.id ) %>
<tr \
%if current_item == item:
class="current" \
@@ -842,7 +844,7 @@
## Item selection column
%if show_item_checkboxes:
<td style="width: 1.5em;">
<input type="checkbox" name="id" value=${trans.security.encode_id( item.id )} class="grid-row-select-checkbox" />
<input type="checkbox" id="${encoded_id}" name="id" value="${encoded_id}" class="grid-row-select-checkbox" />
</td>
%endif
## Data columns
@@ -875,12 +877,12 @@
cls = "menubutton"
if column.attach_popup and href:
cls = "menubutton split"
%>
%if href:
%if href:
<td><div id="${id}" class="${cls}" style="float: left;"><a class="label" href="${href}">${v}</a></td>
%else:
<td><div id="${id}" class="${cls}">${v}</div></td>
<td><div id="${id}" class="${cls}"><label for="${encoded_id}">${v}</label></div></td>
%endif
%endfor
%endif
+12
View File
@@ -0,0 +1,12 @@
## Template generates a grid that enables user to add tracks
<%namespace file="../grid_base.mako" import="*" />
${javascripts()}
${stylesheets()}
${render_grid_table( grid, show_item_checkboxes=True )}
## Initialize the grid.
<script type="text/javascript">
init_grid_elements();
init_grid_controls();
</script>
+54 -11
View File
@@ -78,16 +78,18 @@ ${h.css( "history" )}
## <input name="title" id="title" value="${title}" />
<div id="show-hide-move">
<ul id="sortable-ul"></ul>
## <input type="submit" id="update-config" value="Save settings" />
<input type="button" id="refresh-button" value="Refresh" />
</div>
## <input type="submit" id="update-config" value="Save settings" />
<input type="button" id="refresh-button" value="Refresh" />
<input type="button" id="save-button" value="Save" />
<input id="add-track" type="button" value="Add Track" />
</form>
</%def>
<%def name="javascripts()">
${parent.javascripts()}
${h.js( "jquery", "jquery.event.drag", "jquery.mousewheel", "trackster", "ui.core", "ui.sortable" )}
${h.js( "json2", "jquery", "jquery.event.drag", "jquery.mousewheel", "trackster", "ui.core", "ui.sortable" )}
<script type="text/javascript">
@@ -100,7 +102,9 @@ ${h.js( "jquery", "jquery.event.drag", "jquery.mousewheel", "trackster", "ui.cor
view.add_track( new LabelTrack( $("#nav-labeltrack" ) ) );
%for track in tracks:
view.add_track( new ${track["type"]}( "${track['name']}", ${track['dataset_id']}, "${track['indexer']}" ) );
view.add_track(
new ${track["track_type"]}( "${track['name']}", ${track['dataset_id']}, "${track['indexer']}", ${track['prefs']} )
);
%endfor
$(document).bind( "redraw", function( e ) {
@@ -164,12 +168,51 @@ ${h.js( "jquery", "jquery.event.drag", "jquery.mousewheel", "trackster", "ui.cor
});
$("#refresh-button").bind( "click", function(e) {
for (var track_id in view.tracks) {
var track = view.tracks[track_id];
if (track.update_options) {
track.update_options(track_id);
view.update_options();
});
// Use a popup grid to add more tracks
$("#add-track").bind( "click", function(e) {
$.ajax({
url: "${h.url_for( action='list_datasets' )}",
data: {},
error: function() { alert( "Grid refresh failed" ) },
success: function(table_html) {
show_modal("Add Track &mdash; Select Dataset(s)", table_html, {
"Insert": function() {
hide_modal();
},
"Cancel": function() {
hide_modal();
}
});
}
});
});
$("#save-button").bind("click", function(e) {
view.update_options();
var sorted = $("ul#sortable-ul").sortable('toArray');
var payload = [];
for (var i in sorted) {
var track_id = parseInt(sorted[i].split("track_")[1]),
track = view.tracks[track_id];
payload.push( {
"track_type": track.track_type,
"indexer": track.indexer,
"name": track.name,
"dataset_id": track.dataset_id,
"prefs": track.prefs
});
}
$.ajax({
url: "${h.url_for( action='save' )}",
data: {
'id': '${id}',
'payload': JSON.stringify(payload)
}
});
});
// Execute this on page load
@@ -195,12 +238,12 @@ ${h.js( "jquery", "jquery.event.drag", "jquery.mousewheel", "trackster", "ui.cor
var track = view.tracks[track_id];
if (!track.hidden) {
var label = $('<label for="track_' + track_id + 'title">' + track.name + '</label>');
var title = $('<div class="toolFormTitle"></div>');
var title = $('<div class="historyItemTitle"></div>');
var del_icon = $('<a style="display:block; float:right" href="#" class="icon-button delete" />');
var body = $('<div class="toolFormBody"></div>');
var body = $('<div class="historyItemBody"></div>');
// var checkbox = $('<input type="checkbox" checked="checked"></input>').attr("id", "track_" + track_id + "title");
var li = $('<li class="sortable"></li>').attr("id", "track_" + track_id);
var div = $('<div class="toolForm"></div>');
var div = $('<div class="historyItemContainer historyItem"></div>');
del_icon.prependTo(title);
label.appendTo(title);
// checkbox.prependTo(title);