Explicit vars from multi-declarations.

This commit is contained in:
Dannon Baker
2017-11-01 13:31:10 -04:00
parent 5c9ef6149b
commit 5803e6f7d5
163 changed files with 3057 additions and 2588 deletions
+6 -5
View File
@@ -24,9 +24,10 @@ function GalaxyApp(options, bootstrapped) {
addLogging(GalaxyApp, "GalaxyApp");
// a debug flag can be set via local storage and made available during script/page loading
var DEBUGGING_KEY = "galaxy:debug",
NAMESPACE_KEY = DEBUGGING_KEY + ":namespaces",
localDebugging = false;
var DEBUGGING_KEY = "galaxy:debug";
var NAMESPACE_KEY = DEBUGGING_KEY + ":namespaces";
var localDebugging = false;
try {
localDebugging = localStorage.getItem(DEBUGGING_KEY) == "true";
} catch (storageErr) {
@@ -92,8 +93,8 @@ GalaxyApp.prototype.defaultOptions = {
/** filter to options present in defaultOptions (and default to them) */
GalaxyApp.prototype._processOptions = function _processOptions(options) {
var self = this,
defaults = self.defaultOptions;
var self = this;
var defaults = self.defaultOptions;
self.options = {};
for (var k in defaults) {
+12 -5
View File
@@ -45,7 +45,10 @@ function init_galaxy_elts(wym) {
// Based on the dialog type, return a dictionary of information about an item
function get_item_info(dialog_type) {
var item_singular, item_plural, item_controller, item_class;
var item_singular;
var item_plural;
var item_controller;
var item_class;
switch (dialog_type) {
case CONTROLS.ITEM_HISTORY:
item_singular = "History";
@@ -147,8 +150,11 @@ WYMeditor.editor.prototype.dialog = function(
);
$(wym._options.altSelector).val($(selected).attr(WYMeditor.ALT));
}
// Get current URL, title.
var curURL, curTitle;
var curURL;
var curTitle;
if (selected) {
curURL = $(selected).attr("href");
if (curURL == undefined) curURL = "";
@@ -166,9 +172,10 @@ WYMeditor.editor.prototype.dialog = function(
{
"Make link": function() {
// Get URL, name/title.
var sUrl = $(wym._options.hrefSelector).val() || "",
sId = $(".wym_id").val() || "",
sName = $(wym._options.titleSelector).val() || "";
var sUrl = $(wym._options.hrefSelector).val() || "";
var sId = $(".wym_id").val() || "";
var sName = $(wym._options.titleSelector).val() || "";
if (sUrl || sId) {
// Create link.
@@ -8,31 +8,38 @@ var GenericNavView = Backbone.View.extend({
/** makes bootstrap modal and iframe inside it */
makeModalIframe: function(e) {
// make modal
var host = window.Galaxy.config.communication_server_host,
port = window.Galaxy.config.communication_server_port,
username = escape(window.Galaxy.user.attributes.username),
persistent_communication_rooms = escape(
window.Galaxy.config.persistent_communication_rooms
),
query_string =
"?username=" +
username +
"&persistent_communication_rooms=" +
persistent_communication_rooms,
src = host + ":" + port + query_string,
$el_chat_modal_header = null,
$el_chat_modal_body = null,
iframe_template =
'<iframe class="f-iframe fade in communication-iframe" src="' +
src +
'"> </iframe>',
header_template =
'<i class="fa fa-comment" aria-hidden="true" title="Communicate with other users"></i>' +
'<i class="fa fa-expand expand-compress-modal" aria-hidden="true" title="Maximize"></i>' +
'<i class="fa fa-times close-modal" aria-hidden="true" title="Close"></i>',
frame_height = 350,
frame_width = 600,
class_names = "ui-modal chat-modal";
var host = window.Galaxy.config.communication_server_host;
var port = window.Galaxy.config.communication_server_port;
var username = escape(window.Galaxy.user.attributes.username);
var persistent_communication_rooms = escape(
window.Galaxy.config.persistent_communication_rooms
);
var query_string =
"?username=" +
username +
"&persistent_communication_rooms=" +
persistent_communication_rooms;
var src = host + ":" + port + query_string;
var $el_chat_modal_header = null;
var $el_chat_modal_body = null;
var iframe_template =
'<iframe class="f-iframe fade in communication-iframe" src="' +
src +
'"> </iframe>';
var header_template =
'<i class="fa fa-comment" aria-hidden="true" title="Communicate with other users"></i>' +
'<i class="fa fa-expand expand-compress-modal" aria-hidden="true" title="Maximize"></i>' +
'<i class="fa fa-times close-modal" aria-hidden="true" title="Close"></i>';
var frame_height = 350;
var frame_width = 600;
var class_names = "ui-modal chat-modal";
// deletes the chat modal if already present and create one
if ($(".chat-modal").length > 0) {
@@ -87,8 +94,8 @@ var GenericNavView = Backbone.View.extend({
/**renders the chat icon as a nav item*/
render: function() {
var self = this,
navItem = {};
var self = this;
var navItem = {};
navItem = {
id: "show-chat-online",
icon: "fa-comment-o",
+4 -4
View File
@@ -156,10 +156,10 @@ var View = Backbone.View.extend({
/** Check if the communication server is online and show the icon otherwise hide the icon */
_checkCommunicationServerOnline: function() {
var host = window.Galaxy.config.communication_server_host,
port = window.Galaxy.config.communication_server_port,
preferences = window.Galaxy.user.attributes.preferences,
$chat_icon_element = $("#show-chat-online");
var host = window.Galaxy.config.communication_server_host;
var port = window.Galaxy.config.communication_server_port;
var preferences = window.Galaxy.user.attributes.preferences;
var $chat_icon_element = $("#show-chat-online");
/** Check if the user has deactivated the communication in it's personal settings */
if (
preferences &&
+12 -12
View File
@@ -2,8 +2,8 @@ import $ from "jquery";
import * as _ from "libs/underscore";
import * as Backbone from "libs/backbone";
var MIN_PANEL_WIDTH = 160,
MAX_PANEL_WIDTH = 800;
var MIN_PANEL_WIDTH = 160;
var MAX_PANEL_WIDTH = 800;
/** View for left/right panels used by Page view */
var SidePanel = Backbone.View.extend({
@@ -80,15 +80,15 @@ var SidePanel = Backbone.View.extend({
},
_mousedownDragHandler: function(ev) {
var self = this,
draggingLeft = this.id === "left",
prevX = ev.pageX;
var self = this;
var draggingLeft = this.id === "left";
var prevX = ev.pageX;
function move(e) {
var delta = e.pageX - prevX;
prevX = e.pageX;
var oldWidth = self.$el.width(),
newWidth = draggingLeft ? oldWidth + delta : oldWidth - delta;
var oldWidth = self.$el.width();
var newWidth = draggingLeft ? oldWidth + delta : oldWidth - delta;
// Limit range
newWidth = Math.min(
MAX_PANEL_WIDTH,
@@ -121,9 +121,9 @@ var SidePanel = Backbone.View.extend({
if (!this.hidden) {
return;
}
var self = this,
animation = {},
whichSide = this.id;
var self = this;
var animation = {};
var whichSide = this.id;
animation[whichSide] = 0;
self.$el
.css(whichSide, -this.saved_size)
@@ -140,8 +140,8 @@ var SidePanel = Backbone.View.extend({
if (this.hidden) {
return;
}
var animation = {},
whichSide = this.id;
var animation = {};
var whichSide = this.id;
this.saved_size = this.$el.width();
animation[whichSide] = -this.saved_size;
this.$el.animate(animation, "fast");
+10 -9
View File
@@ -204,15 +204,16 @@ export default Backbone.View.extend({
content: function(parent_elt) {
// Create view config.
var view_config = {
container: parent_elt,
name: viz.get("title"),
id: viz.id,
// FIXME: this will not work with custom builds b/c the dbkey needed to be encoded.
dbkey: viz.get("dbkey"),
stand_alone: false
},
latest_revision = viz.get("latest_revision"),
drawables = latest_revision.config.view.drawables;
container: parent_elt,
name: viz.get("title"),
id: viz.id,
// FIXME: this will not work with custom builds b/c the dbkey needed to be encoded.
dbkey: viz.get("dbkey"),
stand_alone: false
};
var latest_revision = viz.get("latest_revision");
var drawables = latest_revision.config.view.drawables;
// Set up datasets in drawables.
_.each(drawables, function(d) {
+6 -6
View File
@@ -111,8 +111,8 @@ var SessionStorageModel = Backbone.Model.extend({
/** set storage to the stringified item */
_create: function(model) {
try {
var json = model.toJSON(),
set = sessionStorage.setItem(model.id, JSON.stringify(json));
var json = model.toJSON();
var set = sessionStorage.setItem(model.id, JSON.stringify(json));
return set === null ? set : json;
// DOMException is thrown in Safari if in private browsing mode and sessionStorage is attempted:
// http://stackoverflow.com/questions/14555347
@@ -175,8 +175,8 @@ var SessionStorageModel = Backbone.Model.extend({
* NOTE: this does not combine any hashes (like events, etc.) and you're expected to handle that
*/
function mixin(mixinHash1, /* mixinHash2, etc: ... variadic */ propsHash) {
var args = Array.prototype.slice.call(arguments, 0),
lastArg = args.pop();
var args = Array.prototype.slice.call(arguments, 0);
var lastArg = args.pop();
args.unshift(lastArg);
return _.defaults.apply(_, args);
}
@@ -259,8 +259,8 @@ var SearchableModelMixin = {
* @returns {Boolean} was term found in (any) attribute(s)
*/
matches: function(term) {
var ATTR_SPECIFIER = "=",
split = term.split(ATTR_SPECIFIER);
var ATTR_SPECIFIER = "=";
var split = term.split(ATTR_SPECIFIER);
// attribute is specified - search only that
if (split.length >= 2) {
var attrKey = split[0];
@@ -4,8 +4,9 @@ import BASE_MVC from "mvc/base-mvc";
import _l from "utils/localization";
//==============================================================================
var FoldoutListItemView = LIST_ITEM.FoldoutListItemView,
ListItemView = LIST_ITEM.ListItemView;
var FoldoutListItemView = LIST_ITEM.FoldoutListItemView;
var ListItemView = LIST_ITEM.ListItemView;
/** @class Read only view for DatasetCollection.
*/
var DCListItemView = FoldoutListItemView.extend(
@@ -51,8 +51,9 @@ var CollectionViewEdit = _super.extend(
this.tagsEditorShown = true;
//TODO: extract
var panel = this,
nameSelector = "> .controls .name";
var panel = this;
var nameSelector = "> .controls .name";
$where
.find(nameSelector)
.attr("title", _l("Click to rename collection"))
@@ -72,8 +72,8 @@ var DatasetCollectionElementView = Backbone.View
/** animate the removal of this element and pub */
discard: function() {
var view = this,
parentWidth = this.$el.parent().width();
var view = this;
var parentWidth = this.$el.parent().width();
this.$el.animate(
{ "margin-right": parentWidth },
"fast",
@@ -113,18 +113,21 @@ var DatasetCollectionElementView = Backbone.View
_clickName: function(ev) {
ev.stopPropagation();
ev.preventDefault();
var promptString = [
_l("Enter a new name for the element"),
":\n(",
_l(
"Note that changing the name here will not rename the dataset"
),
")"
].join(""),
response = prompt(
_l("Enter a new name for the element") + ":",
this.element.name
);
_l("Enter a new name for the element"),
":\n(",
_l(
"Note that changing the name here will not rename the dataset"
),
")"
].join("");
var response = prompt(
_l("Enter a new name for the element") + ":",
this.element.name
);
if (response) {
this.element.name = response;
this.render();
@@ -266,8 +269,8 @@ var ListCollectionCreator = Backbone.View
/** separate working list into valid and invalid elements for this collection */
_validateElements: function() {
var creator = this,
existingNames = {};
var creator = this;
var existingNames = {};
creator.invalidElements = [];
this.workingElements = this.workingElements.filter(function(
@@ -304,9 +307,9 @@ var ListCollectionCreator = Backbone.View
/** mangle duplicate names using a mac-like '(counter)' addition to any duplicates */
_mangleDuplicateNames: function() {
var SAFETY = 900,
counter = 1,
existingNames = {};
var SAFETY = 900;
var counter = 1;
var existingNames = {};
this.workingElements.forEach(function(element) {
var currName = element.name;
while (existingNames.hasOwnProperty(currName)) {
@@ -439,9 +442,10 @@ var ListCollectionCreator = Backbone.View
/** render the elements in order (or a warning if no elements found) */
_renderList: function(speed, callback) {
//this.debug( '-- _renderList' );
var creator = this,
$tmp = jQuery("<div/>"),
$list = creator.$list();
var creator = this;
var $tmp = jQuery("<div/>");
var $list = creator.$list();
_.each(this.elementViews, function(view) {
view.destroy();
@@ -558,10 +562,11 @@ var ListCollectionCreator = Backbone.View
return;
}
var creator = this,
elements = this.workingElements.map(function(element) {
return creator._elementToJSON(element);
});
var creator = this;
var elements = this.workingElements.map(function(element) {
return creator._elementToJSON(element);
});
creator.blocking = true;
return creator
@@ -625,11 +630,11 @@ var ListCollectionCreator = Backbone.View
_errorHandler: function(data) {
this.error(data);
var creator = this,
content = data.message || _l("An error occurred");
var creator = this;
var content = data.message || _l("An error occurred");
if (data.xhr) {
var xhr = data.xhr,
message = data.message;
var xhr = data.xhr;
var message = data.message;
if (xhr.readyState === 0 && xhr.status === 0) {
content +=
": " +
@@ -727,11 +732,11 @@ var ListCollectionCreator = Backbone.View
/** If the mouse is near enough to the list's top or bottom, scroll the list */
_checkForAutoscroll: function($element, y) {
var AUTOSCROLL_SPEED = 2,
offset = $element.offset(),
scrollTop = $element.scrollTop(),
upperDist = y - offset.top,
lowerDist = offset.top + $element.outerHeight() - y;
var AUTOSCROLL_SPEED = 2;
var offset = $element.offset();
var scrollTop = $element.scrollTop();
var upperDist = y - offset.top;
var lowerDist = offset.top + $element.outerHeight() - y;
if (upperDist >= 0 && upperDist < this.autoscrollDist) {
$element.scrollTop(scrollTop - AUTOSCROLL_SPEED);
} else if (lowerDist >= 0 && lowerDist < this.autoscrollDist) {
@@ -743,14 +748,16 @@ var ListCollectionCreator = Backbone.View
* If the y is at the end of the list, return an empty jQuery object.
*/
_getNearestElement: function(y) {
var WIGGLE = 4,
lis = this.$(
".collection-elements li.collection-element"
).toArray();
var WIGGLE = 4;
var lis = this.$(
".collection-elements li.collection-element"
).toArray();
for (var i = 0; i < lis.length; i++) {
var $li = $(lis[i]),
top = $li.offset().top,
halfHeight = Math.floor($li.outerHeight() / 2) + WIGGLE;
var $li = $(lis[i]);
var top = $li.offset().top;
var halfHeight = Math.floor($li.outerHeight() / 2) + WIGGLE;
if (top + halfHeight > y && top - halfHeight < y) {
return $li;
}
@@ -784,14 +791,16 @@ var ListCollectionCreator = Backbone.View
/** resync the creator's list of elements based on the DOM order */
_syncOrderToDom: function() {
var creator = this,
newElements = [];
var creator = this;
var newElements = [];
//TODO: doesn't seem wise to use the dom to store these - can't we sync another way?
this.$(".collection-elements .collection-element").each(function() {
var id = $(this).attr("data-element-id"),
element = _.findWhere(creator.workingElements, {
id: id
});
var id = $(this).attr("data-element-id");
var element = _.findWhere(creator.workingElements, {
id: id
});
if (element) {
newElements.push(element);
} else {
@@ -1075,9 +1084,9 @@ var collectionCreatorModal = function _collectionCreatorModal(
options,
CreatorClass
) {
var deferred = jQuery.Deferred(),
modal = Galaxy.modal || new UI_MODAL.View(),
creator;
var deferred = jQuery.Deferred();
var modal = Galaxy.modal || new UI_MODAL.View();
var creator;
options = _.defaults(options || {}, {
elements: elements,
@@ -1121,29 +1130,26 @@ var listCollectionCreatorModal = function _listCollectionCreatorModal(
* @returns {Deferred} resolved when the collection is added to the history.
*/
function createListCollection(contents, defaultHideSourceItems) {
var elements = contents.toJSON(),
promise = listCollectionCreatorModal(elements, {
defaultHideSourceItems: defaultHideSourceItems,
creationFn: function(elements, name, hideSourceItems) {
elements = elements.map(function(element) {
return {
id: element.id,
name: element.name,
//TODO: this allows for list:list even if the filter above does not - reconcile
src:
element.history_content_type === "dataset"
? "hda"
: "hdca"
};
});
return contents.createHDCA(
elements,
"list",
name,
hideSourceItems
);
}
});
var elements = contents.toJSON();
var promise = listCollectionCreatorModal(elements, {
defaultHideSourceItems: defaultHideSourceItems,
creationFn: function(elements, name, hideSourceItems) {
elements = elements.map(function(element) {
return {
id: element.id,
name: element.name,
//TODO: this allows for list:list even if the filter above does not - reconcile
src:
element.history_content_type === "dataset"
? "hda"
: "hdca"
};
});
return contents.createHDCA(elements, "list", name, hideSourceItems);
}
});
return promise;
}
@@ -94,10 +94,10 @@ function autoPairFnBuilder(options) {
options.createPair ||
function _defaultCreatePair(params) {
params = params || {};
var a = params.listA.splice(params.indexA, 1)[0],
b = params.listB.splice(params.indexB, 1)[0],
aInBIndex = params.listB.indexOf(a),
bInAIndex = params.listA.indexOf(b);
var a = params.listA.splice(params.indexA, 1)[0];
var b = params.listB.splice(params.indexB, 1)[0];
var aInBIndex = params.listB.indexOf(a);
var bInAIndex = params.listA.indexOf(b);
if (aInBIndex !== -1) {
params.listB.splice(aInBIndex, 1);
}
@@ -131,15 +131,17 @@ function autoPairFnBuilder(options) {
return function _strategy(params) {
this.debug("autopair _strategy ---------------------------");
params = params || {};
var listA = params.listA,
listB = params.listB,
indexA = 0,
indexB,
bestMatch = {
score: 0.0,
index: null
},
paired = [];
var listA = params.listA;
var listB = params.listB;
var indexA = 0;
var indexB;
var bestMatch = {
score: 0.0,
index: null
};
var paired = [];
//console.debug( 'params:', JSON.stringify( params, null, ' ' ) );
this.debug("starting list lens:", listA.length, listB.length);
this.debug(
@@ -358,9 +360,10 @@ var PairedCollectionCreator = Backbone.View
/** split initial list into two lists, those that pass forward filters & those passing reverse */
_splitByFilters: function() {
var regexFilters = this.filters.map(function(stringFilter) {
return new RegExp(stringFilter);
}),
split = [[], []];
return new RegExp(stringFilter);
});
var split = [[], []];
function _filter(unpaired, filter) {
return filter.test(unpaired.name);
@@ -387,11 +390,12 @@ var PairedCollectionCreator = Backbone.View
return low;
}
var mid = Math.floor((hi - low) / 2) + low,
compared = naturalSort(
dataset.name,
this.unpaired[mid].name
);
var mid = Math.floor((hi - low) / 2) + low;
var compared = naturalSort(
dataset.name,
this.unpaired[mid].name
);
if (compared < 0) {
return binSearchSortedIndex(low, mid);
@@ -421,8 +425,9 @@ var PairedCollectionCreator = Backbone.View
*/
autoPair: function(strategy) {
// split first using exact matching
var split = this._splitByFilters(),
paired = [];
var split = this._splitByFilters();
var paired = [];
if (this.twoPassAutopairing) {
paired = this.autopairSimple({
listA: split[0],
@@ -470,17 +475,17 @@ var PairedCollectionCreator = Backbone.View
},
match: function _matches(params) {
params = params || {};
var distance = levenshteinDistance(
params.matchTo,
params.possible
),
score =
1.0 -
distance /
Math.max(
params.matchTo.length,
params.possible.length
);
params.matchTo,
params.possible
);
var score =
1.0 -
distance /
Math.max(params.matchTo.length, params.possible.length);
if (score > params.bestMatch.score) {
return {
index: params.index,
@@ -498,13 +503,16 @@ var PairedCollectionCreator = Backbone.View
},
match: function _matches(params) {
params = params || {};
var match = this._naiveStartingAndEndingLCS(
params.matchTo,
params.possible
).length,
score =
match /
Math.max(params.matchTo.length, params.possible.length);
params.matchTo,
params.possible
).length;
var score =
match /
Math.max(params.matchTo.length, params.possible.length);
if (score > params.bestMatch.score) {
return {
index: params.index,
@@ -517,10 +525,10 @@ var PairedCollectionCreator = Backbone.View
/** return the concat'd longest common prefix and suffix from two strings */
_naiveStartingAndEndingLCS: function(s1, s2) {
var fwdLCS = "",
revLCS = "",
i = 0,
j = 0;
var fwdLCS = "";
var revLCS = "";
var i = 0;
var j = 0;
while (i < s1.length && i < s2.length) {
if (s1[i] !== s2[i]) {
break;
@@ -580,12 +588,14 @@ var PairedCollectionCreator = Backbone.View
removeExtensions !== undefined
? removeExtensions
: this.removeExtensions;
var fwdName = fwd.name,
revName = rev.name,
lcs = this._naiveStartingAndEndingLCS(
fwdName.replace(new RegExp(this.filters[0]), ""),
revName.replace(new RegExp(this.filters[1]), "")
);
var fwdName = fwd.name;
var revName = rev.name;
var lcs = this._naiveStartingAndEndingLCS(
fwdName.replace(new RegExp(this.filters[0]), ""),
revName.replace(new RegExp(this.filters[1]), "")
);
if (removeExtensions) {
var lastDotIndex = lcs.lastIndexOf(".");
if (lastDotIndex > 0) {
@@ -651,12 +661,13 @@ var PairedCollectionCreator = Backbone.View
* @returns {jQuery.xhr Object} the jquery ajax request
*/
createList: function(name) {
var creator = this,
url =
Galaxy.root +
"api/histories/" +
this.historyId +
"/contents/dataset_collections";
var creator = this;
var url =
Galaxy.root +
"api/histories/" +
this.historyId +
"/contents/dataset_collections";
//TODO: use ListPairedCollection.create()
var ajaxData = {
@@ -779,11 +790,12 @@ var PairedCollectionCreator = Backbone.View
/** render the unpaired section, showing datasets accrd. to filters, update the unpaired counts */
_renderUnpaired: function(speed, callback) {
//this.debug( '-- _renderUnpaired' );
var creator = this,
$fwd,
$rev,
$prd = [],
split = this._splitByFilters();
var creator = this;
var $fwd;
var $rev;
var $prd = [];
var split = this._splitByFilters();
// update unpaired counts
this.$(".forward-column .title").text(
[split[0].length, _l("unpaired forward")].join(" ")
@@ -903,19 +915,23 @@ var PairedCollectionCreator = Backbone.View
},
/** try to detect if the unpaired section has a scrollbar and adjust left column for better centering of all */
_adjUnpairedOnScrollbar: function() {
var $unpairedColumns = this.$(".unpaired-columns").last(),
$firstDataset = this.$(
".unpaired-columns .reverse-column .dataset"
).first();
var $unpairedColumns = this.$(".unpaired-columns").last();
var $firstDataset = this.$(
".unpaired-columns .reverse-column .dataset"
).first();
if (!$firstDataset.length) {
return;
}
var ucRight =
$unpairedColumns.offset().left +
$unpairedColumns.outerWidth(),
dsRight =
$firstDataset.offset().left + $firstDataset.outerWidth(),
rightDiff = Math.floor(ucRight) - Math.floor(dsRight);
$unpairedColumns.offset().left + $unpairedColumns.outerWidth();
var dsRight =
$firstDataset.offset().left + $firstDataset.outerWidth();
var rightDiff = Math.floor(ucRight) - Math.floor(dsRight);
//this.debug( 'rightDiff:', ucRight, '-', dsRight, '=', rightDiff );
this.$(".unpaired-columns .forward-column").css(
"margin-left",
@@ -1092,8 +1108,8 @@ var PairedCollectionCreator = Backbone.View
this._renderUnpaired();
this._renderPaired();
var message,
msgClass = null;
var message;
var msgClass = null;
if (this.paired.length) {
msgClass = "alert-success";
message = this.paired.length + " " + _l("pairs created");
@@ -1274,11 +1290,13 @@ var PairedCollectionCreator = Backbone.View
*/
toggleSelectUnpaired: function($dataset, options) {
options = options || {};
var dataset = $dataset.data("dataset"),
select =
options.force !== undefined
? options.force
: !$dataset.hasClass("selected");
var dataset = $dataset.data("dataset");
var select =
options.force !== undefined
? options.force
: !$dataset.hasClass("selected");
//this.debug( id, options.force, $dataset, dataset );
if (!$dataset.length || dataset === undefined) {
return $dataset;
@@ -1299,10 +1317,10 @@ var PairedCollectionCreator = Backbone.View
/** pair all the currently selected unpaired datasets */
pairAllSelected: function(options) {
options = options || {};
var creator = this,
fwds = [],
revs = [],
pairs = [];
var creator = this;
var fwds = [];
var revs = [];
var pairs = [];
creator
.$(".unpaired-columns .forward-column .dataset.selected")
.each(function() {
@@ -1341,14 +1359,16 @@ var PairedCollectionCreator = Backbone.View
/** when holding down the shift key on a click, 'paint' the moused over datasets as selected */
_mousedownUnpaired: function(ev) {
if (ev.shiftKey) {
var creator = this,
$startTarget = $(ev.target).addClass("selected"),
moveListener = function(ev) {
creator
.$(ev.target)
.filter(".dataset")
.addClass("selected");
};
var creator = this;
var $startTarget = $(ev.target).addClass("selected");
var moveListener = function(ev) {
creator
.$(ev.target)
.filter(".dataset")
.addClass("selected");
};
$startTarget.parent().on("mousemove", moveListener);
// on any mouseup, stop listening to the move and try to pair any selected
@@ -1362,13 +1382,16 @@ var PairedCollectionCreator = Backbone.View
/** attempt to pair two datasets directly across from one another */
_clickPairRow: function(ev) {
//if( !ev.currentTarget ){ return true; }
var rowIndex = $(ev.currentTarget).index(),
fwd = $(".unpaired-columns .forward-column .dataset")
.eq(rowIndex)
.data("dataset"),
rev = $(".unpaired-columns .reverse-column .dataset")
.eq(rowIndex)
.data("dataset");
var rowIndex = $(ev.currentTarget).index();
var fwd = $(".unpaired-columns .forward-column .dataset")
.eq(rowIndex)
.data("dataset");
var rev = $(".unpaired-columns .reverse-column .dataset")
.eq(rowIndex)
.data("dataset");
//this.debug( 'row:', rowIndex, fwd, rev );
this._pair(fwd, rev);
},
@@ -1376,8 +1399,8 @@ var PairedCollectionCreator = Backbone.View
// ........................................................................ divider/partition
/** start dragging the visible divider/partition between unpaired and paired panes */
_startPartitionDrag: function(ev) {
var creator = this,
startingY = ev.pageY;
var creator = this;
var startingY = ev.pageY;
//this.debug( 'partition drag START:', ev );
$("body").css("cursor", "ns-resize");
creator.$(".flexible-partition-drag").css("color", "black");
@@ -1406,10 +1429,10 @@ var PairedCollectionCreator = Backbone.View
/** adjust the parition up/down +/-adj pixels */
adjPartition: function(adj) {
var $unpaired = this.$(".unpaired-columns"),
$paired = this.$(".paired-columns"),
unpairedHi = parseInt($unpaired.css("height"), 10),
pairedHi = parseInt($paired.css("height"), 10);
var $unpaired = this.$(".unpaired-columns");
var $paired = this.$(".paired-columns");
var unpairedHi = parseInt($unpaired.css("height"), 10);
var pairedHi = parseInt($paired.css("height"), 10);
//this.debug( adj, 'hi\'s:', unpairedHi, pairedHi, unpairedHi + adj, pairedHi - adj );
unpairedHi = Math.max(10, unpairedHi + adj);
@@ -1468,11 +1491,11 @@ var PairedCollectionCreator = Backbone.View
/** rename a pair when the pair name is clicked */
_clickPairName: function(ev) {
ev.stopPropagation();
var $name = $(ev.currentTarget),
$pair = $name.parent().parent(),
index = $pair.index(".dataset.paired"),
pair = this.paired[index],
response = prompt("Enter a new name for the pair:", pair.name);
var $name = $(ev.currentTarget);
var $pair = $name.parent().parent();
var index = $pair.index(".dataset.paired");
var pair = this.paired[index];
var response = prompt("Enter a new name for the pair:", pair.name);
if (response) {
pair.name = response;
// set a flag (which won't be passed in json creation) for manual naming so we don't overwrite these
@@ -1526,10 +1549,10 @@ var PairedCollectionCreator = Backbone.View
/** If the mouse is near enough to the list's top or bottom, scroll the list */
_checkForAutoscroll: function($element, y) {
var AUTOSCROLL_SPEED = 2;
var offset = $element.offset(),
scrollTop = $element.scrollTop(),
upperDist = y - offset.top,
lowerDist = offset.top + $element.outerHeight() - y;
var offset = $element.offset();
var scrollTop = $element.scrollTop();
var upperDist = y - offset.top;
var lowerDist = offset.top + $element.outerHeight() - y;
//this.debug( '_checkForAutoscroll:', scrollTop, upperDist, lowerDist );
if (upperDist >= 0 && upperDist < this.autoscrollDist) {
$element.scrollTop(scrollTop - AUTOSCROLL_SPEED);
@@ -1542,12 +1565,12 @@ var PairedCollectionCreator = Backbone.View
* If the y is at the end of the list, return an empty jQuery object.
*/
_getNearestPairedDatasetLi: function(y) {
var WIGGLE = 4,
lis = this.$(".paired-columns .column-datasets li").toArray();
var WIGGLE = 4;
var lis = this.$(".paired-columns .column-datasets li").toArray();
for (var i = 0; i < lis.length; i++) {
var $li = $(lis[i]),
top = $li.offset().top,
halfHeight = Math.floor($li.outerHeight() / 2) + WIGGLE;
var $li = $(lis[i]);
var top = $li.offset().top;
var halfHeight = Math.floor($li.outerHeight() / 2) + WIGGLE;
if (top + halfHeight > y && top - halfHeight < y) {
//this.debug( y, top + halfHeight, top - halfHeight )
return $li;
@@ -1907,8 +1930,8 @@ var pairedCollectionCreatorModal = function _pairedCollectionCreatorModal(
datasets,
options
) {
var deferred = jQuery.Deferred(),
creator;
var deferred = jQuery.Deferred();
var creator;
options = _.defaults(options || {}, {
datasets: datasets,
@@ -88,9 +88,10 @@ var PairCollectionCreator = _super.extend({
_renderList: function(speed, callback) {
//this.debug( '-- _renderList' );
//precondition: there are two valid elements in workingElements
var creator = this,
$tmp = jQuery("<div/>"),
$list = creator.$list();
var creator = this;
var $tmp = jQuery("<div/>");
var $list = creator.$list();
// lose the original views, create the new, append all at once, then call their renders
_.each(this.elementViews, function(view) {
@@ -279,22 +280,24 @@ var pairCollectionCreatorModal = function _pairCollectionCreatorModal(
* @returns {Deferred} resolved when the collection is added to the history.
*/
function createPairCollection(contents, defaultHideSourceItems) {
var elements = contents.toJSON(),
promise = pairCollectionCreatorModal(elements, {
defaultHideSourceItems: defaultHideSourceItems,
creationFn: function(elements, name, hideSourceItems) {
elements = [
{ name: "forward", src: "hda", id: elements[0].id },
{ name: "reverse", src: "hda", id: elements[1].id }
];
return contents.createHDCA(
elements,
"paired",
name,
hideSourceItems
);
}
});
var elements = contents.toJSON();
var promise = pairCollectionCreatorModal(elements, {
defaultHideSourceItems: defaultHideSourceItems,
creationFn: function(elements, name, hideSourceItems) {
elements = [
{ name: "forward", src: "hda", id: elements[0].id },
{ name: "reverse", src: "hda", id: elements[1].id }
];
return contents.createHDCA(
elements,
"paired",
name,
hideSourceItems
);
}
});
return promise;
}
+13 -10
View File
@@ -95,8 +95,9 @@ var TabularDataset = Dataset.extend({
}
// Get next chunk.
var self = this,
next_chunk = $.Deferred();
var self = this;
var next_chunk = $.Deferred();
$.getJSON(this.attributes.chunk_url, {
offset: self.attributes.offset
}).success(function(chunk) {
@@ -175,9 +176,9 @@ var TabularDatasetChunkedView = Backbone.View.extend({
cellpadding: 0
});
this.$el.append(data_table);
var column_names = this.model.get_metadata("column_names"),
header_container = $("<thead/>").appendTo(data_table),
header_row = $("<tr/>").appendTo(header_container);
var column_names = this.model.get_metadata("column_names");
var header_container = $("<thead/>").appendTo(data_table);
var header_row = $("<tr/>").appendTo(header_container);
if (column_names) {
header_row.append(
"<th>" + column_names.join("</th><th>") + "</th>"
@@ -189,8 +190,9 @@ var TabularDatasetChunkedView = Backbone.View.extend({
}
// Render first chunk.
var self = this,
first_chunk = this.model.get("first_data_chunk");
var self = this;
var first_chunk = this.model.get("first_data_chunk");
if (first_chunk) {
// First chunk is bootstrapped, so render now.
this._renderChunk(first_chunk);
@@ -239,9 +241,10 @@ var TabularDatasetChunkedView = Backbone.View.extend({
_renderRow: function(line) {
// Check length of cells to ensure this is a complete row.
var cells = line.split("\t"),
row = $("<tr>"),
num_columns = this.model.get_metadata("columns");
var cells = line.split("\t");
var row = $("<tr>");
var num_columns = this.model.get_metadata("columns");
if (this.row_count % 2 !== 0) {
row.addClass("dark_row");
@@ -100,11 +100,11 @@ var DatasetChoiceModal = function(datasetJSON, options) {
? _l("Choose datasets:")
: _l("Choose a dataset:"));
var modal,
list,
buttons,
promise = jQuery.Deferred(),
filterFn = options.filter || _filterDatasetJSON;
var modal;
var list;
var buttons;
var promise = jQuery.Deferred();
var filterFn = options.filter || _filterDatasetJSON;
// filter the given datasets and if none left return a rejected promise for use with fail()
datasetJSON = filterFn(datasetJSON, options.where, options.datasetsOnly);
@@ -14,8 +14,9 @@ var View = Backbone.View.extend({
// Fetch data for the selected dataset and
render: function() {
var data_url =
Galaxy.root + "api/datasets/" + this.model.get("dataset_id"),
self = this;
Galaxy.root + "api/datasets/" + this.model.get("dataset_id");
var self = this;
Utils.get({
url: data_url,
@@ -54,25 +54,27 @@ var DatasetListItemEdit = _super.extend(
) {
return null;
}
var purged = this.model.get("purged"),
deleted = this.model.get("deleted"),
editBtnData = {
title: _l("Edit attributes"),
href:
Galaxy.root +
"datasets/edit?dataset_id=" +
this.model.attributes.id,
faIcon: "fa-pencil",
classes: "edit-btn",
onclick: function(ev) {
if (Galaxy.router) {
ev.preventDefault();
Galaxy.router.push("datasets/edit", {
dataset_id: self.model.attributes.id
});
}
var purged = this.model.get("purged");
var deleted = this.model.get("deleted");
var editBtnData = {
title: _l("Edit attributes"),
href:
Galaxy.root +
"datasets/edit?dataset_id=" +
this.model.attributes.id,
faIcon: "fa-pencil",
classes: "edit-btn",
onclick: function(ev) {
if (Galaxy.router) {
ev.preventDefault();
Galaxy.router.push("datasets/edit", {
dataset_id: self.model.attributes.id
});
}
};
}
};
// disable if purged or deleted and explain why in the tooltip
if (deleted || purged) {
editBtnData.disabled = true;
@@ -103,8 +105,8 @@ var DatasetListItemEdit = _super.extend(
return null;
}
var self = this,
deletedAlready = this.model.isDeletedOrPurged();
var self = this;
var deletedAlready = this.model.isDeletedOrPurged();
return faIconButton({
title: !deletedAlready
? _l("Delete")
@@ -124,8 +126,9 @@ var DatasetListItemEdit = _super.extend(
/** In this override, add tags and annotations controls, make the ? dbkey a link to editing page */
_renderDetails: function() {
//TODO: generalize to be allow different details for each state
var $details = _super.prototype._renderDetails.call(this),
state = this.model.get("state");
var $details = _super.prototype._renderDetails.call(this);
var state = this.model.get("state");
if (
!this.model.isDeletedOrPurged() &&
@@ -215,8 +215,8 @@ var DatasetListItemView = _super.extend(
/** Defer to the appropo summary rendering fn based on state */
_renderSummary: function() {
var json = this.model.toJSON(),
summaryRenderFn = this.templates.summaries[json.state];
var json = this.model.toJSON();
var summaryRenderFn = this.templates.summaries[json.state];
summaryRenderFn =
summaryRenderFn || this.templates.summaries.unknown;
return summaryRenderFn(json, this);
@@ -224,9 +224,9 @@ var DatasetListItemView = _super.extend(
/** Render messages to be displayed only when the details are shown */
_renderDetailMessages: function() {
var view = this,
$warnings = $('<div class="detail-messages"></div>'),
json = view.model.toJSON();
var view = this;
var $warnings = $('<div class="detail-messages"></div>');
var json = view.model.toJSON();
//TODO:! unordered (map)
_.each(view.templates.detailMessages, function(templateFn) {
$warnings.append($(templateFn(json, view)));
@@ -211,8 +211,9 @@ var DatasetAssociation = Backbone.Model.extend(BASE_MVC.LoggableMixin).extend(
//TODO: ideally this would be a DELETE call to the api
// using purge async for now
var hda = this,
xhr = jQuery.ajax(options);
var hda = this;
var xhr = jQuery.ajax(options);
xhr.done(function(message, status, responseObj) {
hda.set({ deleted: true, purged: true });
});
@@ -327,9 +328,9 @@ var DatasetAssociationCollection = Backbone.Collection
// ........................................................................ ajax
/** using a queue, perform ajaxFn on each of the models in this collection */
ajaxQueue: function(ajaxFn, options) {
var deferred = jQuery.Deferred(),
startingLength = this.length,
responses = [];
var deferred = jQuery.Deferred();
var startingLength = this.length;
var responses = [];
if (!startingLength) {
deferred.resolve([]);
+3 -2
View File
@@ -31,8 +31,9 @@ export default Backbone.Model.extend({
// Update URL arg with new condition.
if (append) {
// Update or append value.
var cur_val = this.attributes.filters[key],
new_val;
var cur_val = this.attributes.filters[key];
var new_val;
if (cur_val === null || cur_val === undefined) {
new_val = value;
} else if (typeof cur_val == "string") {
+10 -6
View File
@@ -378,8 +378,9 @@ export default Backbone.View.extend({
// Set new value for categorical filter.
set_categorical_filter: function(name, new_value) {
// Update filter hyperlinks to reflect new filter value.
var category_filter = this.grid.get("categorical_filters")[name],
cur_value = this.grid.get("filters")[name];
var category_filter = this.grid.get("categorical_filters")[name];
var cur_value = this.grid.get("filters")[name];
var self = this;
this.$el.find("." + name + "-filter").each(function() {
var text = $.trim($(this).text());
@@ -415,10 +416,13 @@ export default Backbone.View.extend({
// Update page hyperlink to reflect new page.
var self = this;
this.$el.find(".page-link").each(function() {
var id = $(this).attr("id"),
page_num = parseInt(id.split("-")[2], 10), // Id has form 'page-link-<page_num>
cur_page = self.grid.get("cur_page"),
text;
var id = $(this).attr("id");
var // Id has form 'page-link-<page_num>
page_num = parseInt(id.split("-")[2], 10);
var cur_page = self.grid.get("cur_page");
var text;
if (page_num === new_page) {
// Remove link to page since grid will be on this page. It is assumed that
// this element has a single child, a hyperlink/anchor with text.
@@ -89,23 +89,26 @@ var CopyDialog = {
dialog: function _dialog(modal, history, options) {
options = options || {};
var dialog = this,
deferred = jQuery.Deferred(),
// TODO: getting a little byzantine here
defaultCopyNameFn = options.nameFn || this.defaultName,
defaultCopyName = defaultCopyNameFn({
name: history.get("name")
}),
// TODO: these two might be simpler as one 3 state option (all,active,no-choice)
defaultCopyWhat = options.allDatasets
? "copy-all"
: "copy-non-deleted",
allowAll = !_.isUndefined(options.allowAll)
? options.allowAll
: true,
autoClose = !_.isUndefined(options.autoClose)
? options.autoClose
: true;
var dialog = this;
var deferred = jQuery.Deferred();
var // TODO: getting a little byzantine here
defaultCopyNameFn = options.nameFn || this.defaultName;
var defaultCopyName = defaultCopyNameFn({
name: history.get("name")
});
var // TODO: these two might be simpler as one 3 state option (all,active,no-choice)
defaultCopyWhat = options.allDatasets ? "copy-all" : "copy-non-deleted";
var allowAll = !_.isUndefined(options.allowAll)
? options.allowAll
: true;
var autoClose = !_.isUndefined(options.autoClose)
? options.autoClose
: true;
this.modal = modal;
@@ -4,8 +4,9 @@ import BASE_MVC from "mvc/base-mvc";
import _l from "utils/localization";
//==============================================================================
var _super = DATASET.DatasetAssociation,
hcontentMixin = HISTORY_CONTENT.HistoryContentMixin;
var _super = DATASET.DatasetAssociation;
var hcontentMixin = HISTORY_CONTENT.HistoryContentMixin;
/** @class (HDA) model for a Galaxy dataset contained in and related to a history.
*/
var HistoryDatasetAssociation = _super.extend(
@@ -41,8 +41,8 @@ var HDCAListItemEdit = _super.extend(
/** Render icon-button to delete this collection. */
_renderDeleteButton: function() {
var self = this,
deleted = this.model.get("deleted");
var self = this;
var deleted = this.model.get("deleted");
return faIconButton({
title: deleted
? _l("Dataset collection is already deleted")
@@ -11,11 +11,12 @@ TODO:
collection-model is used.
==============================================================================*/
var hcontentMixin = HISTORY_CONTENT.HistoryContentMixin,
ListDC = DC_MODEL.ListDatasetCollection,
PairDC = DC_MODEL.PairDatasetCollection,
ListPairedDC = DC_MODEL.ListPairedDatasetCollection,
ListOfListsDC = DC_MODEL.ListOfListsDatasetCollection;
var hcontentMixin = HISTORY_CONTENT.HistoryContentMixin;
var ListDC = DC_MODEL.ListDatasetCollection;
var PairDC = DC_MODEL.PairDatasetCollection;
var ListPairedDC = DC_MODEL.ListPairedDatasetCollection;
var ListOfListsDC = DC_MODEL.ListOfListsDatasetCollection;
//==============================================================================
/** Override to post to contents route w/o id. */
@@ -432,7 +432,10 @@ var HistoryContents = _super.extend(BASE_MVC.LoggableMixin).extend({
/** copy an existing, accessible hda into this collection */
copy: function(json) {
// TODO: somehow showhorn all this into 'save'
var id, type, contentType;
var id;
var type;
var contentType;
if (_.isString(json)) {
id = json;
contentType = "hda";
@@ -447,30 +450,32 @@ var HistoryContents = _super.extend(BASE_MVC.LoggableMixin).extend({
}[json.model_class] || "hda";
type = contentType === "hdca" ? "dataset_collection" : "dataset";
}
var collection = this,
xhr = jQuery
.ajax(this.url(), {
method: "POST",
contentType: "application/json",
data: JSON.stringify({
content: id,
source: contentType,
type: type
})
var collection = this;
var xhr = jQuery
.ajax(this.url(), {
method: "POST",
contentType: "application/json",
data: JSON.stringify({
content: id,
source: contentType,
type: type
})
.done(function(response) {
collection.add([response], { parse: true });
})
.fail(function(error, status, message) {
collection.trigger(
"error",
collection,
xhr,
{},
"Error copying contents",
{ type: type, id: id, source: contentType }
);
});
})
.done(function(response) {
collection.add([response], { parse: true });
})
.fail(function(error, status, message) {
collection.trigger(
"error",
collection,
xhr,
{},
"Error copying contents",
{ type: type, id: id, source: contentType }
);
});
return xhr;
},
@@ -372,10 +372,11 @@ var History = Backbone.Model.extend(BASE_MVC.LoggableMixin).extend(
},
setAsCurrent: function() {
var history = this,
xhr = jQuery.getJSON(
Galaxy.root + "history/set_as_current?id=" + this.id
);
var history = this;
var xhr = jQuery.getJSON(
Galaxy.root + "history/set_as_current?id=" + this.id
);
xhr.done(function() {
history.trigger("set-as-current", history);
@@ -546,8 +547,9 @@ var HistoryCollection = _collectionSuper.extend(BASE_MVC.LoggableMixin).extend({
/** create a new history and by default set it to be the current history */
create: function create(data, hdas, historyOptions, xhrOptions) {
//TODO: .create is actually a collection function that's overridden here
var collection = this,
xhr = jQuery.getJSON(Galaxy.root + "history/create_new_current");
var collection = this;
var xhr = jQuery.getJSON(Galaxy.root + "history/create_new_current");
return xhr.done(function(newData) {
collection.setCurrent(
new History(newData, [], historyOptions || {})
@@ -126,8 +126,9 @@ var HistoryStructureComponent = Backbone.View
var view = this;
view.component.eachVertex(function(vertex) {
//TODO: hack
var type = vertex.data.job ? "job" : "copy",
li;
var type = vertex.data.job ? "job" : "copy";
var li;
if (type === "job") {
li = view._createJobListItem(vertex);
} else if (type === "copy") {
@@ -140,9 +141,9 @@ var HistoryStructureComponent = Backbone.View
_createJobListItem: function(vertex) {
this.debug("_createJobListItem:", vertex);
var view = this,
jobData = vertex.data,
job = new JOB.Job(jobData.job);
var view = this;
var jobData = vertex.data;
var job = new JOB.Job(jobData.job);
// get the models of the outputs for this job from the history
var outputModels = _.map(job.get("outputs"), function(output) {
@@ -201,13 +202,14 @@ var HistoryStructureComponent = Backbone.View
_createLayout: function(options) {
options = _.defaults(_.clone(options || {}), this.layoutDefaults);
var view = this,
vertices = _.values(view.component.vertices),
layout = _.extend(options, {
nodeMap: {},
links: [],
svg: { width: 0, height: 0 }
});
var view = this;
var vertices = _.values(view.component.vertices);
var layout = _.extend(options, {
nodeMap: {},
links: [],
svg: { width: 0, height: 0 }
});
vertices.forEach(function(v, j) {
var node = { name: v.name, x: 0, y: 0 };
@@ -280,8 +282,9 @@ var HistoryStructureComponent = Backbone.View
// position the job views accrd. to the layout
view.component.eachVertex(function(v) {
//TODO:?? liMap needed - can't we attach to vertex?
var li = view._liMap[v.name],
position = view.layout.nodeMap[v.name];
var li = view._liMap[v.name];
var position = view.layout.nodeMap[v.name];
//this.debug( position );
li.$el.css({ top: position.y, left: position.x });
});
@@ -297,8 +300,8 @@ var HistoryStructureComponent = Backbone.View
_updateLayout: function() {
this.debug(this + "._updateLayout:");
var view = this,
layout = view.layout;
var view = this;
var layout = view.layout;
layout.linkHeight = layout.linkSpacing * _.size(layout.nodeMap);
layout.svg.height = layout.linkHeight + layout.jobHeight;
@@ -308,8 +311,9 @@ var HistoryStructureComponent = Backbone.View
//TODO:?? can't we just alter the component v and e's directly?
// layout the job views putting jobSpacing btwn each
var x = 0,
y = layout.linkHeight;
var x = 0;
var y = layout.linkHeight;
_.each(layout.nodeMap, function(node, jobId) {
//this.debug( node, jobId );
node.x = x;
@@ -321,8 +325,8 @@ var HistoryStructureComponent = Backbone.View
// layout the links - connecting each job by it's main coords (currently)
//TODO: somehow adjust the svg height based on the largest distance the longest connection needs
layout.links.forEach(function(link) {
var source = layout.nodeMap[link.source],
target = layout.nodeMap[link.target];
var source = layout.nodeMap[link.source];
var target = layout.nodeMap[link.target];
link.x1 = source.x + layout.linkAdjX;
link.y1 = source.y + layout.linkAdjY;
link.x2 = target.x + layout.linkAdjX;
@@ -335,8 +339,8 @@ var HistoryStructureComponent = Backbone.View
renderSVG: function() {
this.debug(this + ".renderSVG:");
var view = this,
layout = view.layout;
var view = this;
var layout = view.layout;
var svg = d3.select(this.$graph().get(0)).select("svg");
if (svg.empty()) {
@@ -379,11 +383,11 @@ var HistoryStructureComponent = Backbone.View
},
_connectionPath: function(d) {
var CURVE_X = 0,
controlY =
(d.x2 - d.x1) /
this.layout.svg.width *
this.layout.linkHeight;
var CURVE_X = 0;
var controlY =
(d.x2 - d.x1) / this.layout.svg.width * this.layout.linkHeight;
return [
"M",
d.x1,
@@ -418,23 +422,26 @@ var HistoryStructureComponent = Backbone.View
this.debug("highlightConnected", jobElement, highlight);
highlight = highlight !== undefined ? highlight : true;
var view = this,
component = view.component,
jobClassFn = highlight
? jQuery.prototype.addClass
: jQuery.prototype.removeClass,
connectionClass = highlight
? "connection highlighted"
: "connection";
var view = this;
var component = view.component;
var jobClassFn = highlight
? jQuery.prototype.addClass
: jQuery.prototype.removeClass;
var connectionClass = highlight
? "connection highlighted"
: "connection";
//console.debug( 'mouseover', this );
var $hoverTarget = jobClassFn.call($(jobElement), "highlighted"),
id = $hoverTarget.data(view._VERTEX_NAME_DATA_KEY);
var $hoverTarget = jobClassFn.call($(jobElement), "highlighted");
var id = $hoverTarget.data(view._VERTEX_NAME_DATA_KEY);
// immed. ancestors
component.edges({ target: id }).forEach(function(edge) {
var ancestorId = edge.source,
ancestorLi = view._liMap[ancestorId];
var ancestorId = edge.source;
var ancestorLi = view._liMap[ancestorId];
//view.debug( '\t ancestor:', ancestorId, ancestorLi );
jobClassFn.call(ancestorLi.$el, "highlighted");
view
@@ -443,8 +450,8 @@ var HistoryStructureComponent = Backbone.View
});
// descendants
component.vertices[id].eachEdge(function(edge) {
var descendantId = edge.target,
descendantLi = view._liMap[descendantId];
var descendantId = edge.target;
var descendantLi = view._liMap[descendantId];
//view.debug( '\t descendant:', descendantId, descendantLi );
jobClassFn.call(descendantLi.$el, "highlighted");
view
@@ -486,8 +493,8 @@ var VerticalHistoryStructureComponent = HistoryStructureComponent.extend({
//TODO: how can we use the dom height of the job li's - they're not visible when this is called?
_updateLayout: function() {
this.debug(this + "._updateLayout:");
var view = this,
layout = view.layout;
var view = this;
var layout = view.layout;
//this.info( this.cid, '_updateLayout' )
layout.linkWidth = layout.linkSpacing * _.size(layout.nodeMap);
@@ -497,8 +504,9 @@ var VerticalHistoryStructureComponent = HistoryStructureComponent.extend({
layout.svg.height = 0;
//TODO:?? can't we just alter the component v and e's directly?
var x = layout.linkWidth,
y = 0;
var x = layout.linkWidth;
var y = 0;
_.each(layout.nodeMap, function(node, nodeId) {
node.x = x;
node.y = y;
@@ -509,8 +517,8 @@ var VerticalHistoryStructureComponent = HistoryStructureComponent.extend({
// layout the links - connecting each job by it's main coords (currently)
layout.links.forEach(function(link) {
var source = layout.nodeMap[link.source],
target = layout.nodeMap[link.target];
var source = layout.nodeMap[link.source];
var target = layout.nodeMap[link.target];
link.x1 = source.x + layout.linkAdjX;
link.y1 = source.y + layout.linkAdjY;
link.x2 = target.x + layout.linkAdjX;
@@ -523,9 +531,11 @@ var VerticalHistoryStructureComponent = HistoryStructureComponent.extend({
},
_connectionPath: function(d) {
var CURVE_Y = 0,
controlX =
(d.y2 - d.y1) / this.layout.svg.height * this.layout.linkWidth;
var CURVE_Y = 0;
var controlX =
(d.y2 - d.y1) / this.layout.svg.height * this.layout.linkWidth;
return [
"M",
d.x1,
@@ -229,8 +229,8 @@ var HistoryViewEdit = _super.extend(
return;
}
var panel = this,
nameSelector = "> .controls .name";
var panel = this;
var nameSelector = "> .controls .name";
$where
.find(nameSelector)
.attr("title", _l("Click to rename history"))
@@ -258,46 +258,47 @@ var HistoryViewEdit = _super.extend(
* ajax calls made for multiple datasets are queued
*/
multiselectActions: function() {
var panel = this,
actions = [
{
html: _l("Hide datasets"),
func: function() {
var action =
HDA_MODEL.HistoryDatasetAssociation.prototype
.hide;
panel.getSelectedModels().ajaxQueue(action);
}
},
{
html: _l("Unhide datasets"),
func: function() {
var action =
HDA_MODEL.HistoryDatasetAssociation.prototype
.unhide;
panel.getSelectedModels().ajaxQueue(action);
}
},
{
html: _l("Delete datasets"),
func: function() {
var action =
HDA_MODEL.HistoryDatasetAssociation.prototype[
"delete"
];
panel.getSelectedModels().ajaxQueue(action);
}
},
{
html: _l("Undelete datasets"),
func: function() {
var action =
HDA_MODEL.HistoryDatasetAssociation.prototype
.undelete;
panel.getSelectedModels().ajaxQueue(action);
}
var panel = this;
var actions = [
{
html: _l("Hide datasets"),
func: function() {
var action =
HDA_MODEL.HistoryDatasetAssociation.prototype.hide;
panel.getSelectedModels().ajaxQueue(action);
}
];
},
{
html: _l("Unhide datasets"),
func: function() {
var action =
HDA_MODEL.HistoryDatasetAssociation.prototype
.unhide;
panel.getSelectedModels().ajaxQueue(action);
}
},
{
html: _l("Delete datasets"),
func: function() {
var action =
HDA_MODEL.HistoryDatasetAssociation.prototype[
"delete"
];
panel.getSelectedModels().ajaxQueue(action);
}
},
{
html: _l("Undelete datasets"),
func: function() {
var action =
HDA_MODEL.HistoryDatasetAssociation.prototype
.undelete;
panel.getSelectedModels().ajaxQueue(action);
}
}
];
if (panel.purgeAllowed) {
actions.push({
html: _l("Permanently delete datasets"),
+21 -17
View File
@@ -59,8 +59,8 @@ JobDAG.prototype.init = function _init(options) {
/** add job filters based on options */
JobDAG.prototype._initFilters = function __initFilters() {
var self = this,
filters = [];
var self = this;
var filters = [];
if (self.options.excludeSetMetadata) {
self.filteredSetMetadata = [];
@@ -173,8 +173,9 @@ JobDAG.prototype.sort = function _sort(jobs) {
/** decorate with input/output datasets and tool */
JobDAG.prototype.preprocessJob = function _preprocessJob(job, index) {
//this.info( 'preprocessJob', job, index );
var self = this,
jobData = { job: job };
var self = this;
var jobData = { job: job };
jobData.inputs = self._processInputs(job);
if (_.size(jobData.inputs) === 0) {
@@ -194,9 +195,9 @@ JobDAG.prototype.preprocessJob = function _preprocessJob(job, index) {
/**
*/
JobDAG.prototype._processInputs = function __processInputs(job) {
var self = this,
inputs = job.inputs,
inputMap = {};
var self = this;
var inputs = job.inputs;
var inputMap = {};
_.each(inputs, function(input, nameInJob) {
input = _.clone(self._validateInputOutput(input));
input.name = nameInJob;
@@ -233,9 +234,9 @@ JobDAG.prototype._validateInputOutput = function __validateInputOutput(
/**
*/
JobDAG.prototype._processOutputs = function __processOutputs(job) {
var self = this,
outputs = job.outputs,
outputMap = {};
var self = this;
var outputs = job.outputs;
var outputMap = {};
_.each(outputs, function(output, nameInJob) {
output = _.clone(self._validateInputOutput(output));
output.name = nameInJob;
@@ -321,8 +322,9 @@ JobDAG.prototype.createJobLessVertex = function _createJobLessVertex(
) {
// currently, copied contents are the only history contents without jobs (that I know of)
//note: following needed to prevent id collision btwn content and jobs in vertex map
var JOBLESS_ID_MANGLER = "copy-",
mangledId = JOBLESS_ID_MANGLER + contentId;
var JOBLESS_ID_MANGLER = "copy-";
var mangledId = JOBLESS_ID_MANGLER + contentId;
return this.createVertex(mangledId, this._historyContentsMap[contentId]);
};
@@ -335,11 +337,13 @@ JobDAG.prototype.weakComponentGraphArray = function() {
// since update_time for jobless/copied datasets is changes more often
component.vertices.sort(function cmpCreate(a, b) {
var aCreateTime = a.data.job
? a.data.job.create_time
: a.data.create_time,
bCreateTime = b.data.job
? b.data.job.create_time
: b.data.create_time;
? a.data.job.create_time
: a.data.create_time;
var bCreateTime = b.data.job
? b.data.job.create_time
: b.data.create_time;
if (aCreateTime > bCreateTime) {
return 1;
}
@@ -88,8 +88,8 @@ var HistoryViewColumn = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** do the dimensions of this column overlap the given (horizontal) browser coords? */
inView: function(viewLeft, viewRight) {
var columnLeft = this.$el.offset().left,
columnRight = columnLeft + this.$el.width();
var columnLeft = this.$el.offset().left;
var columnRight = columnLeft + this.$el.width();
if (columnRight < viewLeft) {
return false;
}
@@ -429,8 +429,8 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
this.collection.includeDeleted,
history
);
var multipanel = this,
column = multipanel.columnMap[history.id];
var multipanel = this;
var column = multipanel.columnMap[history.id];
if (!column) {
return;
}
@@ -538,8 +538,9 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** add a new column for history and make it the current history/column */
addAsCurrentColumn: function add(history, collection, options) {
//this.log( 'adding current column for:', history );
var multipanel = this,
newColumn = this.addColumn(history, false);
var multipanel = this;
var newColumn = this.addColumn(history, false);
this.setCurrentHistory(history);
newColumn.once("rendered", function() {
multipanel.queueHdaFetch(newColumn);
@@ -554,8 +555,8 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
if (!column) {
return;
}
var multipanel = this,
widthToRemove = this.options.columnWidth + this.options.columnGap;
var multipanel = this;
var widthToRemove = this.options.columnWidth + this.options.columnGap;
column.$el.fadeOut("fast", function() {
if (render) {
$(this).remove();
@@ -863,9 +864,9 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** change the collection order and re-fetch when the drop down in the options menu is changed */
_chooseOrder: function(ev) {
var multipanel = this,
collection = multipanel.collection,
orderKey = $(ev.currentTarget).data("order");
var multipanel = this;
var collection = multipanel.collection;
var orderKey = $(ev.currentTarget).data("order");
// set the sort order text also
multipanel
.$(".current-order")
@@ -1010,9 +1011,9 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** Adjust the height of the first, current column since flex-boxes won't work with fixed postiion elements */
_recalcFirstColumnHeight: function() {
var $firstColumn = this.$(".history-column").first(),
middleHeight = this.$(".middle").height(),
controlHeight = $firstColumn.find(".panel-controls").height();
var $firstColumn = this.$(".history-column").first();
var middleHeight = this.$(".middle").height();
var controlHeight = $firstColumn.find(".panel-controls").height();
$firstColumn
.height(middleHeight)
.find(".inner")
@@ -1021,9 +1022,9 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** Get the left and right pixel coords of the middle element */
_viewport: function() {
var $outerMiddle = this.$(".middle").parent(),
viewLeft = $outerMiddle.offset().left,
width = $outerMiddle.width();
var $outerMiddle = this.$(".middle").parent();
var viewLeft = $outerMiddle.offset().left;
var width = $outerMiddle.width();
return {
left: viewLeft,
right: viewLeft + width
@@ -1052,9 +1053,9 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** is the middle, horizontally scrolling section scrolled fully to the right? */
checkForEndOfScroll: function(viewport) {
viewport = viewport || this._viewport();
var END_PADDING = 16,
$middle = this.$(".middle"),
scrollRight = $middle.parent().scrollLeft() + viewport.right;
var END_PADDING = 16;
var $middle = this.$(".middle");
var scrollRight = $middle.parent().scrollLeft() + viewport.right;
if (scrollRight >= $middle.width() - END_PADDING) {
this.trigger("end-of-scroll");
}
@@ -254,9 +254,9 @@ function buildMenu(isAnon, purgeAllowed, urlRoot) {
var create = function($button, options) {
options = options || {};
var isAnon = options.anonymous === undefined ? true : options.anonymous,
purgeAllowed = options.purgeAllowed || false,
menu = buildMenu(isAnon, purgeAllowed, Galaxy.root);
var isAnon = options.anonymous === undefined ? true : options.anonymous;
var purgeAllowed = options.purgeAllowed || false;
var menu = buildMenu(isAnon, purgeAllowed, Galaxy.root);
//console.debug( 'menu:', menu );
return new PopupMenu($button, menu);
};
+9 -6
View File
@@ -59,8 +59,9 @@ var JobListItemView = _super.extend(
/** Return tool.inputs that should/can be safely displayed */
_labelParamMap: function() {
//ADAPTER
var params = this.model.get("params"),
labelParamMap = {};
var params = this.model.get("params");
var labelParamMap = {};
_.each(this.tool.inputs, function(i) {
//console.debug( i.label, i.model_class );
if (i.label && i.model_class !== "DataToolParameter") {
@@ -72,8 +73,9 @@ var JobListItemView = _super.extend(
_labelInputMap: function() {
//ADAPTER
var view = this,
labelInputMap = {};
var view = this;
var labelInputMap = {};
_.each(this.jobData.inputs, function(input) {
var toolInput = view._findToolInput(input.name);
if (toolInput) {
@@ -86,8 +88,9 @@ var JobListItemView = _super.extend(
/** Return a tool.inputs object that matches (or partially matches) the given (job input) name */
_findToolInput: function(name) {
//ADAPTER
var toolInputs = this.tool.inputs,
exactMatch = _.findWhere(toolInputs, { name: name });
var toolInputs = this.tool.inputs;
var exactMatch = _.findWhere(toolInputs, { name: name });
if (exactMatch) {
return exactMatch;
}
+12 -10
View File
@@ -166,14 +166,16 @@ var JobCollection = Backbone.Collection.extend(BASE_MVC.LoggableMixin).extend(
// ........................................................................ ajax
/** fetches all details for each job in the collection using a queue */
queueDetailFetching: function() {
var collection = this,
queue = new AJAX_QUEUE.AjaxQueue(
this.map(function(job) {
return function() {
return job.fetch({ silent: true });
};
})
);
var collection = this;
var queue = new AJAX_QUEUE.AjaxQueue(
this.map(function(job) {
return function() {
return job.fetch({ silent: true });
};
})
);
queue.done(function() {
collection.trigger("details-loaded");
});
@@ -204,8 +206,8 @@ var JobCollection = Backbone.Collection.extend(BASE_MVC.LoggableMixin).extend(
/** class level fn for fetching the job details for all jobs in a history */
fromHistory: function(historyId) {
console.debug(this);
var Collection = this,
collection = new Collection([]);
var Collection = this;
var collection = new Collection([]);
collection
.fetch({ data: { history_id: historyId } })
.done(function() {
+3 -3
View File
@@ -2,9 +2,9 @@
import Utils from "utils/utils";
/** Build messages after user action */
function build_messages(self) {
var $el_message = self.$el.find(".response-message"),
status = Utils.getQueryString("status"),
message = Utils.getQueryString("message");
var $el_message = self.$el.find(".response-message");
var status = Utils.getQueryString("status");
var message = Utils.getQueryString("message");
if (message && message !== "") {
$el_message.addClass(status + "message");
@@ -168,8 +168,8 @@ var FolderToolbarView = Backbone.View.extend({
var folderDetails = this.serialize_new_folder();
if (this.validate_new_folder(folderDetails)) {
var folder = new mod_library_model.FolderAsModel();
var url_items = Backbone.history.fragment.split("/"),
current_folder_id;
var url_items = Backbone.history.fragment.split("/");
var current_folder_id;
if (url_items.indexOf("page") > -1) {
current_folder_id = url_items[url_items.length - 3];
} else {
+17 -14
View File
@@ -153,8 +153,8 @@ var ExpandableView = Backbone.View.extend(BASE_MVC.LoggableMixin).extend({
/** Inner fn called when expand (public) has fetched the details */
_expand: function() {
var view = this,
$newDetails = view._renderDetails();
var view = this;
var $newDetails = view._renderDetails();
view.$details().replaceWith($newDetails);
// needs to be set after the above or the slide will not show
view.expanded = true;
@@ -253,9 +253,9 @@ var ListItemView = ExpandableView.extend(
/** Render any warnings the item may need to show (e.g. "I'm deleted") */
_renderWarnings: function() {
var view = this,
$warnings = $('<div class="warnings"></div>'),
json = view.model.toJSON();
var view = this;
var $warnings = $('<div class="warnings"></div>');
var json = view.model.toJSON();
//TODO:! unordered (map)
_.each(view.templates.warnings, function(templateFn) {
$warnings.append($(templateFn(json, view)));
@@ -304,8 +304,9 @@ var ListItemView = ExpandableView.extend(
/** expand when the title bar is in focus and enter or space is pressed */
_keyDownTitleBar: function(event) {
// bail (with propagation) if keydown and not space or enter
var KEYCODE_SPACE = 32,
KEYCODE_RETURN = 13;
var KEYCODE_SPACE = 32;
var KEYCODE_RETURN = 13;
if (
event &&
event.type === "keydown" &&
@@ -433,13 +434,15 @@ var FoldoutListItemView = ListItemView.extend({
/** In this override, handle collection expansion. */
_createFoldoutPanel: function() {
var model = this.model;
var FoldoutClass = this._getFoldoutPanelClass(model),
options = this._getFoldoutPanelOptions(model),
foldout = new FoldoutClass(
_.extend(options, {
model: model
})
);
var FoldoutClass = this._getFoldoutPanelClass(model);
var options = this._getFoldoutPanelOptions(model);
var foldout = new FoldoutClass(
_.extend(options, {
model: model
})
);
return foldout;
},
+9 -8
View File
@@ -312,8 +312,8 @@ var ListPanel = Backbone.View.extend(BASE_MVC.LoggableMixin).extend(
/** render a menu containing the actions available to sets of selected items */
_renderMultiselectActionMenu: function($where) {
$where = $where || this.$el;
var $menu = $where.find(".list-action-menu"),
actions = this.multiselectActions();
var $menu = $where.find(".list-action-menu");
var actions = this.multiselectActions();
if (!actions.length) {
return $menu.empty();
}
@@ -499,8 +499,9 @@ var ListPanel = Backbone.View.extend(BASE_MVC.LoggableMixin).extend(
"draggable:dragstart",
function(ev, v) {
//TODO: set multiple drag data here
var json = {},
selected = this.getSelectedModels();
var json = {};
var selected = this.getSelectedModels();
if (selected.length) {
json = selected.toJSON();
} else {
@@ -684,8 +685,8 @@ var ListPanel = Backbone.View.extend(BASE_MVC.LoggableMixin).extend(
return viewA ? [viewA] : [];
}
var indexA = this.views.indexOf(viewA),
indexB = this.views.indexOf(viewB);
var indexA = this.views.indexOf(viewA);
var indexB = this.views.indexOf(viewB);
// handle not found
if (indexA === -1 || indexB === -1) {
@@ -1068,8 +1069,8 @@ var ModelListPanel = ListPanel.extend({
*/
_renderControls: function($newRender) {
this.debug(this + "(ModelListPanel)._renderControls");
var json = this.model ? this.model.toJSON() : {},
$controls = $(this.templates.controls(json, this));
var json = this.model ? this.model.toJSON() : {};
var $controls = $(this.templates.controls(json, this));
$newRender.find(".controls").replaceWith($controls);
return $controls;
},
@@ -146,8 +146,8 @@ var View = Backbone.View.extend({
var wp_count = 0;
this.wp_inputs = {};
function _handleWorkflowParameter(value, callback) {
var re = /\$\{(.+?)\}/g,
match;
var re = /\$\{(.+?)\}/g;
var match;
while ((match = re.exec(String(value)))) {
var wp_name = match[1];
callback(
@@ -509,8 +509,8 @@ var View = Backbone.View.extend({
}
} else if (input.wp_linked) {
new_value = input.value;
var re = /\$\{(.+?)\}/g,
match;
var re = /\$\{(.+?)\}/g;
var match;
while ((match = re.exec(input.value))) {
var wp_field =
self.wp_form.field_list[
+45 -40
View File
@@ -160,10 +160,12 @@ var Tool = Backbone.Model.extend({
* client and server yet.
*/
remove_inputs: function(types) {
var tool = this,
incompatible_inputs = tool.get("inputs").filter(function(input) {
return types.indexOf(input.get("type")) !== -1;
});
var tool = this;
var incompatible_inputs = tool.get("inputs").filter(function(input) {
return types.indexOf(input.get("type")) !== -1;
});
tool.get("inputs").remove(incompatible_inputs);
},
@@ -261,20 +263,21 @@ var Tool = Backbone.Model.extend({
// Because job may require indexing datasets, use server-side
// deferred to ensure that job is run. Also use deferred that
// resolves to outputs from tool.
var run_deferred = $.Deferred(),
ss_deferred = new util.ServerStateDeferred({
ajax_settings: {
url: this.urlRoot,
data: JSON.stringify(payload),
dataType: "json",
contentType: "application/json",
type: "POST"
},
interval: 2000,
success_fn: function(response) {
return response !== "pending";
}
});
var run_deferred = $.Deferred();
var ss_deferred = new util.ServerStateDeferred({
ajax_settings: {
url: this.urlRoot,
data: JSON.stringify(payload),
dataType: "json",
contentType: "application/json",
type: "POST"
},
interval: 2000,
success_fn: function(response) {
return response !== "pending";
}
});
// Run job and resolve run_deferred to tool outputs.
$.when(ss_deferred.go()).then(function(result) {
@@ -321,8 +324,8 @@ var ToolSection = Backbone.Model.extend({
},
apply_search_results: function(results) {
var all_hidden = true,
cur_label;
var all_hidden = true;
var cur_label;
_.each(this.attributes.elems, function(elt) {
if (elt instanceof ToolSectionLabel) {
cur_label = elt;
@@ -439,23 +442,24 @@ var ToolPanel = Backbone.Model.extend({
*/
parse: function(response) {
// Recursive function to parse tool panel elements.
var self = this,
// Helper to recursively parse tool panel.
parse_elt = function(elt_dict) {
var type = elt_dict.model_class;
// There are many types of tools; for now, anything that ends in 'Tool'
// is treated as a generic tool.
if (type.indexOf("Tool") === type.length - 4) {
return self.attributes.tools.get(elt_dict.id);
} else if (type === "ToolSection") {
// Parse elements.
var elems = _.map(elt_dict.elems, parse_elt);
elt_dict.elems = elems;
return new ToolSection(elt_dict);
} else if (type === "ToolSectionLabel") {
return new ToolSectionLabel(elt_dict);
}
};
var self = this;
var // Helper to recursively parse tool panel.
parse_elt = function(elt_dict) {
var type = elt_dict.model_class;
// There are many types of tools; for now, anything that ends in 'Tool'
// is treated as a generic tool.
if (type.indexOf("Tool") === type.length - 4) {
return self.attributes.tools.get(elt_dict.id);
} else if (type === "ToolSection") {
// Parse elements.
var elems = _.map(elt_dict.elems, parse_elt);
elt_dict.elems = elems;
return new ToolSection(elt_dict);
} else if (type === "ToolSectionLabel") {
return new ToolSectionLabel(elt_dict);
}
};
return _.map(response, parse_elt);
},
@@ -737,9 +741,10 @@ var ToolPanelView = Backbone.View.extend({
self.$el.find("a.tool-link").click(function(e) {
// Tool id is always the first class.
var tool_id = $(this)
.attr("class")
.split(/\s+/)[0],
tool = self.model.get("tools").get(tool_id);
.attr("class")
.split(/\s+/)[0];
var tool = self.model.get("tools").get(tool_id);
self.trigger("tool_link_click", e, tool);
});
@@ -29,8 +29,8 @@ var View = Backbone.View.extend({
},
bindEvents: function() {
var that = this,
repository_id;
var that = this;
var repository_id;
$(".show_wf_repo").on("click", function() {
var tool_ids = $(this).attr("data-toolids");
var toolshed = $(this).attr("data-shed");
+18 -14
View File
@@ -95,11 +95,13 @@ var PopupMenu = Backbone.View.extend({
"</a></li>"
].join("");
}
var href = option.href || "javascript:void(0);",
target = option.target ? ' target="' + option.target + '"' : "",
check = option.checked
? '<span class="fa fa-check"></span>'
: "";
var href = option.href || "javascript:void(0);";
var target = option.target ? ' target="' + option.target + '"' : "";
var check = option.checked
? '<span class="fa fa-check"></span>'
: "";
return [
'<li><a class="popupmenu-option" href="',
href,
@@ -257,15 +259,15 @@ PopupMenu.convertLinksToOptions = function($parent, selector) {
selector = selector || "a";
var options = [];
$parent.find(selector).each(function(elem, i) {
var option = {},
$link = $(elem);
var option = {};
var $link = $(elem);
// convert link text to the option text (html) and the href into the option func
option.html = $link.text();
if ($link.attr("href")) {
var linkHref = $link.attr("href"),
linkTarget = $link.attr("target"),
confirmText = $link.attr("confirm");
var linkHref = $link.attr("href");
var linkTarget = $link.attr("target");
var confirmText = $link.attr("confirm");
option.func = function() {
// if there's a "confirm" attribute, throw up a confirmation dialog, and
@@ -348,10 +350,12 @@ PopupMenu.make_popup_menus = function(
$(parent)
.find(menuSelector)
.each(function() {
var $menuElement = $(this),
$buttonElement = $(parent).find(
buttonSelectorBuildFn($menuElement, parent)
);
var $menuElement = $(this);
var $buttonElement = $(parent).find(
buttonSelectorBuildFn($menuElement, parent)
);
popupMenusCreated.push(
PopupMenu.fromDom($buttonElement, $menuElement)
);
+3 -1
View File
@@ -126,7 +126,9 @@ var View = Backbone.View.extend({
var container_position = $container.position();
// get position
var top, left;
var top;
var left;
top = left = 0;
if (["top", "bottom"].indexOf(placement) != -1) {
left =
+2 -2
View File
@@ -64,8 +64,8 @@ var User = Backbone.Model.extend(baseMVC.LoggableMixin).extend(
idOrCurrent = idOrCurrent || User.CURRENT_ID_STR;
options = options || {};
var model = this,
userFn = options.success;
var model = this;
var userFn = options.success;
/** @ignore */
options.success = function(newModel, response) {
@@ -58,12 +58,15 @@ var UserQuotaMeter = Backbone.View.extend(baseMVC.LoggableMixin).extend(
* @returns {jQuery} the rendered meter
*/
_render_quota: function() {
var modelJson = this.model.toJSON(),
//prevPercent = this.model.previous( 'quota_percent' ),
percent = modelJson.quota_percent,
//meter = $( UserQuotaMeter.templates.quota( modelJson ) );
$meter = $(this._templateQuotaMeter(modelJson)),
$bar = $meter.find(".progress-bar");
var modelJson = this.model.toJSON();
var //prevPercent = this.model.previous( 'quota_percent' ),
percent = modelJson.quota_percent;
var //meter = $( UserQuotaMeter.templates.quota( modelJson ) );
$meter = $(this._templateQuotaMeter(modelJson));
var $bar = $meter.find(".progress-bar");
//this.log( this + '.rendering quota, percent:', percent, 'meter:', meter );
// OVER QUOTA: color the quota bar and show the quota error message
@@ -30,7 +30,8 @@ $.extend(CanvasManager.prototype, {
this.cc.each(function() {
this.scroll_panel = new ScrollPanel(this);
});
var x_adjust, y_adjust;
var x_adjust;
var y_adjust;
this.cv
.bind("dragstart", function() {
var o = $(this).offset();
@@ -49,14 +50,17 @@ $.extend(CanvasManager.prototype, {
if (self.overview.hasClass("blockaclick")) {
self.overview.removeClass("blockaclick");
} else {
var in_w = self.cc.width(),
in_h = self.cc.height(),
o_w = self.oc.width(),
o_h = self.oc.height(),
new_x_offset =
e.pageX - self.oc.offset().left - self.ov.width() / 2,
new_y_offset =
e.pageY - self.oc.offset().top - self.ov.height() / 2;
var in_w = self.cc.width();
var in_h = self.cc.height();
var o_w = self.oc.width();
var o_h = self.oc.height();
var new_x_offset =
e.pageX - self.oc.offset().left - self.ov.width() / 2;
var new_y_offset =
e.pageY - self.oc.offset().top - self.ov.height() / 2;
move(
-(new_x_offset / o_w * in_w),
-(new_y_offset / o_h * in_h)
@@ -68,12 +72,12 @@ $.extend(CanvasManager.prototype, {
// Dragging for overview pane
this.ov
.bind("drag", function(e, d) {
var in_w = self.cc.width(),
in_h = self.cc.height(),
o_w = self.oc.width(),
o_h = self.oc.height(),
new_x_offset = d.offsetX - self.overview.offset().left,
new_y_offset = d.offsetY - self.overview.offset().top;
var in_w = self.cc.width();
var in_h = self.cc.height();
var o_w = self.oc.width();
var o_h = self.oc.height();
var new_x_offset = d.offsetX - self.overview.offset().left;
var new_y_offset = d.offsetY - self.overview.offset().top;
move(
-(new_x_offset / o_w * in_w),
-(new_y_offset / o_h * in_h)
@@ -104,15 +108,15 @@ $.extend(CanvasManager.prototype, {
$("#overview-border div").bind("drag", function() {});
},
update_viewport_overlay: function() {
var cc = this.cc,
cv = this.cv,
oc = this.oc,
ov = this.ov,
in_w = cc.width(),
in_h = cc.height(),
o_w = oc.width(),
o_h = oc.height(),
cc_pos = cc.position();
var cc = this.cc;
var cv = this.cv;
var oc = this.oc;
var ov = this.ov;
var in_w = cc.width();
var in_h = cc.height();
var o_w = oc.width();
var o_h = oc.height();
var cc_pos = cc.position();
ov.css({
left: -(cc_pos.left / in_w * o_w),
top: -(cc_pos.top / in_h * o_h),
@@ -122,15 +126,20 @@ $.extend(CanvasManager.prototype, {
});
},
draw_overview: function() {
var canvas_el = $("#overview-canvas"),
size = canvas_el
.parent()
.parent()
.width(),
c = canvas_el.get(0).getContext("2d"),
in_w = $("#canvas-container").width(),
in_h = $("#canvas-container").height();
var o_h, shift_h, o_w, shift_w;
var canvas_el = $("#overview-canvas");
var size = canvas_el
.parent()
.parent()
.width();
var c = canvas_el.get(0).getContext("2d");
var in_w = $("#canvas-container").width();
var in_h = $("#canvas-container").height();
var o_h;
var shift_h;
var o_w;
var shift_w;
// Fit canvas into overview area
var cv_w = this.cv.width();
var cv_h = this.cv.height();
@@ -166,12 +175,12 @@ $.extend(CanvasManager.prototype, {
c.fillStyle = "#D2C099";
c.strokeStyle = "#D8B365";
c.lineWidth = 1;
var node_element = $(node.element),
position = node_element.position(),
x = position.left / in_w * o_w,
y = position.top / in_h * o_h,
w = node_element.width() / in_w * o_w,
h = node_element.height() / in_h * o_h;
var node_element = $(node.element);
var position = node_element.position();
var x = position.left / in_w * o_w;
var y = position.top / in_h * o_h;
var w = node_element.width() / in_w * o_w;
var h = node_element.height() / in_h * o_h;
if (node.errors) {
c.fillStyle = "#FFCCCC";
c.strokeStyle = "#AA6666";
@@ -196,33 +205,44 @@ function ScrollPanel(panel) {
$.extend(ScrollPanel.prototype, {
test: function(e, onmove) {
clearTimeout(this.timeout);
var x = e.pageX,
y = e.pageY,
// Panel size and position
panel = $(this.panel),
panel_pos = panel.position(),
panel_w = panel.width(),
panel_h = panel.height(),
// Viewport size and offset
viewport = panel.parent(),
viewport_w = viewport.width(),
viewport_h = viewport.height(),
viewport_offset = viewport.offset(),
// Edges of viewport (in page coordinates)
min_x = viewport_offset.left,
min_y = viewport_offset.top,
max_x = min_x + viewport.width(),
max_y = min_y + viewport.height(),
// Legal panel range
p_min_x = -(panel_w - viewport_w / 2),
p_min_y = -(panel_h - viewport_h / 2),
p_max_x = viewport_w / 2,
p_max_y = viewport_h / 2,
// Did the panel move?
moved = false,
// Constants
close_dist = 5,
nudge = 23;
var x = e.pageX;
var y = e.pageY;
var // Panel size and position
panel = $(this.panel);
var panel_pos = panel.position();
var panel_w = panel.width();
var panel_h = panel.height();
var // Viewport size and offset
viewport = panel.parent();
var viewport_w = viewport.width();
var viewport_h = viewport.height();
var viewport_offset = viewport.offset();
var // Edges of viewport (in page coordinates)
min_x = viewport_offset.left;
var min_y = viewport_offset.top;
var max_x = min_x + viewport.width();
var max_y = min_y + viewport.height();
var // Legal panel range
p_min_x = -(panel_w - viewport_w / 2);
var p_min_y = -(panel_h - viewport_h / 2);
var p_max_x = viewport_w / 2;
var p_max_y = viewport_h / 2;
var // Did the panel move?
moved = false;
var // Constants
close_dist = 5;
var nudge = 23;
if (x - close_dist < min_x) {
if (panel_pos.left < p_max_x) {
var t = Math.min(nudge, p_max_x - panel_pos.left);
@@ -83,11 +83,13 @@ $.extend(Connector.prototype, {
start_y -= canvas_top;
end_x -= canvas_left;
end_y -= canvas_top;
// Draw the line
var c = this.canvas.getContext("2d"),
start_offsets = null,
end_offsets = null;
var c = this.canvas.getContext("2d");
var start_offsets = null;
var end_offsets = null;
var num_offsets = 1;
if (this.handle1 && this.handle1.isMappedOver()) {
var start_offsets = [-6, -3, 0, 3, 6];
@@ -103,8 +105,8 @@ $.extend(Connector.prototype, {
}
var connector = this;
for (var i = 0; i < num_offsets; i++) {
var inner_width = 5,
outer_width = 7;
var inner_width = 5;
var outer_width = 7;
if (start_offsets.length > 1 || end_offsets.length > 1) {
// We have a multi-run, using many lines, make them small.
inner_width = 1;
@@ -434,11 +434,11 @@ $.extend(Workflow.prototype, {
});
},
bounds_for_all_nodes: function() {
var xmin = Infinity,
xmax = -Infinity,
ymin = Infinity,
ymax = -Infinity,
p;
var xmin = Infinity;
var xmax = -Infinity;
var ymin = Infinity;
var ymax = -Infinity;
var p;
$.each(this.nodes, function(id, node) {
var e = $(node.element);
p = e.position();
@@ -192,10 +192,11 @@ var BaseOutputTerminalView = TerminalView.extend({
onDrag: function(e, d) {
var onmove = function() {
var po = $(d.proxy)
.offsetParent()
.offset(),
x = d.offsetX - po.left,
y = d.offsetY - po.top;
.offsetParent()
.offset();
var x = d.offsetX - po.left;
var y = d.offsetY - po.top;
$(d.proxy).css({ left: x, top: y });
d.proxy.terminal.redraw();
// FIXME: global
@@ -644,7 +644,8 @@ export default Backbone.View.extend({
scroll_to_nodes: function() {
var cv = $("#canvas-viewport");
var cc = $("#canvas-container");
var top, left;
var top;
var left;
if (cc.width() < cv.width()) {
left = (cv.width() - cc.width()) / 2;
} else {
@@ -923,10 +924,11 @@ export default Backbone.View.extend({
.bind("drag", function(e, d) {
// Move
var po = $(this)
.offsetParent()
.offset(),
x = d.offsetX - po.left,
y = d.offsetY - po.top;
.offsetParent()
.offset();
var x = d.offsetX - po.left;
var y = d.offsetY - po.top;
$(this).css({ left: x, top: y });
// Redraw
$(this)
+16 -12
View File
@@ -87,12 +87,14 @@ function init_refresh_on_change() {
$("select[refresh_on_change='true']")
.off("change")
.change(function() {
var select_field = $(this),
select_val = select_field.val(),
refresh = false,
ref_on_change_vals = select_field.attr(
"refresh_on_change_values"
);
var select_field = $(this);
var select_val = select_field.val();
var refresh = false;
var ref_on_change_vals = select_field.attr(
"refresh_on_change_values"
);
if (ref_on_change_vals) {
ref_on_change_vals = ref_on_change_vals.split(",");
var last_selected_value = select_field.attr(
@@ -114,12 +116,14 @@ function init_refresh_on_change() {
$(":checkbox[refresh_on_change='true']")
.off("click")
.click(function() {
var select_field = $(this),
select_val = select_field.val(),
refresh = false,
ref_on_change_vals = select_field.attr(
"refresh_on_change_values"
);
var select_field = $(this);
var select_val = select_field.val();
var refresh = false;
var ref_on_change_vals = select_field.attr(
"refresh_on_change_values"
);
if (ref_on_change_vals) {
ref_on_change_vals = ref_on_change_vals.split(",");
var last_selected_value = select_field.attr(
@@ -578,8 +578,8 @@ function create_histogram(inp_data, name, title) {
// Formatter for x axis times (converting minutes to HH:MM).
var formatMinutes = function(d) {
var hours = Math.floor(d / 60),
minutes = Math.floor(d - hours * 60);
var hours = Math.floor(d / 60);
var minutes = Math.floor(d - hours * 60);
if (hours < 10) {
hours = "0" + hours;
@@ -628,8 +628,9 @@ function create_histogram(inp_data, name, title) {
})
.on("mouseenter", function(d) {
// Show tool tip
var i = 0,
size = d.length;
var i = 0;
var size = d.length;
while (size >= 1) {
size = size / 10;
+13 -11
View File
@@ -11,12 +11,15 @@ var $ = jQuery;
*/
$.fn.make_text_editable = function(config_dict) {
// Get config options.
var num_cols = "num_cols" in config_dict ? config_dict.num_cols : 30,
num_rows = "num_rows" in config_dict ? config_dict.num_rows : 4,
use_textarea =
"use_textarea" in config_dict ? config_dict.use_textarea : false,
on_finish = "on_finish" in config_dict ? config_dict.on_finish : null,
help_text = "help_text" in config_dict ? config_dict.help_text : null;
var num_cols = "num_cols" in config_dict ? config_dict.num_cols : 30;
var num_rows = "num_rows" in config_dict ? config_dict.num_rows : 4;
var use_textarea =
"use_textarea" in config_dict ? config_dict.use_textarea : false;
var on_finish = "on_finish" in config_dict ? config_dict.on_finish : null;
var help_text = "help_text" in config_dict ? config_dict.help_text : null;
// Add element behavior.
var container = $(this);
@@ -47,11 +50,10 @@ $.fn.make_text_editable = function(config_dict) {
// Create input element(s) for editing.
var cur_text =
"cur_text" in config_dict
? config_dict.cur_text
: container.text(),
input_elt,
button_elt;
"cur_text" in config_dict ? config_dict.cur_text : container.text();
var input_elt;
var button_elt;
if (use_textarea) {
input_elt = $("<textarea/>")
+21 -17
View File
@@ -53,9 +53,9 @@ function dropDownSelect(options, selected) {
// trigger 'change.dropdown-select' when a new selection is made using the dropdown
function selectThis(event) {
var $this = $(this),
$select = $this.parents(".dropdown-select"),
newSelection = $this.text();
var $this = $(this);
var $select = $this.parents(".dropdown-select");
var newSelection = $this.text();
$select.find(".dropdown-select-selected").text(newSelection);
$select.trigger("change.dropdown-select", newSelection);
}
@@ -140,8 +140,8 @@ FilterControl.prototype._renderKeySelect = function __renderKeySelect() {
/** render the op dropDownSelect, bind a change event to it, and return it */
FilterControl.prototype._renderOpSelect = function __renderOpSelect() {
var filterControl = this,
ops = this.currFilter.ops;
var filterControl = this;
var ops = this.currFilter.ops;
//TODO: search for currOp in avail. ops: use that for selected if there; otherwise: first op
this.$opSelect = dropDownSelect(ops, ops[0])
.addClass("filter-control-op")
@@ -177,16 +177,20 @@ FilterControl.prototype._renderValueInput = function __renderValueInput() {
/** return the current state/setting for the filter as a three key object: key, op, value */
FilterControl.prototype.val = function _val() {
var key = this.$element
.find(".filter-control-key .dropdown-select-selected")
.text(),
op = this.$element
.find(".filter-control-op .dropdown-select-selected")
.text(),
// handle either a dropdown or plain input
$value = this.$element.find(".filter-control-value"),
value = $value.hasClass("dropdown-select")
? $value.find(".dropdown-select-selected").text()
: $value.val();
.find(".filter-control-key .dropdown-select-selected")
.text();
var op = this.$element
.find(".filter-control-op .dropdown-select-selected")
.text();
var // handle either a dropdown or plain input
$value = this.$element.find(".filter-control-value");
var value = $value.hasClass("dropdown-select")
? $value.find(".dropdown-select-selected").text()
: $value.val();
return { key: key, op: op, value: value };
};
@@ -200,8 +204,8 @@ jQuery.fn.extend({
filterControl: function $filterControl(options) {
var nonOptionsArgs = jQuery.makeArray(arguments).slice(1);
return this.map(function() {
var $this = $(this),
data = $this.data(FilterControl.prototype.DATA_KEY);
var $this = $(this);
var data = $this.data(FilterControl.prototype.DATA_KEY);
if (jQuery.type(options) === "object") {
data = new FilterControl($this, options);
+2 -2
View File
@@ -12,8 +12,8 @@ jQuery.fn.extend({
}
$(this).each(function() {
var $this = $(this),
targetSelector = $this.data("target");
var $this = $(this);
var targetSelector = $this.data("target");
if (targetSelector) {
$this
@@ -24,13 +24,14 @@ function LoadingIndicator($where, options) {
].join("\n");
var $indicator = $(html)
.hide()
.css(
options.css || {
position: "fixed"
}
),
$text = $indicator.children(".loading-indicator-text");
.hide()
.css(
options.css || {
position: "fixed"
}
);
var $text = $indicator.children(".loading-indicator-text");
if (options.cover) {
$indicator.css({
+2 -2
View File
@@ -170,8 +170,8 @@ $.fn.modeButton = function $modeButton(options) {
});
}
var $first = $(this[0]),
button = $first.data("mode-button");
var $first = $(this[0]);
var button = $first.data("mode-button");
if (!button) {
throw new Error(
+25 -20
View File
@@ -91,12 +91,13 @@ Pagination.prototype._render = function __render() {
/** render previous and next pagination buttons */
Pagination.prototype._renderPrevNext = function __renderPrevNext() {
var pagination = this,
$prev = _make$Li("Prev"),
$next = _make$Li("Next"),
$paginationContainer = $("<ul/>").addClass(
"pagination pagination-prev-next"
);
var pagination = this;
var $prev = _make$Li("Prev");
var $next = _make$Li("Next");
var $paginationContainer = $("<ul/>").addClass(
"pagination pagination-prev-next"
);
// disable if it either end
if (this.currPage === 0) {
@@ -127,16 +128,19 @@ Pagination.prototype._renderPrevNext = function __renderPrevNext() {
Pagination.prototype._renderPages = function __renderPages() {
// it's better to scroll the control and let the user see all pages
// than to force her/him to change pages in order to find the one they want (as traditional << >> does)
var pagination = this,
$scrollingContainer = $("<div>").addClass(
"pagination-scroll-container"
),
$paginationContainer = $("<ul/>").addClass(
"pagination pagination-page-list"
),
page$LiClick = function(ev) {
pagination.goToPage($(this).data("page"));
};
var pagination = this;
var $scrollingContainer = $("<div>").addClass(
"pagination-scroll-container"
);
var $paginationContainer = $("<ul/>").addClass(
"pagination pagination-page-list"
);
var page$LiClick = function(ev) {
pagination.goToPage($(this).data("page"));
};
for (var i = 0; i < this.numPages; i += 1) {
// add html5 data tag 'page' for later click event handler use
@@ -162,8 +166,8 @@ Pagination.prototype._scrollToActivePage = function __scrollToActivePage() {
return this;
}
var $activePage = this.$element.find("li.active"),
midpoint = $container.width() / 2;
var $activePage = this.$element.find("li.active");
var midpoint = $container.width() / 2;
//console.debug( $container, $activePage, midpoint );
$container.scrollLeft(
$container.scrollLeft() + $activePage.position().left - midpoint
@@ -225,8 +229,9 @@ jQuery.fn.extend({
}
// (other invocations only work on the first element in selected)
var $firstElement = $(this[0]),
previousControl = $firstElement.data(Pagination.prototype.DATA_KEY);
var $firstElement = $(this[0]);
var previousControl = $firstElement.data(Pagination.prototype.DATA_KEY);
// if a pagination control was found for this element, either...
if (previousControl) {
// invoke a function on the pagination object if passed a string (the function name)
@@ -2,6 +2,7 @@
// Uses AMD or browser globals to create a jQuery plugin.
import jQuery from "jquery";
var $ = jQuery;
//==============================================================================
/** Column selection using the peek display as the control.
* Adds rows to the bottom of the peek with clickable areas in each cell
@@ -48,41 +49,52 @@ var $ = jQuery;
/** option defaults */
var defaults = {
/** does this control allow renaming headers? */
renameColumns: false,
/** does this control allow renaming headers? */
columnNames: [],
/** the comment character used by the peek's datatype */
commentChar: "#",
/** should comment rows be shown or hidden in the peek */
hideCommentRows: false,
/** should a column of row control prompts be used */
includePrompts: true,
/** what is the content of the top left cell (often a title) */
topLeftContent: "Columns:"
},
/** class added to the pre.peek element (to allow css on just the control) */
PEEKCONTROL_CLASS = "peek-column-selector",
/** the string of the event fired when a control row changes */
CHANGE_EVENT = "peek-column-selector.change",
/** the string of the event fired when a column is renamed */
RENAME_EVENT = "peek-column-selector.rename",
/** class added to the control rows */
ROW_CLASS = "control",
/** class added to the left-hand cells that serve as row prompts */
PROMPT_CLASS = "control-prompt",
/** class added to selected _cells_/tds */
SELECTED_CLASS = "selected",
/** class added to disabled/un-clickable cells/tds */
DISABLED_CLASS = "disabled",
/** class added to the clickable surface within a cell to select it */
BUTTON_CLASS = "button",
/** class added to peek table header (th) cells to indicate they can be clicked and are renamable */
RENAMABLE_HEADER_CLASS = "renamable-header",
/** the data key used for each cell to store the column index ('data-...') */
COLUMN_INDEX_DATA_KEY = "column-index",
/** renamable header data key used to store the column name (w/o the number and dot: '1.Bler') */
COLUMN_NAME_DATA_KEY = "column-name";
/** does this control allow renaming headers? */
renameColumns: false,
/** does this control allow renaming headers? */
columnNames: [],
/** the comment character used by the peek's datatype */
commentChar: "#",
/** should comment rows be shown or hidden in the peek */
hideCommentRows: false,
/** should a column of row control prompts be used */
includePrompts: true,
/** what is the content of the top left cell (often a title) */
topLeftContent: "Columns:"
};
var /** class added to the pre.peek element (to allow css on just the control) */
PEEKCONTROL_CLASS = "peek-column-selector";
var /** the string of the event fired when a control row changes */
CHANGE_EVENT = "peek-column-selector.change";
var /** the string of the event fired when a column is renamed */
RENAME_EVENT = "peek-column-selector.rename";
var /** class added to the control rows */
ROW_CLASS = "control";
var /** class added to the left-hand cells that serve as row prompts */
PROMPT_CLASS = "control-prompt";
var /** class added to selected _cells_/tds */
SELECTED_CLASS = "selected";
var /** class added to disabled/un-clickable cells/tds */
DISABLED_CLASS = "disabled";
var /** class added to the clickable surface within a cell to select it */
BUTTON_CLASS = "button";
var /** class added to peek table header (th) cells to indicate they can be clicked and are renamable */
RENAMABLE_HEADER_CLASS = "renamable-header";
var /** the data key used for each cell to store the column index ('data-...') */
COLUMN_INDEX_DATA_KEY = "column-index";
var /** renamable header data key used to store the column name (w/o the number and dot: '1.Bler') */
COLUMN_NAME_DATA_KEY = "column-name";
//TODO: not happy with pure functional here - rows should polymorph (multi, single, etc.)
//TODO: needs clean up, move handlers to outer scope
@@ -187,9 +199,10 @@ function buildSingleSelectCell(control, columnIndex) {
setSelectedText($cell, control, columnIndex);
// fire the event from the table itself, passing the id and index of selected
var eventData = {},
key = $cell.parent().attr("id"),
val = $cell.data(COLUMN_INDEX_DATA_KEY);
var eventData = {};
var key = $cell.parent().attr("id");
var val = $cell.data(COLUMN_INDEX_DATA_KEY);
eventData[key] = val;
$cell.parents(".peek").trigger(CHANGE_EVENT, eventData);
}
@@ -220,10 +233,12 @@ function buildMultiSelectCell(control, columnIndex) {
.map(function(i, e) {
return $(e).data(COLUMN_INDEX_DATA_KEY);
});
// fire the event from the table itself, passing the id and index of selected
var eventData = {},
key = $cell.parent().attr("id"),
val = jQuery.makeArray(selectedColumnIndeces);
var eventData = {};
var key = $cell.parent().attr("id");
var val = jQuery.makeArray(selectedColumnIndeces);
eventData[key] = val;
$cell.parents(".peek").trigger(CHANGE_EVENT, eventData);
});
@@ -265,25 +280,28 @@ function buildControlRow(cellCount, control, includePrompts) {
function peekColumnSelector(options) {
options = jQuery.extend(true, {}, defaults, options);
var $peek = $(this).addClass(PEEKCONTROL_CLASS),
$peektable = $peek.find("table"),
// get the size of the tables - width and height, number of comment rows
columnCount = $peektable.find("th").length,
rowCount = $peektable.find("tr").length,
// get the rows containing text starting with the comment char (also make them grey)
$commentRows = $peektable.find("td[colspan]").map(function(e, i) {
var $this = $(this);
if (
$this.text() &&
$this.text().match(new RegExp("^" + options.commentChar))
) {
return $(this)
.css("color", "grey")
.parent()
.get(0);
}
return null;
});
var $peek = $(this).addClass(PEEKCONTROL_CLASS);
var $peektable = $peek.find("table");
var // get the size of the tables - width and height, number of comment rows
columnCount = $peektable.find("th").length;
var rowCount = $peektable.find("tr").length;
var // get the rows containing text starting with the comment char (also make them grey)
$commentRows = $peektable.find("td[colspan]").map(function(e, i) {
var $this = $(this);
if (
$this.text() &&
$this.text().match(new RegExp("^" + options.commentChar))
) {
return $(this)
.css("color", "grey")
.parent()
.get(0);
}
return null;
});
// should comment rows in the peek be hidden?
if (options.hideCommentRows) {
@@ -306,10 +324,12 @@ function peekColumnSelector(options) {
// save either the options column name or the parsed text of each column header in html5 data attr and text
var $headers = $peektable.find("th:not(.top-left)").each(function(i, e) {
var $this = $(this),
// can be '1.name' or '1'
text = $this.text().replace(/^\d+\.*/, ""),
name = options.columnNames[i] || text;
var $this = $(this);
var // can be '1.name' or '1'
text = $this.text().replace(/^\d+\.*/, "");
var name = options.columnNames[i] || text;
$this
.attr("data-" + COLUMN_NAME_DATA_KEY, name)
.text(i + 1 + (name ? "." + name : ""));
@@ -321,10 +341,11 @@ function peekColumnSelector(options) {
.addClass(RENAMABLE_HEADER_CLASS)
.click(function renameColumn() {
// prompt for new name
var $this = $(this),
index = $this.index() + (options.includePrompts ? 0 : 1),
prevName = $this.data(COLUMN_NAME_DATA_KEY),
newColumnName = prompt("New column name:", prevName);
var $this = $(this);
var index = $this.index() + (options.includePrompts ? 0 : 1);
var prevName = $this.data(COLUMN_NAME_DATA_KEY);
var newColumnName = prompt("New column name:", prevName);
if (newColumnName !== null && newColumnName !== prevName) {
// set the new text and data
$this
+5 -5
View File
@@ -126,11 +126,11 @@ function make_popup_menus(parent) {
// find each anchor in the menu, convert them into an options map: { a.text : click_function }
menu.find("a").each(function() {
var link = $(this),
link_dom = link.get(0),
confirmtext = link_dom.getAttribute("confirm"),
href = link_dom.getAttribute("href"),
target = link_dom.getAttribute("target");
var link = $(this);
var link_dom = link.get(0);
var confirmtext = link_dom.getAttribute("confirm");
var href = link_dom.getAttribute("href");
var target = link_dom.getAttribute("target");
// no href - no function (gen. a label)
if (!href) {
+32 -26
View File
@@ -6,32 +6,38 @@ $.ui.plugin.add("draggable", "scrollPanel", {
drag: function(e, ui) {
var instance = $(this).data("draggable");
clearTimeout(instance.timeout);
var o = ui.options,
element = instance.element,
panel = o.panel,
panel_pos = panel.position(),
panel_w = panel.width(),
panel_h = panel.height(),
viewport = panel.parent(),
viewport_w = viewport.width(),
viewport_h = viewport.height(),
element_w = element.width(),
element_h = element.height(),
moved = false,
close_dist = 5,
nudge = 23,
// Legal panel range
p_min_x = -(panel_w - viewport_w),
p_min_y = -(panel_h - viewport_h),
p_max_x = 0,
p_max_y = 0,
// Visible
min_vis_x = -panel_pos.left,
max_vis_x = min_vis_x + viewport_w,
min_vis_y = -panel_pos.top,
max_vis_y = min_vis_y + viewport_h,
// Mouse
mouse_x = ui.position.left + instance.offset.click.left;
var o = ui.options;
var element = instance.element;
var panel = o.panel;
var panel_pos = panel.position();
var panel_w = panel.width();
var panel_h = panel.height();
var viewport = panel.parent();
var viewport_w = viewport.width();
var viewport_h = viewport.height();
var element_w = element.width();
var element_h = element.height();
var moved = false;
var close_dist = 5;
var nudge = 23;
var // Legal panel range
p_min_x = -(panel_w - viewport_w);
var p_min_y = -(panel_h - viewport_h);
var p_max_x = 0;
var p_max_y = 0;
var // Visible
min_vis_x = -panel_pos.left;
var max_vis_x = min_vis_x + viewport_w;
var min_vis_y = -panel_pos.top;
var max_vis_y = min_vis_y + viewport_h;
var // Mouse
mouse_x = ui.position.left + instance.offset.click.left;
mouse_y = ui.position.top + instance.offset.click.top;
// Move it
if (panel_pos.left < p_max_x && mouse_x - close_dist < min_vis_x) {
+17 -16
View File
@@ -19,22 +19,23 @@ var _l =
* is focused will clear the input and call a separate callback.
*/
function searchInput(parentNode, options) {
var KEYCODE_ESC = 27,
KEYCODE_RETURN = 13,
$parentNode = $(parentNode),
firstSearch = true,
defaults = {
initialVal: "",
name: "search",
placeholder: "search",
classes: "",
onclear: function() {},
onfirstsearch: null,
onsearch: function(inputVal) {},
minSearchLen: 0,
escWillClear: true,
oninit: function() {}
};
var KEYCODE_ESC = 27;
var KEYCODE_RETURN = 13;
var $parentNode = $(parentNode);
var firstSearch = true;
var defaults = {
initialVal: "",
name: "search",
placeholder: "search",
classes: "",
onclear: function() {},
onfirstsearch: null,
onsearch: function(inputVal) {},
minSearchLen: 0,
escWillClear: true,
oninit: function() {}
};
// .................................................................... input rendering and events
// visually clear the search, trigger an event, and call the callback
+5 -4
View File
@@ -39,13 +39,14 @@ AjaxQueue.prototype.init = function init(initialFunctions) {
/** add a fn to the queue */
AjaxQueue.prototype.add = function add(fn) {
//console.debug( 'AjaxQueue.prototype.add:', fn );
var self = this,
index = this.queue.length;
var self = this;
var index = this.queue.length;
this.numToProcess += 1;
this.queue.push(function() {
var fnIndex = index,
xhr = fn();
var fnIndex = index;
var xhr = fn();
// if successful, notify using the deferred to allow tracking progress
xhr.done(function(response) {
self.deferred.notify({
@@ -31,9 +31,9 @@ function async_save_text(
if ($("#renaming-active").length > 0) {
return;
}
var text_elt = $("#" + text_elt_id),
old_text = text_elt.text(),
t;
var text_elt = $("#" + text_elt_id);
var old_text = text_elt.text();
var t;
if (use_textarea) {
t = $("<textarea></textarea>")
+99 -89
View File
@@ -232,9 +232,10 @@ var ConfigSettingCollectionView = Backbone.View.extend({
}
// Build row for param.
var id = "param_" + index,
type = param.get("type"),
value = param.get("value");
var id = "param_" + index;
var type = param.get("type");
var value = param.get("value");
var row = $("<div class='form-row' />").appendTo(container);
row.append(
$("<label />")
@@ -272,78 +273,84 @@ var ConfigSettingCollectionView = Backbone.View.extend({
row.append(select);
} else if (type === "color") {
// Draw parameter as color picker
var container_div = $("<div/>").appendTo(row),
input = $("<input />")
.attr("id", id)
.attr("name", id)
.val(value)
.css("float", "left")
.appendTo(container_div)
.click(function(e) {
// Hide other pickers.
$(".tooltip").removeClass("in");
var container_div = $("<div/>").appendTo(row);
// Show input's color picker.
var tip = $(this)
.siblings(".tooltip")
.addClass("in");
tip
.css({
// left: $(this).position().left + ( $(input).width() / 2 ) - 60,
// top: $(this).position().top + $(this.height)
left:
$(this).position().left +
$(this).width() +
5,
top:
$(this).position().top -
$(tip).height() / 2 +
$(this).height() / 2
})
.show();
var input = $("<input />")
.attr("id", id)
.attr("name", id)
.val(value)
.css("float", "left")
.appendTo(container_div)
.click(function(e) {
// Hide other pickers.
$(".tooltip").removeClass("in");
// Click management:
// Keep showing tip if clicking in tip.
tip.click(function(e) {
e.stopPropagation();
});
// Hide tip if clicking outside of tip.
$(document).bind("click.color-picker", function() {
tip.hide();
$(document).unbind("click.color-picker");
});
// No propagation to avoid triggering document click (and tip hiding) above.
e.stopPropagation();
}),
// Icon for setting a new random color; behavior set below.
new_color_icon = $("<a href='javascript:void(0)'/>")
.addClass("icon-button arrow-circle")
.appendTo(container_div)
.attr("title", "Set new random color")
.tooltip(),
// Color picker in tool tip style.
tip = $(
"<div class='tooltip right' style='position: absolute;' />"
)
.appendTo(container_div)
.hide(),
// Inner div for padding purposes
tip_inner = $(
"<div class='tooltip-inner' style='text-align: inherit'></div>"
).appendTo(tip),
tip_arrow = $("<div class='tooltip-arrow'></div>").appendTo(
// Show input's color picker.
var tip = $(this)
.siblings(".tooltip")
.addClass("in");
tip
),
farb_obj = $.farbtastic(tip_inner, {
width: 100,
height: 100,
callback: input,
color: value
.css({
// left: $(this).position().left + ( $(input).width() / 2 ) - 60,
// top: $(this).position().top + $(this.height)
left:
$(this).position().left +
$(this).width() +
5,
top:
$(this).position().top -
$(tip).height() / 2 +
$(this).height() / 2
})
.show();
// Click management:
// Keep showing tip if clicking in tip.
tip.click(function(e) {
e.stopPropagation();
});
// Hide tip if clicking outside of tip.
$(document).bind("click.color-picker", function() {
tip.hide();
$(document).unbind("click.color-picker");
});
// No propagation to avoid triggering document click (and tip hiding) above.
e.stopPropagation();
});
var // Icon for setting a new random color; behavior set below.
new_color_icon = $("<a href='javascript:void(0)'/>")
.addClass("icon-button arrow-circle")
.appendTo(container_div)
.attr("title", "Set new random color")
.tooltip();
var // Color picker in tool tip style.
tip = $(
"<div class='tooltip right' style='position: absolute;' />"
)
.appendTo(container_div)
.hide();
var // Inner div for padding purposes
tip_inner = $(
"<div class='tooltip-inner' style='text-align: inherit'></div>"
).appendTo(tip);
var tip_arrow = $("<div class='tooltip-arrow'></div>").appendTo(
tip
);
var farb_obj = $.farbtastic(tip_inner, {
width: 100,
height: 100,
callback: input,
color: value
});
// Clear floating.
container_div.append($("<div/>").css("clear", "both"));
@@ -375,25 +382,28 @@ var ConfigSettingCollectionView = Backbone.View.extend({
*/
render_in_modal: function(title) {
// Set up handlers for cancel, ok button and for handling esc key.
var self = this,
cancel_fn = function() {
Galaxy.modal.hide();
$(window).unbind("keypress.check_enter_esc");
},
ok_fn = function() {
Galaxy.modal.hide();
$(window).unbind("keypress.check_enter_esc");
self.update_from_form();
},
check_enter_esc = function(e) {
if ((e.keyCode || e.which) === 27) {
// Escape key
cancel_fn();
} else if ((e.keyCode || e.which) === 13) {
// Enter key
ok_fn();
}
};
var self = this;
var cancel_fn = function() {
Galaxy.modal.hide();
$(window).unbind("keypress.check_enter_esc");
};
var ok_fn = function() {
Galaxy.modal.hide();
$(window).unbind("keypress.check_enter_esc");
self.update_from_form();
};
var check_enter_esc = function(e) {
if ((e.keyCode || e.which) === 27) {
// Escape key
cancel_fn();
} else if ((e.keyCode || e.which) === 13) {
// Enter key
ok_fn();
}
};
// Set keypress handler.
$(window).bind("keypress.check_enter_esc", check_enter_esc);
+22 -20
View File
@@ -39,10 +39,10 @@ function matches(d, d2) {
* if propsOrFn is function, call the fn and returned the mapped values from it
*/
function iterate(obj, propsOrFn) {
var fn = typeof propsOrFn === "function" ? propsOrFn : undefined,
props = typeof propsOrFn === "object" ? propsOrFn : undefined,
returned = [],
index = 0;
var fn = typeof propsOrFn === "function" ? propsOrFn : undefined;
var props = typeof propsOrFn === "object" ? propsOrFn : undefined;
var returned = [];
var index = 0;
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
var value = obj[key];
@@ -211,8 +211,8 @@ BreadthFirstSearch.prototype._search = function __search(start, search) {
edges: []
};
var self = this,
queue = [];
var self = this;
var queue = [];
function discoverAdjacent(adj, edge) {
var source = this;
@@ -268,8 +268,8 @@ DepthFirstSearch.prototype._search = function(start, search) {
entryTimes: {},
exitTimes: {}
};
var self = this,
time = 0;
var self = this;
var time = 0;
// discover verts adjacent to the source (this):
// processing each edge, saving the edge to the tree, and caching the reverse path with parents
@@ -363,8 +363,8 @@ Graph.prototype.readNodesAndLinks = function(data) {
//console.debug( JSON.stringify( self.vertices, null, ' ' ) );
(data.links || []).forEach(function(edge, i) {
var sourceName = data.nodes[edge.source].name,
targetName = data.nodes[edge.target].name;
var sourceName = data.nodes[edge.source].name;
var targetName = data.nodes[edge.target].name;
self.createEdge(sourceName, targetName, self.directed);
});
//self.print();
@@ -421,8 +421,9 @@ Graph.prototype.createEdge = function(sourceName, targetName, directed, data) {
}
//TODO: prob. move to vertex
var self = this,
edge = new Edge(sourceName, targetName, data);
var self = this;
var edge = new Edge(sourceName, targetName, data);
sourceVertex.edges[targetName] = edge;
sourceVertex.degree += 1;
self.numEdges += 1;
@@ -485,8 +486,8 @@ Graph.prototype.print = function() {
/** Return a DOT format string of this graph */
Graph.prototype.toDOT = function() {
var self = this,
strings = [];
var self = this;
var strings = [];
strings.push("graph bler {");
self.edges(function(edge) {
strings.push("\t" + edge.from + " -- " + edge.to + ";");
@@ -497,8 +498,8 @@ Graph.prototype.toDOT = function() {
/** Return vertices and edges of this graph in d3 node/link format */
Graph.prototype.toNodesAndLinks = function() {
var self = this,
indeces = {};
var self = this;
var indeces = {};
return {
nodes: self.eachVertex(function(vertex, key, i) {
indeces[vertex.name] = i;
@@ -562,10 +563,11 @@ Graph.prototype.depthFirstSearchTree = function(start, processFns) {
Graph.prototype.weakComponents = function() {
//TODO: alternately, instead of returning graph-like objects:
// - could simply decorate the vertices (vertex.component = componentIndex), or clone the graph and do that
var self = this,
searchGraph = this,
undiscovered,
components = [];
var self = this;
var searchGraph = this;
var undiscovered;
var components = [];
function getComponent(undiscoveredVertex) {
//TODO: better interface on dfs (search v. searchTree)
+22 -17
View File
@@ -247,16 +247,20 @@ MetricsLogger.prototype._postCache = function _postCache(options) {
return jQuery.when({});
}
var self = this,
postSize = options.count || self._postSize,
// do not splice - remove after *successful* post
entries = self.cache.get(postSize),
entriesLength = entries.length,
// use the optional getPingData to add any extra info we may want to send
postData =
typeof self.options.getPingData === "function"
? self.options.getPingData()
: {};
var self = this;
var postSize = options.count || self._postSize;
var // do not splice - remove after *successful* post
entries = self.cache.get(postSize);
var entriesLength = entries.length;
var // use the optional getPingData to add any extra info we may want to send
postData =
typeof self.options.getPingData === "function"
? self.options.getPingData()
: {};
//console.debug( postSize, entriesLength );
// add the metrics and send
@@ -312,8 +316,9 @@ MetricsLogger.prototype._emitToConsole = function _emitToConsole(
logArguments
) {
//console.debug( '_emitToConsole:', level, namespace, logArguments );
var self = this,
whitelist = self.options.consoleNamespaceWhitelist;
var self = this;
var whitelist = self.options.consoleNamespaceWhitelist;
if (!self.consoleLogger) {
return self;
}
@@ -474,9 +479,9 @@ LoggingCache.prototype._initStorage = function _initStorage() {
/** add an entry to the cache, removing the oldest beforehand if size >= maxSize */
LoggingCache.prototype.add = function add(entry) {
var self = this,
_cache = self._fetchAndParse(),
overage = _cache.length + 1 - self.maxSize;
var self = this;
var _cache = self._fetchAndParse();
var overage = _cache.length + 1 - self.maxSize;
if (overage > 0) {
_cache.splice(0, overage);
}
@@ -514,8 +519,8 @@ LoggingCache.prototype.get = function get(count) {
/** remove count number of entries starting with the oldest */
LoggingCache.prototype.remove = function remove(count) {
var _cache = this._fetchAndParse(),
removed = _cache.splice(0, count);
var _cache = this._fetchAndParse();
var removed = _cache.splice(0, count);
this._unparseAndStore(_cache);
return removed;
};
+13 -9
View File
@@ -1,14 +1,15 @@
// Alphanumeric/natural sort fn
function naturalSort(a, b) {
// setup temp-scope variables for comparison evauluation
var re = /(-?[0-9\.]+)/g,
x = a.toString().toLowerCase() || "",
y = b.toString().toLowerCase() || "",
nC = String.fromCharCode(0),
xN = x.replace(re, nC + "$1" + nC).split(nC),
yN = y.replace(re, nC + "$1" + nC).split(nC),
xD = new Date(x).getTime(),
yD = xD ? new Date(y).getTime() : null;
var re = /(-?[0-9\.]+)/g;
var x = a.toString().toLowerCase() || "";
var y = b.toString().toLowerCase() || "";
var nC = String.fromCharCode(0);
var xN = x.replace(re, nC + "$1" + nC).split(nC);
var yN = y.replace(re, nC + "$1" + nC).split(nC);
var xD = new Date(x).getTime();
var yD = xD ? new Date(y).getTime() : null;
// natural sorting of dates
if (yD) {
if (xD < yD) {
@@ -17,8 +18,11 @@ function naturalSort(a, b) {
return 1;
}
}
// natural sorting through split numeric strings and default strings
var oFxNcL, oFyNcL;
var oFxNcL;
var oFyNcL;
for (
var cLoc = 0, numS = Math.max(xN.length, yN.length);
cLoc < numS;
@@ -21,8 +21,8 @@ function parse(queryString) {
if (!queryString) {
return {};
}
var parsed = {},
split = queryString.split("&");
var parsed = {};
var split = queryString.split("&");
split.forEach(function(pairString) {
var pair = pairString.split("=");
parsed[pair[0]] = decodeURI(pair[1]);
+9 -5
View File
@@ -26,7 +26,10 @@ function deepeach(dict, callback) {
/** Identifies urls and replaces them with anchors */
function linkify(inputText) {
var replacedText, replacePattern1, replacePattern2, replacePattern3;
var replacedText;
var replacePattern1;
var replacePattern2;
var replacePattern3;
// URLs starting with http://, https://, or ftp://
replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
@@ -260,10 +263,11 @@ function roundToDecimalPlaces(number, numPlaces) {
}
// calculate on import
var kb = 1024,
mb = kb * kb,
gb = mb * kb,
tb = gb * kb;
var kb = 1024;
var mb = kb * kb;
var gb = mb * kb;
var tb = gb * kb;
/**
* Format byte size to string with units
* @param{Integer} size - Size in bytes
@@ -14,8 +14,9 @@ var BBIDataManager = visualization.GenomeDataManager.extend({
this.set_data(region, deferred);
var url =
Galaxy.root + "datasets/" + this.get("dataset").id + "/display",
self = this;
Galaxy.root + "datasets/" + this.get("dataset").id + "/display";
var self = this;
var promise = new $.Deferred();
$.when(bigwig.makeBwg(url)).then(function(bb, err) {
$.when(
@@ -27,8 +28,9 @@ var BBIDataManager = visualization.GenomeDataManager.extend({
).then(function(data) {
// Transform data into "bigwig" format for LinePainter. "bigwig" format is an array of 2-element arrays
// where each element is [position, score]; unlike real bigwig format, no gaps are allowed.
var result = [],
prev = { max: Number.MIN_VALUE };
var result = [];
var prev = { max: Number.MIN_VALUE };
data.forEach(function(d) {
// If there is a gap between prev and d, fill it with an interval with score 0.
// This is necessary for LinePainter to draw correctly.
+258 -219
View File
@@ -16,8 +16,8 @@ var SVGUtils = Backbone.Model.extend({
* Returns true if element is visible.
*/
is_visible: function(svg_elt, svg) {
var eltBRect = svg_elt.getBoundingClientRect(),
svgBRect = $("svg")[0].getBoundingClientRect();
var eltBRect = svg_elt.getBoundingClientRect();
var svgBRect = $("svg")[0].getBoundingClientRect();
if (
// To the left of screen?
@@ -70,11 +70,14 @@ var UsesTicks = {
});
// Add line + text for ticks.
var tick_coords = [],
text_coords = [],
text_anchor = function(d) {
return d.angle > Math.PI ? "end" : null;
};
var tick_coords = [];
var text_coords = [];
var text_anchor = function(d) {
return d.angle > Math.PI ? "end" : null;
};
if (horizontal) {
tick_coords = [0, 0, 0, -4];
text_coords = [4, 0, "", ".35em"];
@@ -201,27 +204,32 @@ var CircsterView = Backbone.View.extend({
* Returns a list of circular tracks' radius bounds.
*/
get_tracks_bounds: function() {
var circular_tracks = this.get_circular_tracks(),
dataset_arc_height = this.model
.get("config")
.get_value("arc_dataset_height"),
track_gap = this.model.get("config").get_value("track_gap"),
// Subtract 20 to make sure chrom labels are on screen.
min_dimension = Math.min(this.$el.width(), this.$el.height()) - 20,
// Compute radius start based on model, will be centered
// and fit entirely inside element by default.
radius_start =
min_dimension / 2 -
circular_tracks.length * (dataset_arc_height + track_gap) +
// Add track_gap back in because no gap is needed for last track.
track_gap -
this.label_arc_height,
// Compute range of track starting radii.
tracks_start_radii = d3.range(
radius_start,
min_dimension / 2,
dataset_arc_height + track_gap
);
var circular_tracks = this.get_circular_tracks();
var dataset_arc_height = this.model
.get("config")
.get_value("arc_dataset_height");
var track_gap = this.model.get("config").get_value("track_gap");
var // Subtract 20 to make sure chrom labels are on screen.
min_dimension = Math.min(this.$el.width(), this.$el.height()) - 20;
var // Compute radius start based on model, will be centered
// and fit entirely inside element by default.
radius_start =
min_dimension / 2 -
circular_tracks.length * (dataset_arc_height + track_gap) +
// Add track_gap back in because no gap is needed for last track.
track_gap -
this.label_arc_height;
var // Compute range of track starting radii.
tracks_start_radii = d3.range(
radius_start,
min_dimension / 2,
dataset_arc_height + track_gap
);
// Map from track start to bounds.
var self = this;
@@ -234,62 +242,63 @@ var CircsterView = Backbone.View.extend({
* Renders circular tracks, chord tracks, and label tracks.
*/
render: function() {
var self = this,
width = self.$el.width(),
height = self.$el.height(),
circular_tracks = this.get_circular_tracks(),
chords_tracks = this.get_chord_tracks(),
total_gap = self.model.get("config").get_value("total_gap"),
tracks_bounds = this.get_tracks_bounds(),
// Set up SVG element.
svg = d3
.select(self.$el[0])
.append("svg")
.attr("width", width)
.attr("height", height)
.attr("pointer-events", "all")
// Set up zooming, dragging.
.append("svg:g")
.call(
d3.behavior.zoom().on("zoom", function() {
// Do zoom, drag.
var scale = d3.event.scale;
svg.attr(
"transform",
"translate(" +
d3.event.translate +
")" +
" scale(" +
scale +
")"
);
var self = this;
var width = self.$el.width();
var height = self.$el.height();
var circular_tracks = this.get_circular_tracks();
var chords_tracks = this.get_chord_tracks();
var total_gap = self.model.get("config").get_value("total_gap");
var tracks_bounds = this.get_tracks_bounds();
// Propagate scale changes to views.
if (self.scale !== scale) {
// Use timeout to wait for zooming/dragging to stop before rendering more detail.
if (self.zoom_drag_timeout) {
clearTimeout(self.zoom_drag_timeout);
}
self.zoom_drag_timeout = setTimeout(function() {
// Render more detail in tracks' visible elements.
// FIXME: do not do this right now; it is not fully implemented--e.g. data bounds
// are not updated when new data is fetched--and fetching more detailed quantitative
// data is not that useful.
/*
_.each(self.circular_views, function(view) {
view.update_scale(scale);
});
*/
}, 400);
var // Set up SVG element.
svg = d3
.select(self.$el[0])
.append("svg")
.attr("width", width)
.attr("height", height)
.attr("pointer-events", "all")
// Set up zooming, dragging.
.append("svg:g")
.call(
d3.behavior.zoom().on("zoom", function() {
// Do zoom, drag.
var scale = d3.event.scale;
svg.attr(
"transform",
"translate(" +
d3.event.translate +
")" +
" scale(" +
scale +
")"
);
// Propagate scale changes to views.
if (self.scale !== scale) {
// Use timeout to wait for zooming/dragging to stop before rendering more detail.
if (self.zoom_drag_timeout) {
clearTimeout(self.zoom_drag_timeout);
}
})
)
.attr(
"transform",
"translate(" + width / 2 + "," + height / 2 + ")"
)
.append("svg:g")
.attr("class", "tracks");
self.zoom_drag_timeout = setTimeout(function() {
// Render more detail in tracks' visible elements.
// FIXME: do not do this right now; it is not fully implemented--e.g. data bounds
// are not updated when new data is fetched--and fetching more detailed quantitative
// data is not that useful.
/*
_.each(self.circular_views, function(view) {
view.update_scale(scale);
});
*/
}, 400);
}
})
)
.attr(
"transform",
"translate(" + width / 2 + "," + height / 2 + ")"
)
.append("svg:g")
.attr("class", "tracks");
// -- Render circular tracks. --
@@ -330,12 +339,14 @@ var CircsterView = Backbone.View.extend({
// (a) outer radius of last circular track;
// (b)
var outermost_radius = this.circular_views[
this.circular_views.length - 1
].radius_bounds[1],
track_bounds = [
outermost_radius,
outermost_radius + this.label_arc_height
];
this.circular_views.length - 1
].radius_bounds[1];
var track_bounds = [
outermost_radius,
outermost_radius + this.label_arc_height
];
this.label_track_view = new CircsterChromLabelTrackView({
el: svg.append("g")[0],
track: new CircsterLabelTrack(),
@@ -355,14 +366,16 @@ var CircsterView = Backbone.View.extend({
if (new_track.get("track_type") === "DiagonalHeatmapTrack") {
// Added chords track.
var innermost_radius_bounds = this.circular_views[0].radius_bounds,
new_view = new CircsterChromInteractionsTrackView({
el: d3.select("g.tracks").append("g")[0],
track: new_track,
radius_bounds: innermost_radius_bounds,
genome: this.genome,
total_gap: total_gap
});
var innermost_radius_bounds = this.circular_views[0].radius_bounds;
var new_view = new CircsterChromInteractionsTrackView({
el: d3.select("g.tracks").append("g")[0],
track: new_track,
radius_bounds: innermost_radius_bounds,
genome: this.genome,
total_gap: total_gap
});
new_view.render();
this.chords_views.push(new_view);
} else {
@@ -380,14 +393,16 @@ var CircsterView = Backbone.View.extend({
});
// Render new track.
var track_index = this.circular_views.length,
track_view = new CircsterBigWigTrackView({
el: d3.select("g.tracks").append("g")[0],
track: new_track,
radius_bounds: new_track_bounds[track_index],
genome: this.genome,
total_gap: total_gap
});
var track_index = this.circular_views.length;
var track_view = new CircsterBigWigTrackView({
el: d3.select("g.tracks").append("g")[0],
track: new_track,
radius_bounds: new_track_bounds[track_index],
genome: this.genome,
total_gap: total_gap
});
track_view.render();
this.circular_views.push(track_view);
@@ -475,24 +490,27 @@ var CircsterTrackView = Backbone.View.extend({
var track_parent_elt = this.parent_elt;
// -- Render background arcs. --
var genome_arcs = this.chroms_layout,
arc_gen = d3.svg
.arc()
.innerRadius(this.radius_bounds[0])
.outerRadius(this.radius_bounds[1]),
// Attach data to group element.
chroms_elts = track_parent_elt
.selectAll("g")
.data(genome_arcs)
.enter()
.append("svg:g"),
// Draw chrom arcs/paths.
chroms_paths = chroms_elts
.append("path")
.attr("d", arc_gen)
.attr("class", "chrom-background")
.style("stroke", this.bg_stroke)
.style("fill", this.loading_bg_fill);
var genome_arcs = this.chroms_layout;
var arc_gen = d3.svg
.arc()
.innerRadius(this.radius_bounds[0])
.outerRadius(this.radius_bounds[1]);
var // Attach data to group element.
chroms_elts = track_parent_elt
.selectAll("g")
.data(genome_arcs)
.enter()
.append("svg:g");
var // Draw chrom arcs/paths.
chroms_paths = chroms_elts
.append("path")
.attr("d", arc_gen)
.attr("class", "chrom-background")
.style("stroke", this.bg_stroke)
.style("fill", this.loading_bg_fill);
// Append titles to paths.
chroms_paths.append("title").text(function(d) {
@@ -501,12 +519,14 @@ var CircsterTrackView = Backbone.View.extend({
// -- Render track data and, when track data is rendered, apply preferences and update chrom_elts fill. --
var self = this,
data_manager = self.track.get("data_manager"),
// If track has a data manager, get deferred that resolves when data is ready.
data_ready_deferred = data_manager
? data_manager.data_is_ready()
: true;
var self = this;
var data_manager = self.track.get("data_manager");
var // If track has a data manager, get deferred that resolves when data is ready.
data_ready_deferred = data_manager
? data_manager.data_is_ready()
: true;
// When data is ready, render track.
$.when(data_ready_deferred).then(function() {
@@ -562,8 +582,9 @@ var CircsterTrackView = Backbone.View.extend({
// -- Scale increased, so render visible data with more detail. --
var self = this,
utils = new SVGUtils();
var self = this;
var utils = new SVGUtils();
// Select all chrom data and filter to operate on those that are visible.
this.parent_elt
@@ -574,11 +595,12 @@ var CircsterTrackView = Backbone.View.extend({
.each(function(d, i) {
// -- Now operating on a single path element representing chromosome data. --
var path_elt = d3.select(this),
chrom = path_elt.attr("chrom"),
chrom_region = self.genome.get_chrom_region(chrom),
data_manager = self.track.get("data_manager"),
data_deferred;
var path_elt = d3.select(this);
var chrom = path_elt.attr("chrom");
var chrom_region = self.genome.get_chrom_region(chrom);
var data_manager = self.track.get("data_manager");
var data_deferred;
// If can't get more detailed data, return.
if (!data_manager.can_get_more_detailed_data(chrom_region)) {
@@ -628,10 +650,10 @@ var CircsterTrackView = Backbone.View.extend({
* Transitions chrom data to new values (e.g new radius or data bounds).
*/
_transition_chrom_data: function() {
var track = this.track,
chrom_arcs = this.chroms_layout,
chrom_data_paths = this.parent_elt.selectAll("g>path.chrom-data"),
num_paths = chrom_data_paths[0].length;
var track = this.track;
var chrom_arcs = this.chroms_layout;
var chrom_data_paths = this.parent_elt.selectAll("g>path.chrom-data");
var num_paths = chrom_data_paths[0].length;
if (num_paths > 0) {
var self = this;
@@ -641,11 +663,13 @@ var CircsterTrackView = Backbone.View.extend({
// Map chrom data to path data, filtering out null values.
var path_data = _.reject(
_.map(genome_wide_data, function(chrom_data, i) {
var rval = null,
path_fn = self._get_path_function(
chrom_arcs[i],
chrom_data
);
var rval = null;
var path_fn = self._get_path_function(
chrom_arcs[i],
chrom_data
);
if (path_fn) {
rval = path_fn(chrom_data.data);
}
@@ -694,10 +718,10 @@ var CircsterTrackView = Backbone.View.extend({
* Render data as elements attached to svg.
*/
_render_data: function(svg) {
var self = this,
chrom_arcs = this.chroms_layout,
track = this.track,
rendered_deferred = $.Deferred();
var self = this;
var chrom_arcs = this.chroms_layout;
var track = this.track;
var rendered_deferred = $.Deferred();
// When genome-wide data is available, render data.
$.when(
@@ -722,8 +746,8 @@ var CircsterTrackView = Backbone.View.extend({
// Render each chromosome's data.
_.each(layout_and_data, function(chrom_info) {
var chrom_arc = chrom_info[0],
data = chrom_info[1];
var chrom_arc = chrom_info[0];
var data = chrom_info[1];
return self._render_chrom_data(svg, chrom_arc, data);
});
@@ -756,24 +780,26 @@ var CircsterTrackView = Backbone.View.extend({
*/
_chroms_layout: function() {
// Setup chroms layout using pie.
var chroms_info = this.genome.get_chroms_info(),
pie_layout = d3.layout
.pie()
.value(function(d) {
return d.len;
})
.sort(null),
init_arcs = pie_layout(chroms_info),
gap_per_chrom = 2 * Math.PI * this.total_gap / chroms_info.length,
chrom_arcs = _.map(init_arcs, function(arc, index) {
// For short chroms, endAngle === startAngle.
var new_endAngle = arc.endAngle - gap_per_chrom;
arc.endAngle =
new_endAngle > arc.startAngle
? new_endAngle
: arc.startAngle;
return arc;
});
var chroms_info = this.genome.get_chroms_info();
var pie_layout = d3.layout
.pie()
.value(function(d) {
return d.len;
})
.sort(null);
var init_arcs = pie_layout(chroms_info);
var gap_per_chrom = 2 * Math.PI * this.total_gap / chroms_info.length;
var chrom_arcs = _.map(init_arcs, function(arc, index) {
// For short chroms, endAngle === startAngle.
var new_endAngle = arc.endAngle - gap_per_chrom;
arc.endAngle =
new_endAngle > arc.startAngle ? new_endAngle : arc.startAngle;
return arc;
});
return chrom_arcs;
}
});
@@ -800,8 +826,9 @@ var CircsterChromLabelTrackView = CircsterTrackView.extend({
_render_data: function(svg) {
// -- Add chromosome label where it will fit; an alternative labeling mechanism
// would be nice for small chromosomes. --
var self = this,
chrom_arcs = svg.selectAll("g");
var self = this;
var chrom_arcs = svg.selectAll("g");
chrom_arcs.selectAll("path").attr("id", function(d) {
return "label-" + d.data.chrom;
@@ -827,14 +854,15 @@ var CircsterChromLabelTrackView = CircsterTrackView.extend({
/** Returns an array of tick angles and labels, given a chrom arc. */
var chromArcTicks = function(d) {
var k = (d.endAngle - d.startAngle) / d.value,
ticks = d3.range(0, d.value, 25000000).map(function(v, i) {
return {
radius: self.innerRadius,
angle: v * k + d.startAngle,
label: i === 0 ? 0 : i % 3 ? null : self.formatNum(v)
};
});
var k = (d.endAngle - d.startAngle) / d.value;
var ticks = d3.range(0, d.value, 25000000).map(function(v, i) {
return {
radius: self.innerRadius,
angle: v * k + d.startAngle,
label: i === 0 ? 0 : i % 3 ? null : self.formatNum(v)
};
});
// If there are fewer that 4 ticks, label last tick so that at least one non-zero tick is labeled.
if (ticks.length < 4) {
@@ -892,11 +920,13 @@ var CircsterQuantitativeTrackView = CircsterTrackView.extend({
* Update track when min and/or max are changed.
*/
_update_min_max: function() {
var track_config = this.track.get("config"),
new_bounds = [
track_config.get_value("min_value"),
track_config.get_value("max_value")
];
var track_config = this.track.get("config");
var new_bounds = [
track_config.get_value("min_value"),
track_config.get_value("max_value")
];
this._update_data_bounds(new_bounds);
// FIXME: this works to update tick/text bounds, but there's probably a better way to do this
@@ -926,12 +956,13 @@ var CircsterQuantitativeTrackView = CircsterTrackView.extend({
}
// There is path data, so render as path.
var parent = svg.datum(chrom_data.data),
path = parent
.append("path")
.attr("class", "chrom-data")
.attr("chrom", chrom_arc.data.chrom)
.attr("d", path_data);
var parent = svg.datum(chrom_data.data);
var path = parent
.append("path")
.attr("class", "chrom-data")
.attr("chrom", chrom_arc.data.chrom)
.attr("d", path_data);
return path;
},
@@ -985,11 +1016,12 @@ var CircsterQuantitativeTrackView = CircsterTrackView.extend({
* Render track min, max using ticks.
*/
render_labels: function() {
var self = this,
// Keep counter of visible chroms.
textTransform = function() {
return "rotate(90)";
};
var self = this;
var // Keep counter of visible chroms.
textTransform = function() {
return "rotate(90)";
};
// FIXME:
// (1) using min_max class below is needed for _update_min_max, which could be improved.
@@ -1036,18 +1068,22 @@ var CircsterQuantitativeTrackView = CircsterTrackView.extend({
}
// Transition labels to new radius bounds.
var self = this,
visibleChroms = _.filter(this.chroms_layout, function(c) {
return c.endAngle - c.startAngle > 0.08;
}),
labeledChroms = _.filter(visibleChroms, function(c, i) {
return i % 3 === 0;
}),
new_data = _.flatten(
_.map(labeledChroms, function(c) {
return self._data_bounds_ticks_fn()(c);
})
);
var self = this;
var visibleChroms = _.filter(this.chroms_layout, function(c) {
return c.endAngle - c.startAngle > 0.08;
});
var labeledChroms = _.filter(visibleChroms, function(c, i) {
return i % 3 === 0;
});
var new_data = _.flatten(
_.map(labeledChroms, function(c) {
return self._data_bounds_ticks_fn()(c);
})
);
this.parent_elt
.selectAll("g.tick")
.data(new_data)
@@ -1138,8 +1174,8 @@ var CircsterChromInteractionsTrackView = CircsterTrackView.extend({
$.when(
self.track.get("data_manager").get_genome_wide_data(self.genome)
).then(function(genome_wide_data) {
var chord_data = [],
chroms_info = self.genome.get_chroms_info();
var chord_data = [];
var chroms_info = self.genome.get_chroms_info();
// Convert chromosome data into chord data.
_.each(genome_wide_data, function(chrom_data, index) {
// Map each interaction into chord data.
@@ -1149,13 +1185,15 @@ var CircsterChromInteractionsTrackView = CircsterTrackView.extend({
) {
// Each datum is an interaction/chord.
var source_angle = self._get_region_angle(
cur_chrom,
datum[1]
),
target_angle = self._get_region_angle(
datum[3],
datum[4]
);
cur_chrom,
datum[1]
);
var target_angle = self._get_region_angle(
datum[3],
datum[4]
);
return {
source: {
startAngle: source_angle,
@@ -1218,10 +1256,11 @@ var CircsterChromInteractionsTrackView = CircsterTrackView.extend({
var Circster = Backbone.View.extend({
initialize: function() {
// -- Configure visualization --
var genome = new visualization.Genome(galaxy_config.app.genome),
vis = new visualization.GenomeVisualization(
galaxy_config.app.viz_config
);
var genome = new visualization.Genome(galaxy_config.app.genome);
var vis = new visualization.GenomeVisualization(
galaxy_config.app.viz_config
);
// Add Circster-specific config options.
vis.get("config").add([
+103 -81
View File
@@ -13,10 +13,11 @@ var UserMenuBase = Backbone.View.extend({
*/
isAcceptableValue: function($inputKey, min, max) {
//TODO: use better feedback than alert
var value = $inputKey.val(),
fieldName =
$inputKey.attr("displayLabel") ||
$inputKey.attr("id").replace("phyloViz", "");
var value = $inputKey.val();
var fieldName =
$inputKey.attr("displayLabel") ||
$inputKey.attr("id").replace("phyloViz", "");
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
@@ -58,18 +59,31 @@ var UserMenuBase = Backbone.View.extend({
* 2) Nodes must appear in other after they have expand and contracted
*/
function PhyloTreeLayout() {
var self = this,
hierarchy = d3.layout
.hierarchy()
.sort(null)
.value(null),
height = 360, // ! represents both the layout angle and the height of the layout, in px
layoutMode = "Linear",
leafHeight = 18, // height of each individual leaf node
depthSeparation = 200, // separation between nodes of different depth, in px
leafIndex = 0, // change to recurssive call
defaultDist = 0.5, // tree defaults to 0.5 dist if no dist is specified
maxTextWidth = 50; // maximum length of the text labels
var self = this; // maximum length of the text labels
var hierarchy = d3.layout
.hierarchy()
.sort(null)
.value(null);
var // ! represents both the layout angle and the height of the layout, in px
height = 360;
var layoutMode = "Linear";
var // height of each individual leaf node
leafHeight = 18;
var // separation between nodes of different depth, in px
depthSeparation = 200;
var // change to recurssive call
leafIndex = 0;
var // tree defaults to 0.5 dist if no dist is specified
defaultDist = 0.5;
var maxTextWidth = 50;
self.leafHeight = function(inputLeafHeight) {
if (typeof inputLeafHeight === "undefined") {
@@ -125,11 +139,13 @@ function PhyloTreeLayout() {
// if d is an array, replate with the first object (newick, phyloxml)
d = d[0];
}
// self is to find the depth of all the nodes, assumes root is passed in
var _nodes = hierarchy.call(self, d, i),
nodes = [],
maxDepth = 0,
numLeaves = 0;
var _nodes = hierarchy.call(self, d, i);
var nodes = [];
var maxDepth = 0;
var numLeaves = 0;
//console.debug( JSON.stringify( _nodes, null, 2 ) )
window._d = d;
window._nodes = _nodes;
@@ -168,8 +184,8 @@ function PhyloTreeLayout() {
* -- The layout will first calculate the y0 field going towards the leaves, and x0 when returning
*/
function layout(node, maxDepth, vertSeparation, parent) {
var children = node.children,
sumChildVertSeparation = 0;
var children = node.children;
var sumChildVertSeparation = 0;
// calculation of node's dist from parents, going down.
var dist = node.dist || defaultDist;
@@ -351,8 +367,8 @@ var PhylovizLayoutBase = Backbone.View.extend({
* AND possibly when the tree is edited.
*/
updateAndRender: function(source) {
var vis = d3.select(".vis"),
self = this;
var vis = d3.select(".vis");
var self = this;
source = source || self.model.root;
self.renderNodes(source);
@@ -441,8 +457,8 @@ var PhylovizLayoutBase = Backbone.View.extend({
$(".tooltip").remove(); //clean up tooltip, just in case its listeners are removed by d3
$(".node")
.attr("data-original-title", function() {
var d = this.__data__,
annotation = d.annotation || "None";
var d = this.__data__;
var annotation = d.annotation || "None";
return d
? (d.name ? d.name + "<br/>" : "") +
"Dist: " +
@@ -492,18 +508,19 @@ var PhylovizLinearView = PhylovizLayoutBase.extend({
* Renders the nodes base on Linear layout.
*/
renderNodes: function(source) {
var self = this,
fontSize = self.model.get("fontSize") + "px";
var self = this;
var fontSize = self.model.get("fontSize") + "px";
// assigning properties from models
self.tree
.separation(self.model.get("separation"))
.leafHeight(self.model.get("leafHeight"));
var duration = 500,
nodes = self.tree
.separation(self.model.get("separation"))
.nodes(self.model.root);
var duration = 500;
var nodes = self.tree
.separation(self.model.get("separation"))
.nodes(self.model.root);
var node = self.vis.selectAll("g.node").data(nodes, function(d) {
return d.name + d.id || (d.id = ++self.i);
@@ -706,17 +723,18 @@ var PhylovizView = Backbone.View.extend({
* Uses d3.zoom events, and extend them to allow manual updates and keeping states in model
*/
zoomAndPan: function(event) {
var zoomParams, translateParams;
var zoomParams;
var translateParams;
if (typeof event !== "undefined") {
zoomParams = event.zoom;
translateParams = event.translate;
}
var self = this,
scaleFactor = self.zoomFunc.scale(),
translationCoor = self.zoomFunc.translate(),
zoomStatement = "",
translateStatement = "";
var self = this;
var scaleFactor = self.zoomFunc.scale();
var translationCoor = self.zoomFunc.translate();
var zoomStatement = "";
var translateStatement = "";
// Do manual scaling.
switch (zoomParams) {
@@ -779,8 +797,8 @@ var PhylovizView = Backbone.View.extend({
* Primes the Ajax URL to load another Nexus tree
*/
reloadViz: function() {
var self = this,
treeIndex = $("#phylovizNexSelector :selected").val();
var self = this;
var treeIndex = $("#phylovizNexSelector :selected").val();
$.getJSON(
self.phyloTree.get("dataset").url(),
{
@@ -872,37 +890,39 @@ var HeaderButtons = Backbone.View.extend({
},
initNavBtns: function() {
var self = this,
navMenu = mod_icon_btn.create_icon_buttons_menu(
[
{
icon_class: "zoom-in",
title: "Zoom in",
on_click: function() {
self.phylovizView.zoomAndPan({ zoom: "+" });
}
},
{
icon_class: "zoom-out",
title: "Zoom out",
on_click: function() {
self.phylovizView.zoomAndPan({ zoom: "-" });
}
},
{
icon_class: "arrow-circle",
title: "Reset Zoom/Pan",
on_click: function() {
self.phylovizView.zoomAndPan({
zoom: "reset"
});
}
}
],
var self = this;
var navMenu = mod_icon_btn.create_icon_buttons_menu(
[
{
tooltip_config: { placement: "bottom" }
icon_class: "zoom-in",
title: "Zoom in",
on_click: function() {
self.phylovizView.zoomAndPan({ zoom: "+" });
}
},
{
icon_class: "zoom-out",
title: "Zoom out",
on_click: function() {
self.phylovizView.zoomAndPan({ zoom: "-" });
}
},
{
icon_class: "arrow-circle",
title: "Reset Zoom/Pan",
on_click: function() {
self.phylovizView.zoomAndPan({
zoom: "reset"
});
}
}
);
],
{
tooltip_config: { placement: "bottom" }
}
);
$("#phyloVizNavBtns").append(navMenu.$el);
}
});
@@ -1041,8 +1061,8 @@ var NodeSelectionView = UserMenuBase.extend({
* For turning on and off the child elements
*/
toggleUI: function() {
var self = this,
checked = self.UI.enableEdit.is(":checked");
var self = this;
var checked = self.UI.enableEdit.is(":checked");
if (!checked) {
self.cancelChanges();
@@ -1064,8 +1084,8 @@ var NodeSelectionView = UserMenuBase.extend({
* Reverting to previous values in case user change their minds
*/
cancelChanges: function() {
var self = this,
node = self.phyloTree.get("selectedNode");
var self = this;
var node = self.phyloTree.get("selectedNode");
if (node) {
$.each(self.valuesOfConcern, function(key, value) {
self.UI[key].val(node[key]);
@@ -1077,8 +1097,8 @@ var NodeSelectionView = UserMenuBase.extend({
* Changing the data in the underlying tree with user-specified values
*/
updateNodes: function() {
var self = this,
node = self.phyloTree.get("selectedNode");
var self = this;
var node = self.phyloTree.get("selectedNode");
if (node) {
if (
!self.isAcceptableValue(self.UI.dist, 0, 1) ||
@@ -1106,12 +1126,14 @@ var PhyloVizSearch = UserMenuBase.extend({
var self = this;
$("#phyloVizSearchBtn").on("click", function() {
var searchTerm = $("#phyloVizSearchTerm"),
searchConditionVal = $("#phyloVizSearchCondition")
.val()
.split("-"),
attr = searchConditionVal[0],
condition = searchConditionVal[1];
var searchTerm = $("#phyloVizSearchTerm");
var searchConditionVal = $("#phyloVizSearchCondition")
.val()
.split("-");
var attr = searchConditionVal[0];
var condition = searchConditionVal[1];
self.hasIllegalJsonCharacters(searchTerm);
if (attr === "dist") {
+175 -152
View File
@@ -110,37 +110,38 @@ var ToolParameterTree = Backbone.Model.extend({
samples: param.get_samples()
};
});
var node_id = 0,
// Creates tree data recursively.
create_tree_data = function(params_samples, index) {
var param_samples = params_samples[index],
param = param_samples.param,
param_label = param.get("label"),
settings = param_samples.samples;
var node_id = 0;
// Create leaves when last parameter setting is reached.
if (params_samples.length - 1 === index) {
return _.map(settings, function(setting) {
return {
id: node_id++,
name: setting,
param: param,
value: setting
};
});
}
var // Creates tree data recursively.
create_tree_data = function(params_samples, index) {
var param_samples = params_samples[index],
param = param_samples.param,
param_label = param.get("label"),
settings = param_samples.samples;
// Recurse to handle other parameters.
// Create leaves when last parameter setting is reached.
if (params_samples.length - 1 === index) {
return _.map(settings, function(setting) {
return {
id: node_id++,
name: setting,
param: param,
value: setting,
children: create_tree_data(params_samples, index + 1)
value: setting
};
});
};
}
// Recurse to handle other parameters.
return _.map(settings, function(setting) {
return {
id: node_id++,
name: setting,
param: param,
value: setting,
children: create_tree_data(params_samples, index + 1)
};
});
};
this.set("tree_data", {
name: "Root",
@@ -191,30 +192,32 @@ var ToolParameterTree = Backbone.Model.extend({
}
// Walk subtree starting at clicked node to get full list of settings.
var self = this,
get_settings = function(node, settings) {
// Add setting for this node. Root node does not have a param,
// however.
if (node.param) {
settings[node.param.get("name")] = node.value;
}
var self = this;
if (!node.children) {
// At leaf node, so return settings.
return new ToolInputsSettings({
inputs: self.get("tool").get("inputs"),
values: settings
});
} else {
// At interior node: return list of subtree settings.
return _.flatten(
_.map(node.children, function(c) {
return get_settings(c, _.clone(settings));
})
);
}
},
all_settings = get_settings(target_node, fixed_settings);
var get_settings = function(node, settings) {
// Add setting for this node. Root node does not have a param,
// however.
if (node.param) {
settings[node.param.get("name")] = node.value;
}
if (!node.children) {
// At leaf node, so return settings.
return new ToolInputsSettings({
inputs: self.get("tool").get("inputs"),
values: settings
});
} else {
// At interior node: return list of subtree settings.
return _.flatten(
_.map(node.children, function(c) {
return get_settings(c, _.clone(settings));
})
);
}
};
var all_settings = get_settings(target_node, fixed_settings);
// If user clicked on leaf, settings is a single dict. Convert to array for simplicity.
if (!_.isArray(all_settings)) {
@@ -243,8 +246,9 @@ var ToolParameterTree = Backbone.Model.extend({
};
// Get node's parents.
var parents = [],
cur_parent = node.parent;
var parents = [];
var cur_parent = node.parent;
while (cur_parent) {
parents.push(cur_parent);
cur_parent = cur_parent.parent;
@@ -257,12 +261,13 @@ var ToolParameterTree = Backbone.Model.extend({
* Returns the leaf that corresponds to a settings collection.
*/
get_leaf: function(settings) {
var cur_node = this.get("tree_data"),
find_child = function(children) {
return _.find(children, function(child) {
return settings[child.param.get("name")] === child.value;
});
};
var cur_node = this.get("tree_data");
var find_child = function(children) {
return _.find(children, function(child) {
return settings[child.param.get("name")] === child.value;
});
};
while (cur_node.children) {
cur_node = find_child(cur_node.children);
@@ -314,8 +319,8 @@ var SweepsterTrack = Backbone.Model.extend({
},
same_settings: function(a_track) {
var this_settings = this.get("settings"),
other_settings = a_track.get("settings");
var this_settings = this.get("settings");
var other_settings = a_track.get("settings");
for (var prop in this_settings) {
if (
!other_settings[prop] ||
@@ -423,15 +428,19 @@ var SweepsterTrackView = Backbone.View.extend({
render: function() {
// Render settings icon and popup.
// TODO: use template.
var settings = this.model.get("settings"),
values = settings.get("values"),
settings_td = $("<td/>")
.addClass("settings")
.appendTo(this.$el),
settings_div = $("<div/>")
.addClass("track-info")
.hide()
.appendTo(settings_td);
var settings = this.model.get("settings");
var values = settings.get("values");
var settings_td = $("<td/>")
.addClass("settings")
.appendTo(this.$el);
var settings_div = $("<div/>")
.addClass("track-info")
.hide()
.appendTo(settings_td);
settings_div.append(
$("<div/>")
.css("font-weight", "bold")
@@ -442,14 +451,16 @@ var SweepsterTrackView = Backbone.View.extend({
input.get("label") + ": " + values[input.get("name")] + "<br/>"
);
});
var self = this,
run_on_dataset_button = $("<button/>")
.appendTo(settings_div)
.text("Run on complete dataset")
.click(function() {
settings_div.toggle();
self.trigger("run_on_dataset", settings);
});
var self = this;
var run_on_dataset_button = $("<button/>")
.appendTo(settings_div)
.text("Run on complete dataset")
.click(function() {
settings_div.toggle();
self.trigger("run_on_dataset", settings);
});
var icon_menu = mod_icon_btn.create_icon_buttons_menu([
{
title: "Settings",
@@ -493,10 +504,10 @@ var SweepsterTrackView = Backbone.View.extend({
* Draw tiles for regions.
*/
draw_tiles: function() {
var self = this,
track = this.model.get("track"),
regions = this.model.get("regions"),
tile_containers = this.$el.find("td.tile");
var self = this;
var track = this.model.get("track");
var regions = this.model.get("regions");
var tile_containers = this.$el.find("td.tile");
// Do nothing if track is not defined.
if (!track) {
@@ -507,9 +518,9 @@ var SweepsterTrackView = Backbone.View.extend({
$.when(track.data_manager.data_is_ready()).then(function(data_ok) {
// Draw tile for each region.
regions.each(function(region, index) {
var resolution = region.length() / self.TILE_LEN,
w_scale = 1 / resolution,
mode = self.model.get("mode");
var resolution = region.length() / self.TILE_LEN;
var w_scale = 1 / resolution;
var mode = self.model.get("mode");
$.when(
track.data_manager.get_data(region, mode, resolution, {})
).then(function(tile_data) {
@@ -559,10 +570,10 @@ var ToolInputValOrSweepView = Backbone.View.extend({
},
render: function() {
var input = this.model,
type = input.get("type"),
single_input_row = this.$el.find(".form-row-input"),
sweep_inputs_row = null;
var input = this.model;
var type = input.get("type");
var single_input_row = this.$el.find(".form-row-input");
var sweep_inputs_row = null;
// Update tool inputs as single input changes.
single_input_row.find(":input").change(function() {
@@ -576,11 +587,12 @@ var ToolInputValOrSweepView = Backbone.View.extend({
);
} else if (input instanceof tools.SelectToolParameter) {
var options = _.map(this.$el.find("select option"), function(
option
) {
return $(option).val();
}),
options_text = options.join(", ");
option
) {
return $(option).val();
});
var options_text = options.join(", ");
sweep_inputs_row = $(
_.template(this.select_input_template)({
options: options_text
@@ -590,35 +602,37 @@ var ToolInputValOrSweepView = Backbone.View.extend({
sweep_inputs_row.insertAfter(single_input_row);
// Add buttons for adding/removing parameter.
var self = this,
menu = mod_icon_btn.create_icon_buttons_menu(
[
{
title: "Add parameter to tree",
icon_class: "plus-button",
on_click: function() {
input.set("in_ptree", true);
single_input_row.hide();
sweep_inputs_row.show();
$(this).hide();
self.$el.find(".icon-button.toggle").show();
}
},
{
title: "Remove parameter from tree",
icon_class: "toggle",
on_click: function() {
// Remove parameter from tree params where name matches clicked paramter.
input.set("in_ptree", false);
sweep_inputs_row.hide();
single_input_row.show();
$(this).hide();
self.$el.find(".icon-button.plus-button").show();
}
var self = this;
var menu = mod_icon_btn.create_icon_buttons_menu(
[
{
title: "Add parameter to tree",
icon_class: "plus-button",
on_click: function() {
input.set("in_ptree", true);
single_input_row.hide();
sweep_inputs_row.show();
$(this).hide();
self.$el.find(".icon-button.toggle").show();
}
],
{}
);
},
{
title: "Remove parameter from tree",
icon_class: "toggle",
on_click: function() {
// Remove parameter from tree params where name matches clicked paramter.
input.set("in_ptree", false);
sweep_inputs_row.hide();
single_input_row.show();
$(this).hide();
self.$el.find(".icon-button.plus-button").show();
}
}
],
{}
);
this.$el.prepend(menu.$el);
// Show/hide input rows and icons depending on whether parameter is in the tree.
@@ -655,8 +669,9 @@ var ToolParameterTreeDesignView = Backbone.View.extend({
this.$el.append(tool_form_view.$el);
// Set up views for each tool input.
var self = this,
inputs = self.model.get("tool").get("inputs");
var self = this;
var inputs = self.model.get("tool").get("inputs");
this.$el
.find(".form-row")
.not(".form-actions")
@@ -708,8 +723,8 @@ var ToolParameterTreeView = Backbone.View.extend({
// Setup and add labels for tree levels.
var param_depths = _.uniq(_.pluck(nodes, "y"));
_.each(tree_params, function(param, index) {
var x = param_depths[index + 1],
center_left = $("#center").position().left;
var x = param_depths[index + 1];
var center_left = $("#center").position().left;
self.$el.append(
$("<div>")
.addClass("label")
@@ -879,9 +894,10 @@ var SweepsterVisualizationView = Backbone.View.extend({
$("#left").append(tree_design_view.$el);
// Render track collection container/view in right panel.
var self = this,
regions = self.model.get("regions"),
tr = $("<tr/>").appendTo(this.track_collection_container);
var self = this;
var regions = self.model.get("regions");
var tr = $("<tr/>").appendTo(this.track_collection_container);
regions.each(function(region) {
tr.append($("<th>").text(region.toString()));
@@ -901,17 +917,18 @@ var SweepsterVisualizationView = Backbone.View.extend({
// -- Render help and tool parameter tree in center panel. --
// Help includes text and a close button.
var help_div = $(this.helpText).addClass("help"),
close_button = mod_icon_btn.create_icon_buttons_menu([
{
title: "Close",
icon_class: "cross-circle",
on_click: function() {
$(".tooltip").remove();
help_div.remove();
}
var help_div = $(this.helpText).addClass("help");
var close_button = mod_icon_btn.create_icon_buttons_menu([
{
title: "Close",
icon_class: "cross-circle",
on_click: function() {
$(".tooltip").remove();
help_div.remove();
}
]);
}
]);
help_div.prepend(close_button.$el.css("float", "right"));
$("#center").append(help_div);
@@ -966,8 +983,9 @@ var SweepsterVisualizationView = Backbone.View.extend({
);
// Create mode selection popup. Mode selection changes default mode and mode for all tracks.
var modes = ["Squish", "Pack"],
mode_mapping = {};
var modes = ["Squish", "Pack"];
var mode_mapping = {};
_.each(modes, function(mode) {
mode_mapping[mode] = function() {
self.model.set("default_mode", mode);
@@ -991,9 +1009,9 @@ var SweepsterVisualizationView = Backbone.View.extend({
},
run_tool_on_dataset: function(settings) {
var tool = this.model.get("tool"),
tool_name = tool.get("name"),
dataset = this.model.get("dataset");
var tool = this.model.get("tool");
var tool_name = tool.get("name");
var dataset = this.model.get("dataset");
tool.set_input_values(settings.get("values"));
$.when(tool.rerun(dataset)).then(function(outputs) {
// TODO.
@@ -1017,8 +1035,8 @@ var SweepsterVisualizationView = Backbone.View.extend({
* Add track to model and view.
*/
add_track: function(pm_track) {
var self = this,
param_tree = this.model.get("parameter_tree");
var self = this;
var param_tree = this.model.get("parameter_tree");
// Add track to model.
self.model.add_track(pm_track);
@@ -1068,18 +1086,22 @@ var SweepsterVisualizationView = Backbone.View.extend({
*/
handle_node_clicks: function() {
// When node clicked in tree, run tool and add tracks to model.
var self = this,
param_tree = this.model.get("parameter_tree"),
regions = this.model.get("regions"),
node = d3
.select(this.tool_param_tree_view.$el[0])
.selectAll("g.node");
var self = this;
var param_tree = this.model.get("parameter_tree");
var regions = this.model.get("regions");
var node = d3
.select(this.tool_param_tree_view.$el[0])
.selectAll("g.node");
node.on("click", function(d, i) {
// Get all settings corresponding to node.
var tool = self.model.get("tool"),
dataset = self.model.get("dataset"),
all_settings = param_tree.get_node_settings(d),
run_jobs_deferred = $.Deferred();
var tool = self.model.get("tool");
var dataset = self.model.get("dataset");
var all_settings = param_tree.get_node_settings(d);
var run_jobs_deferred = $.Deferred();
// Do not allow 10+ jobs to be run.
if (all_settings.length >= 10) {
@@ -1131,8 +1153,9 @@ var SweepsterVisualizationView = Backbone.View.extend({
// HACKish: output is an HDA with track config attribute. To create a track
// that works correctly with Backbone relational, it is necessary to
// use a modified version of the track config.
var dataset = output.first(),
track_config = dataset.get("track_config");
var dataset = output.first();
var track_config = dataset.get("track_config");
// Set dataset to be the tool's output.
track_config.dataset = dataset;
// Set tool to null so that it is not unpacked; unpacking it messes with
+148 -132
View File
@@ -69,18 +69,19 @@ var TracksterUI = Base.extend({
// FIXME: give unique IDs to Drawables and save overview as ID.
var overview_track_name = view.overview_drawable
? view.overview_drawable.config.get_value("name")
: null,
viz_config = {
view: view.to_dict(),
viewport: {
chrom: view.chrom,
start: view.low,
end: view.high,
overview: overview_track_name
},
bookmarks: bookmarks
};
? view.overview_drawable.config.get_value("name")
: null;
var viz_config = {
view: view.to_dict(),
viewport: {
chrom: view.chrom,
start: view.low,
end: view.high,
overview: overview_track_name
},
bookmarks: bookmarks
};
// Make call to save visualization.
return $.ajax({
@@ -126,81 +127,83 @@ var TracksterUI = Base.extend({
* Create button menu
*/
createButtonMenu: function() {
var self = this,
menu = mod_icon_btn.create_icon_buttons_menu(
[
{
icon_class: "plus-button",
title: "Add tracks",
on_click: function() {
visualization.select_datasets(
{ dbkey: view.dbkey },
function(new_tracks) {
_.each(new_tracks, function(track) {
view.add_drawable(
tracks.object_from_template(
track,
view,
view
)
);
});
}
);
}
},
{
icon_class: "block--plus",
title: "Add group",
on_click: function() {
view.add_drawable(
new tracks.DrawableGroup(view, view, {
name: "New Group"
})
);
}
},
{
icon_class: "bookmarks",
title: "Bookmarks",
on_click: function() {
// HACK -- use style to determine if panel is hidden and hide/show accordingly.
force_right_panel(
$("div#right").css("right") == "0px"
? "hide"
: "show"
);
}
},
{
icon_class: "globe",
title: "Circster",
on_click: function() {
window.location =
self.baseURL +
"visualization/circster?id=" +
view.vis_id;
}
},
{
icon_class: "disk--arrow",
title: "Save",
on_click: function() {
self.save_viz();
}
},
{
icon_class: "cross-circle",
title: "Close",
on_click: function() {
self.handle_unsaved_changes(view);
}
}
],
var self = this;
var menu = mod_icon_btn.create_icon_buttons_menu(
[
{
tooltip_config: { placement: "bottom" }
icon_class: "plus-button",
title: "Add tracks",
on_click: function() {
visualization.select_datasets(
{ dbkey: view.dbkey },
function(new_tracks) {
_.each(new_tracks, function(track) {
view.add_drawable(
tracks.object_from_template(
track,
view,
view
)
);
});
}
);
}
},
{
icon_class: "block--plus",
title: "Add group",
on_click: function() {
view.add_drawable(
new tracks.DrawableGroup(view, view, {
name: "New Group"
})
);
}
},
{
icon_class: "bookmarks",
title: "Bookmarks",
on_click: function() {
// HACK -- use style to determine if panel is hidden and hide/show accordingly.
force_right_panel(
$("div#right").css("right") == "0px"
? "hide"
: "show"
);
}
},
{
icon_class: "globe",
title: "Circster",
on_click: function() {
window.location =
self.baseURL +
"visualization/circster?id=" +
view.vis_id;
}
},
{
icon_class: "disk--arrow",
title: "Save",
on_click: function() {
self.save_viz();
}
},
{
icon_class: "cross-circle",
title: "Close",
on_click: function() {
self.handle_unsaved_changes(view);
}
}
);
],
{
tooltip_config: { placement: "bottom" }
}
);
this.buttonMenu = menu;
return menu;
},
@@ -210,40 +213,45 @@ var TracksterUI = Base.extend({
*/
add_bookmark: function(position, annotation, editable) {
// Create HTML.
var bookmarks_container = $("#right .unified-panel-body"),
new_bookmark = $("<div/>")
.addClass("bookmark")
.appendTo(bookmarks_container);
var bookmarks_container = $("#right .unified-panel-body");
var new_bookmark = $("<div/>")
.addClass("bookmark")
.appendTo(bookmarks_container);
var 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 = $("<div/>")
.text(annotation)
.appendTo(new_bookmark);
.addClass("position")
.appendTo(new_bookmark);
var position_link = $("<a href=''/>")
.text(position)
.appendTo(position_div)
.click(function() {
view.go_to(position);
return false;
});
var annotation_div = $("<div/>")
.text(annotation)
.appendTo(new_bookmark);
// If editable, enable bookmark deletion and annotation editing.
if (editable) {
var delete_icon_container = $("<div/>")
.addClass("delete-icon-container")
.prependTo(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);
.addClass("delete-icon-container")
.prependTo(new_bookmark)
.click(function() {
// Remove bookmark.
new_bookmark.slideUp("fast");
new_bookmark.remove();
view.has_changes = true;
return false;
});
var delete_icon = $("<a href=''/>")
.addClass("icon-button delete")
.appendTo(delete_icon_container);
annotation_div
.make_text_editable({
num_rows: 3,
@@ -268,18 +276,20 @@ var TracksterUI = Base.extend({
editable
) {
// Create view.
var self = this,
view = new tracks.TracksterView(
_.extend(view_config, { header: false })
);
var self = this;
var view = new tracks.TracksterView(
_.extend(view_config, { header: false })
);
view.editor = true;
$.when(view.load_chroms_deferred).then(function(chrom_info) {
// Viewport config.
if (viewport_config) {
var chrom = viewport_config.chrom,
start = viewport_config.start,
end = viewport_config.end,
overview_drawable_name = viewport_config.overview;
var chrom = viewport_config.chrom;
var start = viewport_config.start;
var end = viewport_config.end;
var overview_drawable_name = viewport_config.overview;
if (chrom && start !== undefined && end) {
view.change_chrom(chrom, start, end);
@@ -295,7 +305,10 @@ var TracksterUI = Base.extend({
// Add drawables to view.
if (drawables_config) {
// FIXME: can from_dict() be used to create view and add drawables?
var drawable_config, drawable_type, drawable;
var drawable_config;
var drawable_type;
var drawable;
for (var i = 0; i < drawables_config.length; i++) {
view.add_drawable(
tracks.object_from_template(
@@ -461,14 +474,16 @@ var TracksterView = Backbone.View.extend({
choose_existing_or_new: function() {
var self = this;
var dbkey = query_string.get("dbkey"),
listTracksParams = {},
dataset_params = {
dbkey: dbkey,
dataset_id: query_string.get("dataset_id"),
hda_ldda: query_string.get("hda_ldda"),
gene_region: query_string.get("gene_region")
};
var dbkey = query_string.get("dbkey");
var listTracksParams = {};
var dataset_params = {
dbkey: dbkey,
dataset_id: query_string.get("dataset_id"),
hda_ldda: query_string.get("hda_ldda"),
gene_region: query_string.get("gene_region")
};
if (dbkey) {
listTracksParams["f-dbkey"] = dbkey;
}
@@ -697,8 +712,9 @@ var TracksterView = Backbone.View.extend({
// initialize icons
$("#add-bookmark-button").click(function() {
// add new bookmark.
var position = view.chrom + ":" + view.low + "-" + view.high,
annotation = "Bookmark description";
var position = view.chrom + ":" + view.low + "-" + view.high;
var annotation = "Bookmark description";
return ui.add_bookmark(position, annotation, true);
});
+66 -52
View File
@@ -68,12 +68,14 @@ var NumberFilter = function(obj_dict) {
// Enable users to edit parameter's value via a text box.
var edit_slider_values = function(container, span, slider) {
container.click(function() {
var cur_value = span.text(),
max = parseFloat(slider.slider("option", "max")),
input_size =
max <= 1 ? 4 : max <= 1000000 ? max.toString().length : 6,
multi_value = false,
slider_row = $(this).parents(".slider-row");
var cur_value = span.text();
var max = parseFloat(slider.slider("option", "max"));
var input_size =
max <= 1 ? 4 : max <= 1000000 ? max.toString().length : 6;
var multi_value = false;
var slider_row = $(this).parents(".slider-row");
// Row now has input.
slider_row.addClass("input");
@@ -110,16 +112,19 @@ var NumberFilter = function(obj_dict) {
// Enter/return key initiates callback. If new value(s) are in slider range,
// change value (which calls slider's change() function).
//
var slider_min = slider.slider("option", "min"),
slider_max = slider.slider("option", "max"),
invalid = function(a_val) {
return (
isNaN(a_val) ||
a_val > slider_max ||
a_val < slider_min
);
},
new_value = $(this).val();
var slider_min = slider.slider("option", "min");
var slider_max = slider.slider("option", "max");
var invalid = function(a_val) {
return (
isNaN(a_val) ||
a_val > slider_max ||
a_val < slider_min
);
};
var new_value = $(this).val();
if (!multi_value) {
new_value = parseFloat(new_value);
if (invalid(new_value)) {
@@ -171,19 +176,23 @@ var NumberFilter = function(obj_dict) {
// Set up filter label (name, values).
var filter_label = $("<div/>")
.addClass("elt-label")
.appendTo(filter.parent_div),
name_span = $("<span/>")
.addClass("slider-name")
.text(filter.name + " ")
.appendTo(filter_label),
values_span = $("<span/>").text(this.low + "-" + this.high),
values_span_container = $("<span/>")
.addClass("slider-value")
.appendTo(filter_label)
.append("[")
.append(values_span)
.append("]");
.addClass("elt-label")
.appendTo(filter.parent_div);
var name_span = $("<span/>")
.addClass("slider-name")
.text(filter.name + " ")
.appendTo(filter_label);
var values_span = $("<span/>").text(this.low + "-" + this.high);
var values_span_container = $("<span/>")
.addClass("slider-value")
.appendTo(filter_label)
.append("[")
.append(values_span)
.append("]");
filter.values_span = values_span;
// Set up slider for filter.
@@ -439,8 +448,8 @@ extend(NumberFilter.prototype, {
this.parent_div.hide();
}
var slider_min = this.slider.slider("option", "min"),
slider_max = this.slider.slider("option", "max");
var slider_min = this.slider.slider("option", "min");
var slider_max = this.slider.slider("option", "max");
if (this.min < slider_min || this.max > slider_max) {
// Update slider min, max, step.
this.slider.slider("option", "min", this.min);
@@ -501,11 +510,13 @@ var FiltersManager = function(track, obj_dict) {
if (obj_dict && "filters" in obj_dict) {
// Second condition needed for backward compatibility.
var alpha_filter_name =
"alpha_filter" in obj_dict ? obj_dict.alpha_filter : null,
height_filter_name =
"height_filter" in obj_dict ? obj_dict.height_filter : null,
filters_dict = obj_dict.filters,
filter;
"alpha_filter" in obj_dict ? obj_dict.alpha_filter : null;
var height_filter_name =
"height_filter" in obj_dict ? obj_dict.height_filter : null;
var filters_dict = obj_dict.filters;
var filter;
for (var i = 0; i < filters_dict.length; i++) {
if (filters_dict[i].type === "number") {
filter = new NumberFilter(filters_dict[i]);
@@ -561,9 +572,9 @@ extend(FiltersManager.prototype, {
* Returns dictionary for manager.
*/
to_dict: function() {
var obj_dict = {},
filter_dicts = [],
filter;
var obj_dict = {};
var filter_dicts = [];
var filter;
// Include individual filter states.
for (var i = 0; i < this.filters.length; i++) {
@@ -648,9 +659,10 @@ extend(FiltersManager.prototype, {
// Find and group active filters. Active filters are those being used to hide data.
// Filters with the same tool id are grouped.
//
var active_filters = {},
filter,
tool_filter_conditions;
var active_filters = {};
var filter;
var tool_filter_conditions;
for (var i = 0; i < this.filters.length; i++) {
filter = this.filters[i];
if (filter.tool_id) {
@@ -693,16 +705,18 @@ extend(FiltersManager.prototype, {
// iteratively application.
(function run_filter(input_dataset_id, filters) {
var // Set up filtering info and params.
filter_tuple = filters[0],
tool_id = filter_tuple[0],
tool_filters = filter_tuple[1],
tool_filter_str = "(" + tool_filters.join(") and (") + ")",
url_params = {
cond: tool_filter_str,
input: input_dataset_id,
target_dataset_id: input_dataset_id,
tool_id: tool_id
};
filter_tuple = filters[0];
var tool_id = filter_tuple[0];
var tool_filters = filter_tuple[1];
var tool_filter_str = "(" + tool_filters.join(") and (") + ")";
var url_params = {
cond: tool_filter_str,
input: input_dataset_id,
target_dataset_id: input_dataset_id,
tool_id: tool_id
};
// Remove current filter.
filters = filters.slice(1);
+369 -312
View File
@@ -1,22 +1,24 @@
import * as _ from "libs/underscore";
/**
* Compute the type of overlap between two regions. They are assumed to be on the same chrom/contig.
* The overlap is computed relative to the second region; hence, OVERLAP_START indicates that the first
* region overlaps the start (but not the end) of the second region.
* NOTE: Coordinates are assumed to be in BED format: half open (start is closed, end is open).
*/
var BEFORE = 1001,
CONTAINS = 1002,
OVERLAP_START = 1003,
OVERLAP_END = 1004,
CONTAINED_BY = 1005,
AFTER = 1006;
var BEFORE = 1001;
var CONTAINS = 1002;
var OVERLAP_START = 1003;
var OVERLAP_END = 1004;
var CONTAINED_BY = 1005;
var AFTER = 1006;
var compute_overlap = function(first_region, second_region) {
var first_start = first_region[0],
first_end = first_region[1],
second_start = second_region[0],
second_end = second_region[1],
overlap;
var first_start = first_region[0];
var first_end = first_region[1];
var second_start = second_region[0];
var second_end = second_region[1];
var overlap;
if (first_start < second_start) {
if (first_end <= second_start) {
overlap = BEFORE;
@@ -83,9 +85,10 @@ var drawDownwardEquilateralTriangle = function(
side_len
) {
// Compute other two points of triangle.
var x1 = down_vertex_x - side_len / 2,
x2 = down_vertex_x + side_len / 2,
y = down_vertex_y - Math.sqrt(side_len * 3 / 2);
var x1 = down_vertex_x - side_len / 2;
var x2 = down_vertex_x + side_len / 2;
var y = down_vertex_y - Math.sqrt(side_len * 3 / 2);
// Draw and fill.
ctx.beginPath();
@@ -192,14 +195,14 @@ LinePainter.prototype.default_prefs = {
};
LinePainter.prototype.draw = function(ctx, width, height, w_scale) {
var in_path = false,
min_value = this.prefs.min_value,
max_value = this.prefs.max_value,
vertical_range = max_value - min_value,
height_px = height,
view_start = this.view_start,
mode = this.mode,
data = this.data;
var in_path = false;
var min_value = this.prefs.min_value;
var max_value = this.prefs.max_value;
var vertical_range = max_value - min_value;
var height_px = height;
var view_start = this.view_start;
var mode = this.mode;
var data = this.data;
ctx.save();
@@ -213,7 +216,9 @@ LinePainter.prototype.draw = function(ctx, width, height, w_scale) {
}
ctx.beginPath();
var x_scaled, y, delta_x_pxs;
var x_scaled;
var y;
var delta_x_pxs;
if (data.length > 1) {
delta_x_pxs = _.map(data.slice(0, -1), function(d, i) {
return Math.ceil((data[i + 1][0] - data[i][0]) * w_scale);
@@ -223,14 +228,16 @@ LinePainter.prototype.draw = function(ctx, width, height, w_scale) {
}
// Painter color can be in either block_color (FeatureTrack) or color pref (LineTrack).
var painter_color = this.prefs.block_color || this.prefs.color,
// Extract RGB from preference color.
pref_color = parseInt(painter_color.slice(1), 16),
pref_r = (pref_color & 0xff0000) >> 16,
pref_g = (pref_color & 0x00ff00) >> 8,
pref_b = pref_color & 0x0000ff,
top_overflow = false,
bot_overflow = false;
var painter_color = this.prefs.block_color || this.prefs.color;
var // Extract RGB from preference color.
pref_color = parseInt(painter_color.slice(1), 16);
var pref_r = (pref_color & 0xff0000) >> 16;
var pref_g = (pref_color & 0x00ff00) >> 8;
var pref_b = pref_color & 0x0000ff;
var top_overflow = false;
var bot_overflow = false;
// Paint track.
var delta_x_px;
@@ -267,11 +274,13 @@ LinePainter.prototype.draw = function(ctx, width, height, w_scale) {
y = Math.round(y / vertical_range * height_px);
ctx.fillRect(x_scaled, y_zero, delta_x_px, -y);
} else if (mode === "Intensity") {
var saturation = (y - min_value) / vertical_range,
// Range is [pref_color, 255] where saturation = 0 --> 255 and saturation = 1 --> pref color
new_r = Math.round(pref_r + (255 - pref_r) * (1 - saturation)),
new_g = Math.round(pref_g + (255 - pref_g) * (1 - saturation)),
new_b = Math.round(pref_b + (255 - pref_b) * (1 - saturation));
var saturation = (y - min_value) / vertical_range;
var // Range is [pref_color, 255] where saturation = 0 --> 255 and saturation = 1 --> pref color
new_r = Math.round(pref_r + (255 - pref_r) * (1 - saturation));
var new_g = Math.round(pref_g + (255 - pref_g) * (1 - saturation));
var new_b = Math.round(pref_b + (255 - pref_b) * (1 - saturation));
ctx.fillStyle = "rgb(" + new_r + "," + new_g + "," + new_b + ")";
ctx.fillRect(x_scaled, 0, delta_x_px, height_px);
} else {
@@ -365,8 +374,9 @@ FeaturePositionMapper.prototype.map_feature_data = function(
*/
FeaturePositionMapper.prototype.get_feature_data = function(x, y) {
// Find slot using Y.
var slot = Math.floor((y - this.y_translation) / this.slot_height),
feature_dict;
var slot = Math.floor((y - this.y_translation) / this.slot_height);
var feature_dict;
// May not be over a slot due to padding, margin, etc.
if (!this.feature_positions[slot]) {
@@ -411,9 +421,10 @@ FeaturePainter.prototype.default_prefs = {
_.extend(FeaturePainter.prototype, {
get_required_height: function(rows_required, width) {
// y_scale is the height per row
var required_height = this.get_row_height(),
y_scale = required_height,
mode = this.mode;
var required_height = this.get_row_height();
var y_scale = required_height;
var mode = this.mode;
// If using a packing mode, need to multiply by the number of slots used
if (mode === "no_detail" || mode === "Squish" || mode === "Pack") {
required_height = rows_required * y_scale;
@@ -431,31 +442,32 @@ _.extend(FeaturePainter.prototype, {
* a FeaturePositionMapper object with information about where features were drawn.
*/
draw: function(ctx, width, height, w_scale, slots) {
var data = this.data,
view_start = this.view_start,
view_end = this.view_end;
var data = this.data;
var view_start = this.view_start;
var view_end = this.view_end;
ctx.save();
ctx.fillStyle = this.prefs.block_color;
ctx.textAlign = "right";
var y_scale = this.get_row_height(),
feature_mapper = new FeaturePositionMapper(y_scale),
x_draw_coords,
incomplete_features = [];
var y_scale = this.get_row_height();
var feature_mapper = new FeaturePositionMapper(y_scale);
var x_draw_coords;
var incomplete_features = [];
for (var i = 0, len = data.length; i < len; i++) {
var feature = data[i],
feature_uid = feature[0],
feature_start = feature[1],
feature_end = feature[2],
// Slot valid only if features are slotted and this feature is slotted;
// feature may not be due to lack of space.
slot =
slots && slots[feature_uid] !== undefined
? slots[feature_uid].slot
: null;
var feature = data[i];
var feature_uid = feature[0];
var feature_start = feature[1];
var feature_end = feature[2];
var // Slot valid only if features are slotted and this feature is slotted;
// feature may not be due to lack of space.
slot =
slots && slots[feature_uid] !== undefined
? slots[feature_uid].slot
: null;
// Draw feature if (a) mode is dense or feature is slotted (as it must be for all non-dense modes) and
// (b) there's overlap between the feature and drawing region.
@@ -517,16 +529,17 @@ _.extend(FeaturePainter.prototype, {
// Constants specific to feature tracks moved here (HACKING, these should
// basically all be configuration options)
var DENSE_TRACK_HEIGHT = 10,
NO_DETAIL_TRACK_HEIGHT = 3,
SQUISH_TRACK_HEIGHT = 5,
PACK_TRACK_HEIGHT = 10,
NO_DETAIL_FEATURE_HEIGHT = 1,
DENSE_FEATURE_HEIGHT = 9,
SQUISH_FEATURE_HEIGHT = 3,
PACK_FEATURE_HEIGHT = 9,
LABEL_SPACING = 2,
CONNECTOR_COLOR = "#ccc";
var DENSE_TRACK_HEIGHT = 10;
var NO_DETAIL_TRACK_HEIGHT = 3;
var SQUISH_TRACK_HEIGHT = 5;
var PACK_TRACK_HEIGHT = 10;
var NO_DETAIL_FEATURE_HEIGHT = 1;
var DENSE_FEATURE_HEIGHT = 9;
var SQUISH_FEATURE_HEIGHT = 3;
var PACK_FEATURE_HEIGHT = 9;
var LABEL_SPACING = 2;
var CONNECTOR_COLOR = "#ccc";
var LinkedFeaturePainter = function(
data,
@@ -558,8 +571,8 @@ _.extend(LinkedFeaturePainter.prototype, FeaturePainter.prototype, {
* Height of a single row, depends on mode
*/
get_row_height: function() {
var mode = this.mode,
height;
var mode = this.mode;
var height;
if (mode === "Dense") {
height = DENSE_TRACK_HEIGHT;
} else if (mode === "no_detail") {
@@ -587,39 +600,44 @@ _.extend(LinkedFeaturePainter.prototype, FeaturePainter.prototype, {
y_scale,
width
) {
var feature_uid = feature[0],
feature_start = feature[1],
feature_end = feature[2],
feature_name = feature[3],
feature_strand = feature[4],
// -0.5 to offset region between bases.
f_start = Math.floor(
Math.max(0, (feature_start - tile_low - 0.5) * w_scale)
),
f_end = Math.ceil(
Math.min(
width,
Math.max(0, (feature_end - tile_low - 0.5) * w_scale)
)
),
draw_start = f_start,
draw_end = f_end,
y_start =
(mode === "Dense" ? 0 : 0 + slot) * y_scale +
this.get_top_padding(width),
thickness,
y_start,
thick_start = null,
thick_end = null,
// TODO: is there any reason why block, label color cannot be set at the Painter level?
// For now, assume '.' === '+'
block_color =
!feature_strand ||
feature_strand === "+" ||
feature_strand === "."
? this.prefs.block_color
: this.prefs.reverse_strand_color,
label_color = this.prefs.label_color;
var feature_uid = feature[0];
var feature_start = feature[1];
var feature_end = feature[2];
var feature_name = feature[3];
var feature_strand = feature[4];
var // -0.5 to offset region between bases.
f_start = Math.floor(
Math.max(0, (feature_start - tile_low - 0.5) * w_scale)
);
var f_end = Math.ceil(
Math.min(
width,
Math.max(0, (feature_end - tile_low - 0.5) * w_scale)
)
);
var draw_start = f_start;
var draw_end = f_end;
var y_start =
(mode === "Dense" ? 0 : 0 + slot) * y_scale +
this.get_top_padding(width);
var thickness;
var y_start;
var thick_start = null;
var thick_end = null;
var // TODO: is there any reason why block, label color cannot be set at the Painter level?
// For now, assume '.' === '+'
block_color =
!feature_strand || feature_strand === "+" || feature_strand === "."
? this.prefs.block_color
: this.prefs.reverse_strand_color;
var label_color = this.prefs.label_color;
// Set global alpha.
ctx.globalAlpha = this.alpha_scaler.gen_val(feature);
@@ -641,11 +659,13 @@ _.extend(LinkedFeaturePainter.prototype, FeaturePainter.prototype, {
} else {
// Mode is either Squish or Pack:
// Feature details.
var feature_ts = feature[5],
feature_te = feature[6],
feature_blocks = feature[7],
// Whether we are drawing full height or squished features
full_height = true;
var feature_ts = feature[5];
var feature_te = feature[6];
var feature_blocks = feature[7];
var // Whether we are drawing full height or squished features
full_height = true;
if (feature_ts && feature_te) {
thick_start = Math.floor(
@@ -660,7 +680,9 @@ _.extend(LinkedFeaturePainter.prototype, FeaturePainter.prototype, {
}
// Set vars that depend on mode.
var thin_height, thick_height;
var thin_height;
var thick_height;
if (mode === "Squish") {
thin_height = 1;
thick_height = SQUISH_FEATURE_HEIGHT;
@@ -712,7 +734,9 @@ _.extend(LinkedFeaturePainter.prototype, FeaturePainter.prototype, {
//
// Compute y axis start position and height
var cur_y_start, cur_height;
var cur_y_start;
var cur_height;
if (mode === "Squish" || mode === "Dense") {
cur_y_start =
y_start + Math.floor(SQUISH_FEATURE_HEIGHT / 2) + 1;
@@ -759,19 +783,22 @@ _.extend(LinkedFeaturePainter.prototype, FeaturePainter.prototype, {
// Draw blocks.
var start_and_height;
for (var k = 0, k_len = feature_blocks.length; k < k_len; k++) {
var block = feature_blocks[k],
// -0.5 to offset block between bases.
block_start = Math.floor(
Math.max(0, (block[0] - tile_low - 0.5) * w_scale)
),
block_end = Math.ceil(
Math.min(
width,
Math.max((block[1] - tile_low - 0.5) * w_scale)
)
),
last_block_start,
last_block_end;
var block = feature_blocks[k];
var // -0.5 to offset block between bases.
block_start = Math.floor(
Math.max(0, (block[0] - tile_low - 0.5) * w_scale)
);
var block_end = Math.ceil(
Math.min(
width,
Math.max((block[1] - tile_low - 0.5) * w_scale)
)
);
var last_block_start;
var last_block_end;
// Skip drawing if block not on tile.
if (block_start > block_end) {
@@ -795,10 +822,11 @@ _.extend(LinkedFeaturePainter.prototype, FeaturePainter.prototype, {
!(block_start > thick_end || block_end < thick_start)
) {
var block_thick_start = Math.max(
block_start,
thick_start
),
block_thick_end = Math.min(block_end, thick_end);
block_start,
thick_start
);
var block_thick_end = Math.min(block_end, thick_end);
ctx.fillRect(
block_thick_start,
y_start + 1,
@@ -852,10 +880,12 @@ _.extend(LinkedFeaturePainter.prototype, FeaturePainter.prototype, {
// Height scaling: draw white lines to reduce height according to height scale factor.
ctx.fillStyle = "white"; // TODO: set this to background color.
var hscale_factor = this.height_scaler.gen_val(feature),
// Ceil ensures that min height is >= 1.
new_height = Math.ceil(thick_height * hscale_factor),
ws_height = Math.round((thick_height - new_height) / 2);
var hscale_factor = this.height_scaler.gen_val(feature);
var // Ceil ensures that min height is >= 1.
new_height = Math.ceil(thick_height * hscale_factor);
var ws_height = Math.round((thick_height - new_height) / 2);
if (hscale_factor !== 1) {
ctx.fillRect(
f_start,
@@ -945,8 +975,8 @@ _.extend(ReadPainter.prototype, FeaturePainter.prototype, {
* Returns height based on mode.
*/
get_row_height: function() {
var height,
mode = this.mode;
var height;
var mode = this.mode;
if (mode === "Dense") {
height = DENSE_TRACK_HEIGHT;
} else if (mode === "Squish") {
@@ -970,35 +1000,36 @@ _.extend(ReadPainter.prototype, FeaturePainter.prototype, {
var cigar_ops = "MIDNSHP=X";
// Parse cigar.
var blocks = [[0, 0]],
cur_block = blocks[0],
base_pos = 0,
// Parse cigar operations out and update/create blocks as needed.
parsed_cigar = _.map(
cigar_str.match(/[0-9]+[MIDNSHP=X]/g),
function(op) {
// Get operation length, character.
var op_len = parseInt(op.slice(0, -1), 10),
op_char = op.slice(-1);
var blocks = [[0, 0]];
// Update drawing block.
if (op_char === "N") {
// At skip, so need to start new block if current block represents
// drawing area.
if (cur_block[1] !== 0) {
cur_block = [base_pos + op_len, base_pos + op_len];
blocks.push(cur_block);
}
} else if ("ISHP".indexOf(op_char) === -1) {
// Operation is M,D,=,X.
cur_block[1] += op_len;
base_pos += op_len;
}
var cur_block = blocks[0];
var base_pos = 0;
// Return parsed cigar.
return [cigar_ops.indexOf(op_char), op_len];
var // Parse cigar operations out and update/create blocks as needed.
parsed_cigar = _.map(cigar_str.match(/[0-9]+[MIDNSHP=X]/g), function(
op
) {
// Get operation length, character.
var op_len = parseInt(op.slice(0, -1), 10),
op_char = op.slice(-1);
// Update drawing block.
if (op_char === "N") {
// At skip, so need to start new block if current block represents
// drawing area.
if (cur_block[1] !== 0) {
cur_block = [base_pos + op_len, base_pos + op_len];
blocks.push(cur_block);
}
);
} else if ("ISHP".indexOf(op_char) === -1) {
// Operation is M,D,=,X.
cur_block[1] += op_len;
base_pos += op_len;
}
// Return parsed cigar.
return [cigar_ops.indexOf(op_char), op_len];
});
return {
blocks: blocks,
@@ -1023,44 +1054,50 @@ _.extend(ReadPainter.prototype, FeaturePainter.prototype, {
) {
// Helper function to update base and sequnence offsets.
var update_base_offset = function(offset, cig_op, cig_len) {
if ("M=NXD".indexOf(cig_op) !== -1) {
offset += cig_len;
}
return offset;
},
update_seq_offset = function(offset, cig_op, cig_len) {
if ("IX".indexOf(cig_op) !== -1) {
offset += cig_len;
}
return offset;
},
// Gets drawing coordinate for a sequence coordinate. Assumes closure variables w_scale and tile_low.
get_draw_coord = function(sequence_coord) {
// -0.5 to offset sequence between bases.
return Math.floor(
Math.max(0, (sequence_coord - tile_low - 0.5) * w_scale)
);
};
if ("M=NXD".indexOf(cig_op) !== -1) {
offset += cig_len;
}
return offset;
};
var update_seq_offset = function(offset, cig_op, cig_len) {
if ("IX".indexOf(cig_op) !== -1) {
offset += cig_len;
}
return offset;
};
var // Gets drawing coordinate for a sequence coordinate. Assumes closure variables w_scale and tile_low.
get_draw_coord = function(sequence_coord) {
// -0.5 to offset sequence between bases.
return Math.floor(
Math.max(0, (sequence_coord - tile_low - 0.5) * w_scale)
);
};
ctx.textAlign = "center";
var tile_region = [tile_low, tile_high],
base_offset = 0,
seq_offset = 0,
gap = Math.round(w_scale / 2),
char_width_px = ctx.canvas.manager.char_width_px,
block_color =
strand === "+"
? this.prefs.detail_block_color
: this.prefs.reverse_strand_color,
pack_mode = mode === "Pack",
draw_height = pack_mode
? PACK_FEATURE_HEIGHT
: SQUISH_FEATURE_HEIGHT,
rect_y = y_start + 1,
paint_utils = new ReadPainterUtils(ctx, draw_height, w_scale, mode),
drawing_blocks = [],
s_start,
s_end;
var tile_region = [tile_low, tile_high];
var base_offset = 0;
var seq_offset = 0;
var gap = Math.round(w_scale / 2);
var char_width_px = ctx.canvas.manager.char_width_px;
var block_color =
strand === "+"
? this.prefs.detail_block_color
: this.prefs.reverse_strand_color;
var pack_mode = mode === "Pack";
var draw_height = pack_mode
? PACK_FEATURE_HEIGHT
: SQUISH_FEATURE_HEIGHT;
var rect_y = y_start + 1;
var paint_utils = new ReadPainterUtils(ctx, draw_height, w_scale, mode);
var drawing_blocks = [];
var s_start;
var s_end;
// Keep list of items that need to be drawn on top of initial drawing layer.
var draw_last = [];
@@ -1099,9 +1136,9 @@ _.extend(ReadPainter.prototype, FeaturePainter.prototype, {
// Draw read features.
for (var cig_id = 0, len = cigar.length; cig_id < len; cig_id++) {
var cig = cigar[cig_id],
cig_op = "MIDNSHP=X"[cig[0]],
cig_len = cig[1];
var cig = cigar[cig_id];
var cig_op = "MIDNSHP=X"[cig[0]];
var cig_len = cig[1];
var seq_start = feature_start + base_offset;
s_start = get_draw_coord(seq_start);
@@ -1342,7 +1379,9 @@ _.extend(ReadPainter.prototype, FeaturePainter.prototype, {
// Draw last items.
//
ctx.fillStyle = "yellow";
var item, type, data;
var item;
var type;
var data;
for (var i = 0; i < draw_last.length; i++) {
item = draw_last[i];
type = item.type;
@@ -1373,27 +1412,30 @@ _.extend(ReadPainter.prototype, FeaturePainter.prototype, {
width
) {
// All features need a start, end, and vertical center.
var feature_uid = feature[0],
feature_start = feature[1],
feature_end = feature[2],
feature_name = feature[3],
// -0.5 to put element between bases.
f_start = Math.floor(
Math.max(
-0.5 * w_scale,
(feature_start - tile_low - 0.5) * w_scale
)
),
f_end = Math.ceil(
Math.min(
width,
Math.max(0, (feature_end - tile_low - 0.5) * w_scale)
)
),
y_start = (mode === "Dense" ? 0 : 0 + slot) * y_scale,
draw_height =
mode === "Pack" ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT,
label_color = this.prefs.label_color;
var feature_uid = feature[0];
var feature_start = feature[1];
var feature_end = feature[2];
var feature_name = feature[3];
var // -0.5 to put element between bases.
f_start = Math.floor(
Math.max(-0.5 * w_scale, (feature_start - tile_low - 0.5) * w_scale)
);
var f_end = Math.ceil(
Math.min(
width,
Math.max(0, (feature_end - tile_low - 0.5) * w_scale)
)
);
var y_start = (mode === "Dense" ? 0 : 0 + slot) * y_scale;
var draw_height =
mode === "Pack" ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT;
var label_color = this.prefs.label_color;
// Draw read.
if (feature[5] instanceof Array) {
@@ -1450,20 +1492,22 @@ _.extend(ReadPainter.prototype, FeaturePainter.prototype, {
// make it possible to put together more easily.
// -0.5 to position connector correctly between reads.
var b1_end = Math.ceil(
Math.min(
width,
Math.max(
-0.5 * w_scale,
(feature[4][1] - tile_low - 0.5) * w_scale
)
)
),
b2_start = Math.floor(
Math.min(
width,
Math.max(
-0.5 * w_scale,
(feature[5][0] - tile_low - 0.5) * w_scale
(feature[4][1] - tile_low - 0.5) * w_scale
)
);
)
);
var b2_start = Math.floor(
Math.max(
-0.5 * w_scale,
(feature[5][0] - tile_low - 0.5) * w_scale
)
);
if (connector && b2_start > b1_end) {
ctx.fillStyle = CONNECTOR_COLOR;
var line_height = y_start + 1 + (draw_height - 1) / 2;
@@ -1551,9 +1595,9 @@ _.extend(
calculate_longest_feature_length: function() {
var longest_feature_length = 0;
for (var i = 0, len = this.data.length; i < len; i++) {
var feature = this.data[i],
feature_start = feature[1],
feature_end = feature[2];
var feature = this.data[i];
var feature_start = feature[1];
var feature_end = feature[2];
longest_feature_length = Math.max(
longest_feature_length,
feature_end - feature_start
@@ -1563,8 +1607,8 @@ _.extend(
},
get_top_padding: function(width) {
var view_range = this.view_end - this.view_start,
w_scale = width / view_range;
var view_range = this.view_end - this.view_start;
var w_scale = width / view_range;
return Math.min(
128,
Math.ceil(this.longest_feature_length / 2 * w_scale)
@@ -1580,11 +1624,14 @@ _.extend(
y_start
) {
// Arc drawing -- from closest endpoints
var x_center = (block1_end + block2_start) / 2,
radius = block2_start - x_center;
var x_center = (block1_end + block2_start) / 2;
var radius = block2_start - x_center;
// For full half circles
var angle1 = Math.PI,
angle2 = 0;
var angle1 = Math.PI;
var angle2 = 0;
if (radius > 0) {
ctx.beginPath();
ctx.arc(x_center, y_start, block2_start - x_center, Math.PI, 0);
@@ -1661,17 +1708,16 @@ Color.prototype = {
},
toHSL: function() {
var r = this.rgb[0] / 255,
g = this.rgb[1] / 255,
b = this.rgb[2] / 255,
a = this.alpha;
var max = Math.max(r, g, b),
min = Math.min(r, g, b);
var h,
s,
l = (max + min) / 2,
d = max - min;
var r = this.rgb[0] / 255;
var g = this.rgb[1] / 255;
var b = this.rgb[2] / 255;
var a = this.alpha;
var max = Math.max(r, g, b);
var min = Math.min(r, g, b);
var h;
var s;
var l = (max + min) / 2;
var d = max - min;
if (max === min) {
h = s = 0;
@@ -1785,7 +1831,8 @@ SplitRamp.prototype.map_value = function(value) {
var DiagonalHeatmapPainter = function(data, view_start, view_end, prefs, mode) {
Painter.call(this, data, view_start, view_end, prefs, mode);
var i, len;
var i;
var len;
if (this.prefs.min_value === undefined) {
var min_value = Infinity;
@@ -1812,14 +1859,14 @@ DiagonalHeatmapPainter.prototype.default_prefs = {
};
DiagonalHeatmapPainter.prototype.draw = function(ctx, width, height, w_scale) {
var min_value = this.prefs.min_value,
max_value = this.prefs.max_value,
value_range = max_value - min_value,
height_px = height,
view_start = this.view_start,
mode = this.mode,
data = this.data,
invsqrt2 = 1 / Math.sqrt(2);
var min_value = this.prefs.min_value;
var max_value = this.prefs.max_value;
var value_range = max_value - min_value;
var height_px = height;
var view_start = this.view_start;
var mode = this.mode;
var data = this.data;
var invsqrt2 = 1 / Math.sqrt(2);
var ramp = new SplitRamp(
this.prefs.neg_color,
@@ -1829,7 +1876,12 @@ DiagonalHeatmapPainter.prototype.draw = function(ctx, width, height, w_scale) {
max_value
);
var d, s1, e1, s2, e2, value;
var d;
var s1;
var e1;
var s2;
var e2;
var value;
var scale = function(p) {
return (p - view_start) * w_scale;
@@ -1907,8 +1959,8 @@ _.extend(VariantPainter.prototype, Painter.prototype, {
* Height of a single row, depends on mode
*/
get_row_height: function() {
var mode = this.mode,
height;
var mode = this.mode;
var height;
if (mode === "Dense") {
height = DENSE_TRACK_HEIGHT;
} else if (mode === "Squish") {
@@ -1949,11 +2001,11 @@ _.extend(VariantPainter.prototype, Painter.prototype, {
* -len: how long the deletion is
*/
get_indel_info = function(ref, alt) {
var ref_len = ref.length,
alt_len = alt.length,
start = 0,
len = 1,
type = null;
var ref_len = ref.length;
var alt_len = alt.length;
var start = 0;
var len = 1;
var type = null;
if (alt === "-") {
type = "deletion";
len = ref.length;
@@ -1972,45 +2024,49 @@ _.extend(VariantPainter.prototype, Painter.prototype, {
};
// Draw.
var locus_data,
pos,
id,
ref,
alt,
qual,
filter,
sample_gts,
allele_counts,
variant,
draw_x_start,
draw_y_start,
genotype,
// Always draw variants at least 1 pixel wide.
base_px = Math.max(1, Math.floor(w_scale)),
// Determine number of samples.
num_samples = this.data.length
? this.data[0][7].split(",").length
: 0,
row_height =
this.mode === "Squish"
? SQUISH_TRACK_HEIGHT
: PACK_TRACK_HEIGHT,
// If zoomed out, fill the whole row with feature to make it easier to read;
// when zoomed in, use feature height so that there are gaps in sample rows.
feature_height =
w_scale < 0.1
? row_height
: this.mode === "Squish"
? SQUISH_FEATURE_HEIGHT
: PACK_FEATURE_HEIGHT,
draw_summary = true,
paint_utils = new ReadPainterUtils(
ctx,
row_height,
w_scale,
this.mode
),
j;
var locus_data;
var pos;
var id;
var ref;
var alt;
var qual;
var filter;
var sample_gts;
var allele_counts;
var variant;
var draw_x_start;
var draw_y_start;
var genotype;
var // Always draw variants at least 1 pixel wide.
base_px = Math.max(1, Math.floor(w_scale));
var // Determine number of samples.
num_samples = this.data.length ? this.data[0][7].split(",").length : 0;
var row_height =
this.mode === "Squish" ? SQUISH_TRACK_HEIGHT : PACK_TRACK_HEIGHT;
var // If zoomed out, fill the whole row with feature to make it easier to read;
// when zoomed in, use feature height so that there are gaps in sample rows.
feature_height =
w_scale < 0.1
? row_height
: this.mode === "Squish"
? SQUISH_FEATURE_HEIGHT
: PACK_FEATURE_HEIGHT;
var draw_summary = true;
var paint_utils = new ReadPainterUtils(
ctx,
row_height,
w_scale,
this.mode
);
var j;
// If there's a single sample, update drawing variables.
if (num_samples === 1) {
@@ -2049,11 +2105,12 @@ _.extend(VariantPainter.prototype, Painter.prototype, {
// Process alterate values to derive information about each alt.
alt = _.map(_.flatten(alt), function(a) {
var alt_info = {
type: "snp",
value: a,
start: 0
},
indel_info = get_indel_info(ref, a);
type: "snp",
value: a,
start: 0
};
var indel_info = get_indel_info(ref, a);
return _.extend(alt_info, indel_info);
});
+23 -19
View File
@@ -2,8 +2,9 @@ import * as _ from "libs/underscore";
var extend = _.extend;
// HACK: LABEL_SPACING is currently duplicated between here and painters
var LABEL_SPACING = 2,
PACK_SPACING = 5;
var LABEL_SPACING = 2;
var PACK_SPACING = 5;
/**
* Hold slotting information for a feature.
@@ -40,10 +41,11 @@ extend(FeatureSlotter.prototype, {
*/
_get_draw_coords: function(feature) {
// Get initial draw coordinates using w_scale.
var draw_start = Math.floor(feature[1] * this.w_scale),
draw_end = Math.ceil(feature[2] * this.w_scale),
f_name = feature[3],
text_align;
var draw_start = Math.floor(feature[1] * this.w_scale);
var draw_end = Math.ceil(feature[2] * this.w_scale);
var f_name = feature[3];
var text_align;
// Update start, end drawing locations to include feature name.
// Try to put the name on the left, if not, put on right.
@@ -92,11 +94,12 @@ extend(FeatureSlotter.prototype, {
*/
_find_slot: function(draw_coords) {
// TODO: Use a data structure for faster searching of available slots.
var draw_start = draw_coords[0],
draw_end = draw_coords[1];
var draw_start = draw_coords[0];
var draw_end = draw_coords[1];
for (var slot_num = 0; slot_num <= this.max_rows; slot_num++) {
var has_overlap = false,
slot = this.start_end_dct[slot_num];
var has_overlap = false;
var slot = this.start_end_dct[slot_num];
if (slot !== undefined) {
// Iterate through features already in slot to see if current feature will fit.
for (var k = 0, k_len = slot.length; k < k_len; k++) {
@@ -119,11 +122,11 @@ extend(FeatureSlotter.prototype, {
* Slot features.
*/
slot_features: function(features) {
var start_end_dct = this.start_end_dct,
undone = [],
highest_slot = 0,
feature,
feature_uid;
var start_end_dct = this.start_end_dct;
var undone = [];
var highest_slot = 0;
var feature;
var feature_uid;
// Loop through features to (a) find those that are not yet slotted and (b) update
// those that are slotted if new information is availabe. For (a), features already
@@ -144,10 +147,11 @@ extend(FeatureSlotter.prototype, {
// Feature has changed (e.g. a single read now has its pair), so recalculate its
// drawing coordinates.
var old_draw_coords = this._get_draw_coords(
slotted_info.feature
),
new_draw_coords = this._get_draw_coords(feature),
slotted_coords = this.start_end_dct[slotted_info.slot];
slotted_info.feature
);
var new_draw_coords = this._get_draw_coords(feature);
var slotted_coords = this.start_end_dct[slotted_info.slot];
for (var k = 0; k < slotted_coords.length; k++) {
var dc = slotted_coords[k];
if (
File diff suppressed because it is too large Load Diff
+32 -29
View File
@@ -34,22 +34,24 @@ var ServerStateDeferred = Backbone.Model.extend({
* Returns a deferred that resolves when success function returns true.
*/
go: function() {
var deferred = $.Deferred(),
self = this,
ajax_settings = self.get("ajax_settings"),
success_fn = self.get("success_fn"),
interval = self.get("interval"),
_go = function() {
$.ajax(ajax_settings).success(function(result) {
if (success_fn(result)) {
// Result is good, so resolve.
deferred.resolve(result);
} else {
// Result not good, try again.
setTimeout(_go, interval);
}
});
};
var deferred = $.Deferred();
var self = this;
var ajax_settings = self.get("ajax_settings");
var success_fn = self.get("success_fn");
var interval = self.get("interval");
var _go = function() {
$.ajax(ajax_settings).success(function(result) {
if (success_fn(result)) {
// Result is good, so resolve.
deferred.resolve(result);
} else {
// Result not good, try again.
setTimeout(_go, interval);
}
});
};
_go();
return deferred;
}
@@ -95,19 +97,20 @@ var get_random_color = function(colors) {
};
// Create new random color.
var new_color,
nr,
ng,
nb,
other_color,
or,
og,
ob,
n_brightness,
o_brightness,
diff,
ok = false,
num_tries = 0;
var new_color;
var nr;
var ng;
var nb;
var other_color;
var or;
var og;
var ob;
var n_brightness;
var o_brightness;
var diff;
var ok = false;
var num_tries = 0;
do {
// New color is never white b/c random in [0,1)
new_color = Math.round(Math.random() * 0xffffff);
+113 -101
View File
@@ -14,8 +14,8 @@ var CustomToJSON = {
* Returns JSON representation of object using to_json_keys and to_json_mappers.
*/
toJSON: function() {
var self = this,
json = {};
var self = this;
var json = {};
_.each(self.constructor.to_json_keys, function(k) {
var val = self.get(k);
if (k in self.constructor.to_json_mappers) {
@@ -147,9 +147,9 @@ var CanvasManager = function(default_font) {
_.extend(CanvasManager.prototype, {
load_pattern: function(key, path) {
var patterns = this.patterns,
dummy_context = this.dummy_context,
image = new Image();
var patterns = this.patterns;
var dummy_context = this.dummy_context;
var image = new Image();
image.src = Galaxy.root + "static/images" + path;
image.onload = function() {
patterns[key] = dummy_context.createPattern(image, "repeat");
@@ -187,12 +187,13 @@ var Cache = Backbone.Model.extend({
* Get an element from the cache using its key.
*/
get_elt: function(key) {
var obj_cache = this.attributes.obj_cache,
key_ary = this.attributes.key_ary,
key_str = key.toString(),
index = _.indexOf(key_ary, function(k) {
return k.toString() === key_str;
});
var obj_cache = this.attributes.obj_cache;
var key_ary = this.attributes.key_ary;
var key_str = key.toString();
var index = _.indexOf(key_ary, function(k) {
return k.toString() === key_str;
});
// Update cache.
if (index !== -1) {
@@ -214,10 +215,10 @@ var Cache = Backbone.Model.extend({
* Put an element into the cache.
*/
set_elt: function(key, value) {
var obj_cache = this.attributes.obj_cache,
key_ary = this.attributes.key_ary,
key_str = key.toString(),
num_elements = this.attributes.num_elements;
var obj_cache = this.attributes.obj_cache;
var key_ary = this.attributes.key_ary;
var key_str = key.toString();
var num_elements = this.attributes.num_elements;
// Update keys, objects.
if (!obj_cache[key_str]) {
@@ -323,30 +324,32 @@ var GenomeDataManager = Cache.extend({
* cannot be used).
*/
data_is_ready: function() {
var dataset = this.get("dataset"),
ready_deferred = $.Deferred(),
// If requesting raw data, query dataset state; if requesting (converted) data,
// need to query converted datasets state.
query_type =
this.get("data_type") === "raw_data"
? "state"
: this.get("data_type") === "data"
? "converted_datasets_state"
: "error",
ss_deferred = new util_mod.ServerStateDeferred({
ajax_settings: {
url: this.get("dataset").url(),
data: {
hda_ldda: dataset.get("hda_ldda"),
data_type: query_type
},
dataType: "json"
var dataset = this.get("dataset");
var ready_deferred = $.Deferred();
var // If requesting raw data, query dataset state; if requesting (converted) data,
// need to query converted datasets state.
query_type =
this.get("data_type") === "raw_data"
? "state"
: this.get("data_type") === "data"
? "converted_datasets_state"
: "error";
var ss_deferred = new util_mod.ServerStateDeferred({
ajax_settings: {
url: this.get("dataset").url(),
data: {
hda_ldda: dataset.get("hda_ldda"),
data_type: query_type
},
interval: 5000,
success_fn: function(response) {
return response !== "pending";
}
});
dataType: "json"
},
interval: 5000,
success_fn: function(response) {
return response !== "pending";
}
});
$.when(ss_deferred.go()).then(function(response) {
ready_deferred.resolve(response === "ok" || response === "data");
@@ -358,12 +361,14 @@ var GenomeDataManager = Cache.extend({
* Perform a feature search from server; returns Deferred object that resolves when data is available.
*/
search_features: function(query) {
var dataset = this.get("dataset"),
params = {
query: query,
hda_ldda: dataset.get("hda_ldda"),
data_type: "features"
};
var dataset = this.get("dataset");
var params = {
query: query,
hda_ldda: dataset.get("hda_ldda"),
data_type: "features"
};
return $.getJSON(dataset.url(), params);
},
@@ -374,16 +379,17 @@ var GenomeDataManager = Cache.extend({
*/
load_data: function(region, mode, resolution, extra_params) {
// Setup data request params.
var dataset = this.get("dataset"),
params = {
data_type: this.get("data_type"),
chrom: region.get("chrom"),
low: region.get("start"),
high: region.get("end"),
mode: mode,
resolution: resolution,
hda_ldda: dataset.get("hda_ldda")
};
var dataset = this.get("dataset");
var params = {
data_type: this.get("data_type"),
chrom: region.get("chrom"),
low: region.get("start"),
high: region.get("end"),
mode: mode,
resolution: resolution,
hda_ldda: dataset.get("hda_ldda")
};
$.extend(params, extra_params);
@@ -399,12 +405,13 @@ var GenomeDataManager = Cache.extend({
}
// Do request.
var manager = this,
entry = $.getJSON(dataset.url(), params, function(result) {
// Add region to the result.
result.region = region;
manager.set_data(region, result);
});
var manager = this;
var entry = $.getJSON(dataset.url(), params, function(result) {
// Add region to the result.
result.region = region;
manager.set_data(region, result);
});
this.set_data(region, entry);
return entry;
@@ -429,10 +436,11 @@ var GenomeDataManager = Cache.extend({
// TODO: this logic could be improved if the visualization knew whether
// the data was "index" or "data."
//
var key_ary = this.get("key_ary"),
obj_cache = this.get("obj_cache"),
entry_region,
is_subregion;
var key_ary = this.get("key_ary");
var obj_cache = this.get("obj_cache");
var entry_region;
var is_subregion;
for (var i = 0; i < key_ary.length; i++) {
entry_region = key_ary[i];
@@ -551,14 +559,16 @@ var GenomeDataManager = Cache.extend({
// Get additional data, append to current data, and set new data. Use a custom deferred object
// to signal when new data is available.
//
var data_manager = this,
new_data_request = this.load_data(
query_region,
mode,
resolution,
extra_params
),
new_data_available = $.Deferred();
var data_manager = this;
var new_data_request = this.load_data(
query_region,
mode,
resolution,
extra_params
);
var new_data_available = $.Deferred();
// load_data sets cache to new_data_request, but use custom deferred object so that signal and data
// is all data, not just new data.
this.set_data(region, new_data_available);
@@ -650,27 +660,29 @@ var GenomeDataManager = Cache.extend({
get_genome_wide_data: function(genome) {
// -- Get all data. --
var self = this,
all_data_available = true,
// Map chromosome info into genome data.
gw_data = _.map(genome.get("chroms_info").chrom_info, function(
chrom_info
) {
var chrom_data = self.get_elt(
new GenomeRegion({
chrom: chrom_info.chrom,
start: 0,
end: chrom_info.len
})
);
var self = this;
// Set flag if data is not available.
if (!chrom_data) {
all_data_available = false;
}
var all_data_available = true;
return chrom_data;
});
var // Map chromosome info into genome data.
gw_data = _.map(genome.get("chroms_info").chrom_info, function(
chrom_info
) {
var chrom_data = self.get_elt(
new GenomeRegion({
chrom: chrom_info.chrom,
start: 0,
end: chrom_info.len
})
);
// Set flag if data is not available.
if (!chrom_data) {
all_data_available = false;
}
return chrom_data;
});
// -- If all data is available, return it. --
if (all_data_available) {
@@ -830,9 +842,9 @@ var GenomeRegion = Backbone.Model.extend(
*/
initialize: function(options) {
if (options.from_str) {
var pieces = options.from_str.split(":"),
chrom = pieces[0],
start_end = pieces[1].split("-");
var pieces = options.from_str.split(":");
var chrom = pieces[0];
var start_end = pieces[1].split("-");
this.set({
chrom: chrom,
start: parseInt(start_end[0], 10),
@@ -893,13 +905,13 @@ var GenomeRegion = Backbone.Model.extend(
* hence, OVERLAP_START indicates that the first region overlaps the start (but not the end) of the second region.
*/
compute_overlap: function(a_region) {
var first_chrom = this.get("chrom"),
second_chrom = a_region.get("chrom"),
first_start = this.get("start"),
second_start = a_region.get("start"),
first_end = this.get("end"),
second_end = a_region.get("end"),
overlap;
var first_chrom = this.get("chrom");
var second_chrom = a_region.get("chrom");
var first_start = this.get("start");
var second_start = a_region.get("start");
var first_end = this.get("end");
var second_end = a_region.get("end");
var overlap;
// Compare chroms.
if (first_chrom && second_chrom && first_chrom !== second_chrom) {
+4 -3
View File
@@ -108,9 +108,10 @@ var TrackHeaderView = Backbone.View.extend({
);
// Setup popup menu for changing modes.
var self = this,
track = this.model,
mode_mapping = {};
var self = this;
var track = this.model;
var mode_mapping = {};
for (var i = 0, len = track.display_modes.length; i < len; i++) {
var mode = track.display_modes[i];
mode_mapping[mode] = (function(mode) {
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
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
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
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
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
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
File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More