Trackster: create a set of shared functions for managing the user interface and use functions in both visualization editor and display.

This commit is contained in:
Jeremy Goecks
2011-08-25 11:28:01 -04:00
parent 714291e078
commit a360a335c7
4 changed files with 156 additions and 179 deletions
+3 -2
View File
@@ -464,7 +464,7 @@ extend(ReferenceTrackDataManager.prototype, DataManager.prototype, Cache.prototy
/**
* View object manages complete viz view, including tracks and user interactions.
*/
var View = function( container, title, vis_id, dbkey, callback ) {
var View = function(container, title, vis_id, dbkey, callback) {
this.container = container;
this.chrom = null;
this.vis_id = vis_id;
@@ -826,6 +826,7 @@ extend( View.prototype, {
sortable( track.container_div, '.draghandle' );
this.track_id_counter += 1;
this.num_tracks += 1;
this.has_changes = true;
this.update_intro_div();
},
add_label_track: function (label_track) {
@@ -993,9 +994,9 @@ extend( View.prototype, {
view.overview_track.set_is_overview(false);
}
view.overview_track = track;
view.has_changes = true;
track.set_is_overview(true);
});
view.has_changes = true;
},
/** Close and reset overview. */
reset_overview: function() {
+118
View File
@@ -0,0 +1,118 @@
/************************************************************************
* Functions used for creating and managing the Trackster user interface.
************************************************************************/
/**
* Add bookmark.
*/
var add_bookmark = function(position, annotation) {
var
bookmarks_container = $("#bookmarks-container"),
new_bookmark = $("<div/>").addClass("bookmark").appendTo(bookmarks_container),
delete_icon_container = $("<div/>").addClass("delete-icon-container").appendTo(new_bookmark).click(function (){
// Remove bookmark.
new_bookmark.slideUp("fast");
new_bookmark.remove();
view.has_changes = true;
return false;
}),
delete_icon = $("<a href=''/>").addClass("icon-button delete").appendTo(delete_icon_container),
position_div = $("<div/>").addClass("position").appendTo(new_bookmark),
position_link = $("<a href=''/>").text(position).appendTo(position_div).click(function() {
view.go_to(position);
return false;
});
annotation_div = get_editable_text_elt(annotation, true).addClass("annotation").appendTo(new_bookmark);
view.has_changes = true;
return new_bookmark;
};
/**
* Types of tracks that can be added to a view.
*/
var addable_track_types = { "LineTrack": LineTrack, "FeatureTrack": FeatureTrack, "ReadTrack": ReadTrack };
/**
* Decode a track from a dictionary.
*/
var track_from_dict = function(track_dict) {
return new addable_track_types[track_dict.track_type](
track_dict.name, view, track_dict.hda_ldda, track_dict.dataset_id,
track_dict.prefs, track_dict.filters, track_dict.tool
/* TODO: ( track_dict.is_child ? parent_track : undefined */ );
};
/**
* Create a complete Trackster visualization. Returns view.
*/
var create_visualization = function(parent_elt, title, id, dbkey, callback, tracks_config, bookmarks_config) {
// Create view.
view = new View(parent_elt, title, id, dbkey, callback);
view.editor = true;
// Add tracks to view.
if (tracks_config) {
var track_config, track, parent_track, parent_obj;
for (var i = 0; i < tracks_config.length; i++) {
track_config = tracks_config[i];
// TODO: set parent for child track:
track = track_from_dict(track_config);
parent_obj = view;
if (track_config.is_child) {
parent_obj = parent_track;
}
else {
// New parent track is this track.
parent_track = track;
}
parent_obj.add_track(track);
}
}
// Load bookmarks.
if (bookmarks_config) {
var bookmark;
for (var i = 0; i < bookmarks_config.length; i++) {
bookmark = bookmarks_config[i];
add_bookmark(bookmark['position'], bookmark['annotation']);
}
}
// View has no changes as of yet.
view.has_changes = false;
return view;
};
/**
* Set up keyboard navigation for a visualization.
*/
var init_keyboard_nav = function(view) {
// Keyboard navigation. Scroll ~7% of height when scrolling up/down.
$(document).keydown(function(e) {
// Do not navigate if arrow keys used in input element.
if ($(e.srcElement).is(':input')) {
return;
}
// Key codes: left == 37, up == 38, right == 39, down == 40
switch(e.which) {
case 37:
view.move_fraction(0.25);
break
case 38:
var change = Math.round(view.viewport_container.height()/15.0);
view.viewport_container.scrollTo('-=' + change + 'px');
break;
case 39:
view.move_fraction(-0.25);
break;
case 40:
var change = Math.round(view.viewport_container.height()/15.0);
view.viewport_container.scrollTo('+=' + change + 'px');
break;
}
});
};
+26 -123
View File
@@ -42,7 +42,7 @@ ${parent.javascripts()}
<script type='text/javascript' src="${h.url_for('/static/scripts/excanvas.js')}"></script>
<![endif]-->
${h.js( "galaxy.base", "galaxy.panels", "json2", "jquery", "jstorage", "jquery.event.drag", "jquery.mousewheel", "jquery.autocomplete", "trackster", "jquery.ui.sortable.slider", "jquery.scrollTo", "farbtastic" )}
${h.js( "galaxy.base", "galaxy.panels", "json2", "jquery", "jstorage", "jquery.event.drag", "jquery.mousewheel", "jquery.autocomplete", "trackster", "trackster_ui", "jquery.ui.sortable.slider", "jquery.scrollTo", "farbtastic" )}
<script type="text/javascript">
@@ -57,51 +57,8 @@ ${h.js( "galaxy.base", "galaxy.panels", "json2", "jquery", "jstorage", "jquery.e
chrom_url = "${h.url_for( action='chroms' )}",
dataset_state_url = "${h.url_for( action='dataset_state' )}",
converted_datasets_state_url = "${h.url_for( action='converted_datasets_state' )}",
addable_track_types = { "LineTrack": LineTrack, "FeatureTrack": FeatureTrack, "ReadTrack": ReadTrack },
view;
/**
* Add bookmark.
*/
var add_bookmark = function(position, annotation) {
var
bookmarks_container = $("#bookmarks-container"),
new_bookmark = $("<div/>").addClass("bookmark").appendTo(bookmarks_container),
delete_icon_container = $("<div/>").addClass("delete-icon-container").appendTo(new_bookmark).click(function (){
// Remove bookmark.
new_bookmark.slideUp("fast");
new_bookmark.remove();
view.has_changes = true;
return false;
}),
delete_icon = $("<a href=''/>").addClass("icon-button delete").appendTo(delete_icon_container),
position_div = $("<div/>").addClass("position").appendTo(new_bookmark),
position_link = $("<a href=''/>").text(position).appendTo(position_div).click(function() {
view.go_to(position);
return false;
});
annotation_div = get_editable_text_elt(annotation, true).addClass("annotation").appendTo(new_bookmark);
view.has_changes = true;
return new_bookmark;
};
/**
* Use track data to add a track to a view.
* TODO: rename function?
*/
var add_async_success = function(track_data) {
var td = track_data,
new_track = new addable_track_types[track_data.track_type](
track_data.name, view, track_data.hda_ldda, track_data.dataset_id,
track_data.prefs, track_data.filters, track_data.tool );
view.add_track(new_track);
// Should replace with live event but can't get working
sortable(new_track.container_div, ".draghandle");
view.has_changes = true;
$("#no-tracks").hide();
};
/**
* Use a popup grid to add more tracks.
*/
@@ -144,7 +101,7 @@ ${h.js( "galaxy.base", "galaxy.panels", "json2", "jquery", "jstorage", "jquery.e
[ arguments[0] ]
);
for (var i= 0; i < track_defs.length; i++) {
add_async_success(track_defs[i]);
view.add_track( track_from_dict(track_defs[i]) );
}
});
hide_modal();
@@ -165,6 +122,7 @@ ${h.js( "galaxy.base", "galaxy.panels", "json2", "jquery", "jstorage", "jquery.e
%if config:
var callback;
%if 'viewport' in config:
// TODO: find better way to handle this code.
var callback = function() {
view.change_chrom( '${config['viewport']['chrom']}', ${config['viewport']['start']}, ${config['viewport']['end']} );
// Set overview.
@@ -180,51 +138,20 @@ ${h.js( "galaxy.base", "galaxy.panels", "json2", "jquery", "jstorage", "jquery.e
}
}
%endif
}
view.has_changes = false;
};
%endif
view = new View( $("#browser-container"), "${config.get('title') | h}", "${config.get('vis_id')}", "${config.get('dbkey')}", callback );
view.editor = true;
## A little ugly and redundant, but it gets the job done moving the config from python to JS:
var tracks_config = JSON.parse('${ h.to_json_string( config.get('tracks') ) }');
var track_config, track, parent_track, parent_obj;
for (var i = 0; i < tracks_config.length; i++) {
track_config = tracks_config[i];
track = new addable_track_types[track_config["track_type"]](
track_config['name'],
view,
track_config['hda_ldda'],
track_config['dataset_id'],
track_config['prefs'],
track_config['filters'],
track_config['tool'],
(track_config.is_child ? parent_track : undefined));
parent_obj = view;
if (track_config.is_child) {
parent_obj = parent_track;
}
else {
// New parent track is this track.
parent_track = track;
}
parent_obj.add_track(track);
}
init();
// Load bookmarks.
var bookmarks = JSON.parse('${ h.to_json_string( config.get('bookmarks') ) }'),
bookmark;
for (var i = 0; i < bookmarks.length; i++) {
bookmark = bookmarks[i];
add_bookmark(bookmark['position'], bookmark['annotation']);
}
// View has no changes as of yet.
view.has_changes = false;
view = create_visualization( $("#browser-container"), "${config.get('title') | h}",
"${config.get('vis_id')}", "${config.get('dbkey')}", callback,
JSON.parse('${ h.to_json_string( config.get('tracks') ) }'),
JSON.parse('${ h.to_json_string( config.get('bookmarks') ) }')
);
init_editor();
%else:
var continue_fn = function() {
view = new View( $("#browser-container"), $("#new-title").val(), undefined, $("#new-dbkey").val() );
view = create_visualization( $("#browser-container"), $("#new-title").val(), undefined, $("#new-dbkey").val() );
view.editor = true;
init();
init_editor();
hide_modal();
};
$.ajax({
@@ -242,11 +169,10 @@ ${h.js( "galaxy.base", "galaxy.panels", "json2", "jquery", "jstorage", "jquery.e
});
%endif
// Execute initializer for EDITOR specific javascript
function init() {
if (view.num_tracks === 0) {
$("#no-tracks").show();
}
/**
* Initialization for editor-specific functions.
*/
function init_editor() {
$("#title").text(view.title + " (" + view.dbkey + ")");
window.onbeforeunload = function() {
@@ -260,13 +186,16 @@ ${h.js( "galaxy.base", "galaxy.panels", "json2", "jquery", "jstorage", "jquery.e
url: "${h.url_for( action='add_track_async' )}",
data: { hda_id: "${add_dataset}" },
dataType: "json",
success: add_async_success
success: function(track_data) { view.add_track( track_from_dict(track_data) ) }
});
%endif
$("#viz-options-button").css( "position", "relative" );
make_popupmenu( $("#viz-options-button"), {
//
// Make actions menu.
//
$("#viz-actions-button").css( "position", "relative" );
make_popupmenu( $("#viz-actions-button"), {
"Add Tracks": add_tracks,
"Save": function() {
// Show saving dialog box
@@ -344,34 +273,8 @@ ${h.js( "galaxy.base", "galaxy.panels", "json2", "jquery", "jstorage", "jquery.e
annotation = "Bookmark description";
return add_bookmark(position, annotation);
});
//
// Keyboard navigation. Scroll ~7% of height when scrolling up/down.
//
$(document).keydown(function(e) {
// Do not navigate if arrow keys used in input element.
if ($(e.srcElement).is(':input')) {
return;
}
// Key codes: left == 37, up == 38, right == 39, down == 40
switch(e.which) {
case 37:
view.move_fraction(0.25);
break
case 38:
var change = Math.round(view.viewport_container.height()/15.0);
view.viewport_container.scrollTo('-=' + change + 'px');
break;
case 39:
view.move_fraction(-0.25);
break;
case 40:
var change = Math.round(view.viewport_container.height()/15.0);
view.viewport_container.scrollTo('+=' + change + 'px');
break;
}
});
init_keyboard_nav(view);
};
});
@@ -384,7 +287,7 @@ ${h.js( "galaxy.base", "galaxy.panels", "json2", "jquery", "jstorage", "jquery.e
<div class="unified-panel-header-inner">
<div style="float:left;" id="title"></div>
<div style="float: right">
<a id="viz-options-button" class='panel-header-button popup' href="javascript:void(0)" target="galaxy_main">${_('Options')}</a>
<a id="viz-actions-button" class='panel-header-button popup' href="javascript:void(0)" target="galaxy_main">${_('Actions')}</a>
</div>
</div>
</div>
+9 -54
View File
@@ -8,7 +8,7 @@
<script type='text/javascript' src="${h.url_for('/static/scripts/excanvas.js')}"></script>
<![endif]-->
${h.js( "jquery.event.drag", "jquery.autocomplete", "jquery.mousewheel", "jquery.autocomplete", "trackster", "jquery.ui.sortable.slider", "jquery.scrollTo", "farbtastic" )}
${h.js( "jquery.event.drag", "jquery.autocomplete", "jquery.mousewheel", "jquery.autocomplete", "trackster", "trackster_ui", "jquery.ui.sortable.slider", "jquery.scrollTo", "farbtastic" )}
</%def>
<%def name="stylesheets()">
@@ -86,64 +86,19 @@
$("#right-border").click(function() { view.resize_window(); });
}
// Create view and add tracks.
// Create visualization.
var callback;
%if 'viewport' in config:
var callback = function() { view.change_chrom( '${config['viewport']['chrom']}', ${config['viewport']['start']}, ${config['viewport']['end']} ); }
%endif
view = new View(container_element, "${config.get('title') | h}", "${config.get('vis_id')}", "${config.get('dbkey')}", callback);
## A little ugly and redundant, but it gets the job done moving the config from python to JS:
var tracks_config = JSON.parse('${ h.to_json_string( config.get('tracks') ) }');
var track_config, track, parent_track, parent_obj;
for (var i = 0; i < tracks_config.length; i++) {
track_config = tracks_config[i];
track = new addable_track_types[track_config["track_type"]](
track_config['name'],
view,
track_config['hda_ldda'],
track_config['dataset_id'],
track_config['prefs'],
track_config['filters'],
track_config['tool'],
(track_config.is_child ? parent_track : undefined));
parent_obj = view;
if (track_config.is_child) {
parent_obj = parent_track;
}
else {
// New parent track is this track.
parent_track = track;
}
parent_obj.add_track(track);
}
view = create_visualization( container_element, "${config.get('title') | h}",
"${config.get('vis_id')}", "${config.get('dbkey')}", callback,
JSON.parse('${ h.to_json_string( config.get('tracks') ) }'),
JSON.parse('${ h.to_json_string( config.get('bookmarks') ) }')
);
//
// Keyboard navigation. Scroll ~7% of height when scrolling up/down.
//
$(document).keydown(function(e) {
// Do not navigate if arrow keys used in input element.
if ($(e.srcElement).is(':input')) {
return;
}
// Key codes: left == 37, up == 38, right == 39, down == 40
switch(e.which) {
case 37:
view.move_fraction(0.25);
break
case 38:
var change = Math.round(view.viewport_container.height()/15.0);
view.viewport_container.scrollTo('-=' + change + 'px');
break;
case 39:
view.move_fraction(-0.25);
break;
case 40:
var change = Math.round(view.viewport_container.height()/15.0);
view.viewport_container.scrollTo('+=' + change + 'px');
break;
}
});
// Set up keyboard navigation.
init_keyboard_nav(view);
});
</script>