galaxy-commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
February 2015
- 2 participants
- 305 discussions
commit/galaxy-central: carlfeberhard: UI, paired collection creator: move to underscore fn binding, allow name param in createList, add qunit test and data
by commits-noreply@bitbucket.org 10 Feb '15
by commits-noreply@bitbucket.org 10 Feb '15
10 Feb '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/109da695364c/
Changeset: 109da695364c
User: carlfeberhard
Date: 2015-02-10 18:38:30+00:00
Summary: UI, paired collection creator: move to underscore fn binding, allow name param in createList, add qunit test and data
Affected #: 9 files
diff -r 7ef4ebeaa607b32151ca30c96ba774a3fc0d2274 -r 109da695364ceee5c27bf71b6a0bed918813fcda client/galaxy/scripts/mvc/collection/paired-collection-creator.js
--- a/client/galaxy/scripts/mvc/collection/paired-collection-creator.js
+++ b/client/galaxy/scripts/mvc/collection/paired-collection-creator.js
@@ -236,14 +236,16 @@
_splitByFilters : function( filters ){
var fwd = [],
rev = [];
- this.unpaired.forEach( function( unpaired ){
+
+ function _addToFwdOrRev( unpaired ){
if( this._filterFwdFn( unpaired ) ){
fwd.push( unpaired );
}
if( this._filterRevFn( unpaired ) ){
rev.push( unpaired );
}
- }.bind( this ) );
+ }
+ this.unpaired.forEach( _.bind( _addToFwdOrRev, this ) );
return [ fwd, rev ];
},
@@ -603,7 +605,7 @@
/** create the collection via the API
* @returns {jQuery.xhr Object} the jquery ajax request
*/
- createList : function(){
+ createList : function( name ){
var creator = this,
url;
if( creator.historyId ){
@@ -616,10 +618,11 @@
var ajaxData = {
type : 'dataset_collection',
collection_type : 'list:paired',
- name : _.escape( creator.$( '.collection-name' ).val() ),
+ name : _.escape( name || creator.$( '.collection-name' ).val() ),
element_identifiers : creator.paired.map( function( pair ){
return creator._pairToJSON( pair );
})
+
};
//this.debug( JSON.stringify( ajaxData ) );
return jQuery.ajax( url, {
@@ -1732,6 +1735,8 @@
//=============================================================================
/** a modal version of the paired collection creator */
var pairedCollectionCreatorModal = function _pairedCollectionCreatorModal( datasets, options ){
+ console.log( datasets );
+
options = _.defaults( options || {}, {
datasets : datasets,
oncancel : function(){ Galaxy.modal.hide(); },
diff -r 7ef4ebeaa607b32151ca30c96ba774a3fc0d2274 -r 109da695364ceee5c27bf71b6a0bed918813fcda static/scripts/mvc/collection/paired-collection-creator.js
--- a/static/scripts/mvc/collection/paired-collection-creator.js
+++ b/static/scripts/mvc/collection/paired-collection-creator.js
@@ -236,14 +236,16 @@
_splitByFilters : function( filters ){
var fwd = [],
rev = [];
- this.unpaired.forEach( function( unpaired ){
+
+ function _addToFwdOrRev( unpaired ){
if( this._filterFwdFn( unpaired ) ){
fwd.push( unpaired );
}
if( this._filterRevFn( unpaired ) ){
rev.push( unpaired );
}
- }.bind( this ) );
+ }
+ this.unpaired.forEach( _.bind( _addToFwdOrRev, this ) );
return [ fwd, rev ];
},
@@ -603,7 +605,7 @@
/** create the collection via the API
* @returns {jQuery.xhr Object} the jquery ajax request
*/
- createList : function(){
+ createList : function( name ){
var creator = this,
url;
if( creator.historyId ){
@@ -616,10 +618,11 @@
var ajaxData = {
type : 'dataset_collection',
collection_type : 'list:paired',
- name : _.escape( creator.$( '.collection-name' ).val() ),
+ name : _.escape( name || creator.$( '.collection-name' ).val() ),
element_identifiers : creator.paired.map( function( pair ){
return creator._pairToJSON( pair );
})
+
};
//this.debug( JSON.stringify( ajaxData ) );
return jQuery.ajax( url, {
@@ -1732,6 +1735,8 @@
//=============================================================================
/** a modal version of the paired collection creator */
var pairedCollectionCreatorModal = function _pairedCollectionCreatorModal( datasets, options ){
+ console.log( datasets );
+
options = _.defaults( options || {}, {
datasets : datasets,
oncancel : function(){ Galaxy.modal.hide(); },
diff -r 7ef4ebeaa607b32151ca30c96ba774a3fc0d2274 -r 109da695364ceee5c27bf71b6a0bed918813fcda static/scripts/packed/mvc/collection/paired-collection-creator.js
--- a/static/scripts/packed/mvc/collection/paired-collection-creator.js
+++ b/static/scripts/packed/mvc/collection/paired-collection-creator.js
@@ -1,1 +1,1 @@
-define(["utils/levenshtein","mvc/base-mvc","utils/localization"],function(g,a,d){var f=Backbone.View.extend(a.LoggableMixin).extend({tagName:"li",className:"dataset paired",initialize:function(h){this.pair=h.pair||{}},template:_.template(['<span class="forward-dataset-name flex-column"><%= pair.forward.name %></span>','<span class="pair-name-column flex-column">','<span class="pair-name"><%= pair.name %></span>',"</span>",'<span class="reverse-dataset-name flex-column"><%= pair.reverse.name %></span>'].join("")),render:function(){this.$el.attr("draggable",true).data("pair",this.pair).html(this.template({pair:this.pair})).addClass("flex-column-container");return this},events:{dragstart:"_dragstart",dragend:"_dragend",dragover:"_sendToParent",drop:"_sendToParent"},_dragstart:function(h){h.currentTarget.style.opacity="0.4";if(h.originalEvent){h=h.originalEvent}h.dataTransfer.effectAllowed="move";h.dataTransfer.setData("text/plain",JSON.stringify(this.pair));this.$el.parent().trigger("pair.dragstart",[this])},_dragend:function(h){h.currentTarget.style.opacity="1.0";this.$el.parent().trigger("pair.dragend",[this])},_sendToParent:function(h){this.$el.parent().trigger(h)},toString:function(){return"PairView("+this.pair.name+")"}});var e=Backbone.View.extend(a.LoggableMixin).extend({className:"collection-creator flex-row-container",initialize:function(h){h=_.defaults(h,{datasets:[],filters:this.DEFAULT_FILTERS,automaticallyPair:true,matchPercentage:1,strategy:"lcs"});this.initialList=h.datasets;this.historyId=h.historyId;this.filters=this.commonFilters[h.filters]||this.commonFilters[this.DEFAULT_FILTERS];if(_.isArray(h.filters)){this.filters=h.filters}this.automaticallyPair=h.automaticallyPair;this.matchPercentage=h.matchPercentage;this.strategy=this.strategies[h.strategy]||this.strategies[this.DEFAULT_STRATEGY];if(_.isFunction(h.strategy)){this.strategy=h.strategy}this.removeExtensions=true;this.oncancel=h.oncancel;this.oncreate=h.oncreate;this.autoscrollDist=h.autoscrollDist||24;this.unpairedPanelHidden=false;this.pairedPanelHidden=false;this.$dragging=null;this._setUpBehaviors();this._dataSetUp()},commonFilters:{none:["",""],illumina:["_1","_2"]},DEFAULT_FILTERS:"illumina",strategies:{lcs:"autoPairLCSs",levenshtein:"autoPairLevenshtein"},DEFAULT_STRATEGY:"lcs",_dataSetUp:function(){this.paired=[];this.unpaired=[];this.selectedIds=[];this._sortInitialList();this._ensureIds();this.unpaired=this.initialList.slice(0);if(this.automaticallyPair){this.autoPair();this.once("rendered:initial",function(){this.trigger("autopair")})}},_sortInitialList:function(){this._sortDatasetList(this.initialList)},_sortDatasetList:function(h){h.sort(function(j,i){return naturalSort(j.name,i.name)});return h},_ensureIds:function(){this.initialList.forEach(function(h){if(!h.hasOwnProperty("id")){h.id=_.uniqueId()}});return this.initialList},_splitByFilters:function(j){var i=[],h=[];this.unpaired.forEach(function(k){if(this._filterFwdFn(k)){i.push(k)}if(this._filterRevFn(k)){h.push(k)}}.bind(this));return[i,h]},_filterFwdFn:function(i){var h=new RegExp(this.filters[0]);return h.test(i.name)},_filterRevFn:function(i){var h=new RegExp(this.filters[1]);return h.test(i.name)},_addToUnpaired:function(i){var h=function(j,l){if(j===l){return j}var k=Math.floor((l-j)/2)+j,m=naturalSort(i.name,this.unpaired[k].name);if(m<0){return h(j,k)}else{if(m>0){return h(k+1,l)}}while(this.unpaired[k]&&this.unpaired[k].name===i.name){k++}return k}.bind(this);this.unpaired.splice(h(0,this.unpaired.length),0,i)},autoPair:function(i){i=i||this.strategy;var h=this.simpleAutoPair();h=h.concat(this[i].call(this));return h},simpleAutoPair:function(){var o=0,m,s=this._splitByFilters(),h=s[0],r=s[1],q,u,k=false,t=[];while(o<h.length){var n=h[o];q=n.name.replace(this.filters[0],"");k=false;for(m=0;m<r.length;m++){var p=r[m];u=p.name.replace(this.filters[1],"");if(n!==p&&q===u){k=true;var l=this._pair(h.splice(o,1)[0],r.splice(m,1)[0],{silent:true});t.push(l);break}}if(!k){o+=1}}return t},autoPairLevenshtein:function(){var p=0,n,u=this._splitByFilters(),h=u[0],s=u[1],r,x,k,t,l,v=[];while(p<h.length){var o=h[p];r=o.name.replace(this.filters[0],"");l=Number.MAX_VALUE;for(n=0;n<s.length;n++){var q=s[n];x=q.name.replace(this.filters[1],"");if(o!==q){if(r===x){t=n;l=0;break}k=levenshteinDistance(r,x);if(k<l){t=n;l=k}}}var w=1-(l/(Math.max(r.length,x.length)));if(w>=this.matchPercentage){var m=this._pair(h.splice(p,1)[0],s.splice(t,1)[0],{silent:true});v.push(m);if(h.length<=0||s.length<=0){return v}}else{p+=1}}return v},autoPairLCSs:function(){var n=0,l,u=this._splitByFilters(),h=u[0],s=u[1],r,y,x,t,p,v=[];if(!h.length||!s.length){return v}while(n<h.length){var m=h[n];r=m.name.replace(this.filters[0],"");p=0;for(l=0;l<s.length;l++){var q=s[l];y=q.name.replace(this.filters[1],"");if(m!==q){if(r===y){t=l;p=r.length;break}var o=this._naiveStartingAndEndingLCS(r,y);x=o.length;if(x>p){t=l;p=x}}}var w=p/(Math.min(r.length,y.length));if(w>=this.matchPercentage){var k=this._pair(h.splice(n,1)[0],s.splice(t,1)[0],{silent:true});v.push(k);if(h.length<=0||s.length<=0){return v}}else{n+=1}}return v},_naiveStartingAndEndingLCS:function(m,k){var n="",o="",l=0,h=0;while(l<m.length&&l<k.length){if(m[l]!==k[l]){break}n+=m[l];l+=1}if(l===m.length){return m}if(l===k.length){return k}l=(m.length-1);h=(k.length-1);while(l>=0&&h>=0){if(m[l]!==k[h]){break}o=[m[l],o].join("");l-=1;h-=1}return n+o},_pair:function(j,h,i){i=i||{};var k=this._createPair(j,h,i.name);this.paired.push(k);this.unpaired=_.without(this.unpaired,j,h);if(!i.silent){this.trigger("pair:new",k)}return k},_createPair:function(j,h,i){if(!(j&&h)||(j===h)){throw new Error("Bad pairing: "+[JSON.stringify(j),JSON.stringify(h)])}i=i||this._guessNameForPair(j,h);return{forward:j,name:i,reverse:h}},_guessNameForPair:function(j,h,k){k=(k!==undefined)?(k):(this.removeExtensions);var i=this._naiveStartingAndEndingLCS(j.name.replace(this.filters[0],""),h.name.replace(this.filters[1],""));if(k){var l=i.lastIndexOf(".");if(l>0){i=i.slice(0,l)}}return i||(j.name+" & "+h.name)},_unpair:function(i,h){h=h||{};if(!i){throw new Error("Bad pair: "+JSON.stringify(i))}this.paired=_.without(this.paired,i);this._addToUnpaired(i.forward);this._addToUnpaired(i.reverse);if(!h.silent){this.trigger("pair:unpair",[i])}return i},unpairAll:function(){var h=[];while(this.paired.length){h.push(this._unpair(this.paired[0],{silent:true}))}this.trigger("pair:unpair",h)},_pairToJSON:function(h){return{collection_type:"paired",src:"new_collection",name:h.name,element_identifiers:[{name:"forward",id:h.forward.id,src:"hda"},{name:"reverse",id:h.reverse.id,src:"hda"}]}},createList:function(){var j=this,i;if(j.historyId){i="/api/histories/"+this.historyId+"/contents/dataset_collections"}var h={type:"dataset_collection",collection_type:"list:paired",name:_.escape(j.$(".collection-name").val()),element_identifiers:j.paired.map(function(k){return j._pairToJSON(k)})};return jQuery.ajax(i,{type:"POST",contentType:"application/json",dataType:"json",data:JSON.stringify(h)}).fail(function(m,k,l){j._ajaxErrHandler(m,k,l)}).done(function(k,l,m){j.trigger("collection:created",k,l,m);if(typeof j.oncreate==="function"){j.oncreate.call(this,k,l,m)}})},_ajaxErrHandler:function(k,h,j){this.error(k,h,j);var i=d("An error occurred while creating this collection");if(k){if(k.readyState===0&&k.status===0){i+=": "+d("Galaxy could not be reached and may be updating.")+d(" Try again in a few minutes.")}else{if(k.responseJSON){i+="<br /><pre>"+JSON.stringify(k.responseJSON)+"</pre>"}else{i+=": "+j}}}creator._showAlert(i,"alert-danger")},render:function(h,i){this.$el.empty().html(e.templates.main());this._renderHeader(h);this._renderMiddle(h);this._renderFooter(h);this._addPluginComponents();this.trigger("rendered",this);return this},_renderHeader:function(i,j){var h=this.$(".header").empty().html(e.templates.header()).find(".help-content").prepend($(e.templates.helpContent()));this._renderFilters();return h},_renderFilters:function(){return this.$(".forward-column .column-header input").val(this.filters[0]).add(this.$(".reverse-column .column-header input").val(this.filters[1]))},_renderMiddle:function(i,j){var h=this.$(".middle").empty().html(e.templates.middle());if(this.unpairedPanelHidden){this.$(".unpaired-columns").hide()}else{if(this.pairedPanelHidden){this.$(".paired-columns").hide()}}this._renderUnpaired();this._renderPaired();return h},_renderUnpaired:function(m,n){var k=this,l,i,h=[],j=this._splitByFilters();this.$(".forward-column .title").text([j[0].length,d("unpaired forward")].join(" "));this.$(".forward-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[0].length));this.$(".reverse-column .title").text([j[1].length,d("unpaired reverse")].join(" "));this.$(".reverse-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[1].length));this.$(".unpaired-columns .column-datasets").empty();this.$(".autopair-link").toggle(this.unpaired.length!==0);if(this.unpaired.length===0){this._renderUnpairedEmpty();return}i=j[1].map(function(p,o){if((j[0][o]!==undefined)&&(j[0][o]!==p)){h.push(k._renderPairButton())}return k._renderUnpairedDataset(p)});l=j[0].map(function(o){return k._renderUnpairedDataset(o)});if(!l.length&&!i.length){this._renderUnpairedNotShown();return}this.$(".unpaired-columns .forward-column .column-datasets").append(l).add(this.$(".unpaired-columns .paired-column .column-datasets").append(h)).add(this.$(".unpaired-columns .reverse-column .column-datasets").append(i));this._adjUnpairedOnScrollbar()},_renderUnpairedDisplayStr:function(h){return["(",h," ",d("filtered out"),")"].join("")},_renderUnpairedDataset:function(h){return $("<li/>").attr("id","dataset-"+h.id).addClass("dataset unpaired").attr("draggable",true).addClass(h.selected?"selected":"").append($("<span/>").addClass("dataset-name").text(h.name)).data("dataset",h)},_renderPairButton:function(){return $("<li/>").addClass("dataset unpaired").append($("<span/>").addClass("dataset-name").text(d("Pair these datasets")))},_renderUnpairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no remaining unpaired datasets")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_renderUnpairedNotShown:function(){var h=$('<div class="empty-message"></div>').text("("+d("no datasets were found matching the current filters")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_adjUnpairedOnScrollbar:function(){var k=this.$(".unpaired-columns").last(),l=this.$(".unpaired-columns .reverse-column .dataset").first();if(!l.size()){return}var h=k.offset().left+k.outerWidth(),j=l.offset().left+l.outerWidth(),i=Math.floor(h)-Math.floor(j);this.$(".unpaired-columns .forward-column").css("margin-left",(i>0)?i:0)},_renderPaired:function(i,j){this.$(".paired-column-title .title").text([this.paired.length,d("paired")].join(" "));this.$(".unpair-all-link").toggle(this.paired.length!==0);if(this.paired.length===0){this._renderPairedEmpty();return}else{this.$(".remove-extensions-link").show()}this.$(".paired-columns .column-datasets").empty();var h=this;this.paired.forEach(function(m,k){var l=new f({pair:m});h.$(".paired-columns .column-datasets").append(l.render().$el).append(['<button class="unpair-btn">','<span class="fa fa-unlink" title="',d("Unpair"),'"></span>',"</button>"].join(""))})},_renderPairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no paired datasets yet")+")");this.$(".paired-columns .column-datasets").empty().prepend(h);return h},_renderFooter:function(i,j){var h=this.$(".footer").empty().html(e.templates.footer());this.$(".remove-extensions").prop("checked",this.removeExtensions);if(typeof this.oncancel==="function"){this.$(".cancel-create.btn").show()}return h},_addPluginComponents:function(){this._chooseFiltersPopover(".choose-filters-link");this.$(".help-content i").hoverhighlight(".collection-creator","rgba( 64, 255, 255, 1.0 )")},_chooseFiltersPopover:function(h){function i(l,k){return['<button class="filter-choice btn" ','data-forward="',l,'" data-reverse="',k,'">',d("Forward"),": ",l,", ",d("Reverse"),": ",k,"</button>"].join("")}var j=$(_.template(['<div class="choose-filters">','<div class="help">',d("Choose from the following filters to change which unpaired reads are shown in the display"),":</div>",i("_1","_2"),i("_R1","_R2"),"</div>"].join(""))({}));return this.$(h).popover({container:".collection-creator",placement:"bottom",html:true,content:j})},_validationWarning:function(i,h){var j="validation-warning";if(i==="name"){i=this.$(".collection-name").add(this.$(".collection-name-prompt"));this.$(".collection-name").focus().select()}if(h){i=i||this.$("."+j);i.removeClass(j)}else{i.addClass(j)}},_setUpBehaviors:function(){this.once("rendered",function(){this.trigger("rendered:initial",this)});this.on("pair:new",function(){this._renderUnpaired();this._renderPaired();this.$(".paired-columns").scrollTop(8000000)});this.on("pair:unpair",function(h){this._renderUnpaired();this._renderPaired();this.splitView()});this.on("filter-change",function(){this.filters=[this.$(".forward-unpaired-filter input").val(),this.$(".reverse-unpaired-filter input").val()];this._renderFilters();this._renderUnpaired()});this.on("autopair",function(){this._renderUnpaired();this._renderPaired();var h,i=null;if(this.paired.length){i="alert-success";h=this.paired.length+" "+d("pairs created");if(!this.unpaired.length){h+=": "+d("all datasets have been successfully paired");this.hideUnpaired();this.$(".collection-name").focus()}}else{h=d("Could not automatically create any pairs from the given dataset names")}this._showAlert(h,i)});return this},events:{"click .more-help":"_clickMoreHelp","click .less-help":"_clickLessHelp","click .header .alert button":"_hideAlert","click .forward-column .column-title":"_clickShowOnlyUnpaired","click .reverse-column .column-title":"_clickShowOnlyUnpaired","click .unpair-all-link":"_clickUnpairAll","change .forward-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .forward-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .autopair-link":"_clickAutopair","click .choose-filters .filter-choice":"_clickFilterChoice","click .clear-filters-link":"_clearFilters","change .reverse-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .reverse-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .forward-column .dataset.unpaired":"_clickUnpairedDataset","click .reverse-column .dataset.unpaired":"_clickUnpairedDataset","click .paired-column .dataset.unpaired":"_clickPairRow","click .unpaired-columns":"clearSelectedUnpaired","mousedown .unpaired-columns .dataset":"_mousedownUnpaired","click .paired-column-title":"_clickShowOnlyPaired","mousedown .flexible-partition-drag":"_startPartitionDrag","click .paired-columns .dataset.paired":"selectPair","click .paired-columns":"clearSelectedPaired","click .paired-columns .pair-name":"_clickPairName","click .unpair-btn":"_clickUnpair","dragover .paired-columns .column-datasets":"_dragoverPairedColumns","drop .paired-columns .column-datasets":"_dropPairedColumns","pair.dragstart .paired-columns .column-datasets":"_pairDragstart","pair.dragend .paired-columns .column-datasets":"_pairDragend","change .remove-extensions":function(h){this.toggleExtensions()},"change .collection-name":"_changeName","keydown .collection-name":"_nameCheckForEnter","click .cancel-create":function(h){if(typeof this.oncancel==="function"){this.oncancel.call(this)}},"click .create-collection":"_clickCreate"},_clickMoreHelp:function(h){this.$(".main-help").addClass("expanded");this.$(".more-help").hide()},_clickLessHelp:function(h){this.$(".main-help").removeClass("expanded");this.$(".more-help").show()},_showAlert:function(i,h){h=h||"alert-danger";this.$(".main-help").hide();this.$(".header .alert").attr("class","alert alert-dismissable").addClass(h).show().find(".alert-message").html(i)},_hideAlert:function(h){this.$(".main-help").show();this.$(".header .alert").hide()},_clickShowOnlyUnpaired:function(h){if(this.$(".paired-columns").is(":visible")){this.hidePaired()}else{this.splitView()}},_clickShowOnlyPaired:function(h){if(this.$(".unpaired-columns").is(":visible")){this.hideUnpaired()}else{this.splitView()}},hideUnpaired:function(h,i){this.unpairedPanelHidden=true;this.pairedPanelHidden=false;this._renderMiddle(h,i)},hidePaired:function(h,i){this.unpairedPanelHidden=false;this.pairedPanelHidden=true;this._renderMiddle(h,i)},splitView:function(h,i){this.unpairedPanelHidden=this.pairedPanelHidden=false;this._renderMiddle(h,i);return this},_clickUnpairAll:function(h){this.unpairAll()},_clickAutopair:function(h){this.autoPair();this.trigger("autopair")},_clickFilterChoice:function(i){var h=$(i.currentTarget);this.$(".forward-unpaired-filter input").val(h.data("forward"));this.$(".reverse-unpaired-filter input").val(h.data("reverse"));this._hideChooseFilters();this.trigger("filter-change")},_hideChooseFilters:function(){this.$(".choose-filters-link").popover("hide");this.$(".popover").css("display","none")},_clearFilters:function(h){this.$(".forward-unpaired-filter input").val("");this.$(".reverse-unpaired-filter input").val("");this.trigger("filter-change")},_clickUnpairedDataset:function(h){h.stopPropagation();return this.toggleSelectUnpaired($(h.currentTarget))},toggleSelectUnpaired:function(j,i){i=i||{};var k=j.data("dataset"),h=i.force!==undefined?i.force:!j.hasClass("selected");if(!j.size()||k===undefined){return j}if(h){j.addClass("selected");if(!i.waitToPair){this.pairAllSelected()}}else{j.removeClass("selected")}return j},pairAllSelected:function(i){i=i||{};var j=this,k=[],h=[],l=[];j.$(".unpaired-columns .forward-column .dataset.selected").each(function(){k.push($(this).data("dataset"))});j.$(".unpaired-columns .reverse-column .dataset.selected").each(function(){h.push($(this).data("dataset"))});k.length=h.length=Math.min(k.length,h.length);k.forEach(function(n,m){try{l.push(j._pair(n,h[m],{silent:true}))}catch(o){j.error(o)}});if(l.length&&!i.silent){this.trigger("pair:new",l)}return l},clearSelectedUnpaired:function(){this.$(".unpaired-columns .dataset.selected").removeClass("selected")},_mousedownUnpaired:function(j){if(j.shiftKey){var i=this,h=$(j.target).addClass("selected"),k=function(l){i.$(l.target).filter(".dataset").addClass("selected")};h.parent().on("mousemove",k);$(document).one("mouseup",function(l){h.parent().off("mousemove",k);i.pairAllSelected()})}},_clickPairRow:function(j){var k=$(j.currentTarget).index(),i=$(".unpaired-columns .forward-column .dataset").eq(k).data("dataset"),h=$(".unpaired-columns .reverse-column .dataset").eq(k).data("dataset");this._pair(i,h)},_startPartitionDrag:function(i){var h=this,l=i.pageY;$("body").css("cursor","ns-resize");h.$(".flexible-partition-drag").css("color","black");function k(m){h.$(".flexible-partition-drag").css("color","");$("body").css("cursor","").unbind("mousemove",j)}function j(m){var n=m.pageY-l;if(!h.adjPartition(n)){$("body").trigger("mouseup")}h._adjUnpairedOnScrollbar();l+=n}$("body").mousemove(j);$("body").one("mouseup",k)},adjPartition:function(i){var h=this.$(".unpaired-columns"),j=this.$(".paired-columns"),k=parseInt(h.css("height"),10),l=parseInt(j.css("height"),10);k=Math.max(10,k+i);l=l-i;var m=i<0;if(m){if(this.unpairedPanelHidden){return false}else{if(k<=10){this.hideUnpaired();return false}}}else{if(this.unpairedPanelHidden){h.show();this.unpairedPanelHidden=false}}if(!m){if(this.pairedPanelHidden){return false}else{if(l<=15){this.hidePaired();return false}}}else{if(this.pairedPanelHidden){j.show();this.pairedPanelHidden=false}}h.css({height:k+"px",flex:"0 0 auto"});return true},selectPair:function(h){h.stopPropagation();$(h.currentTarget).toggleClass("selected")},clearSelectedPaired:function(h){this.$(".paired-columns .dataset.selected").removeClass("selected")},_clickPairName:function(k){k.stopPropagation();var m=$(k.currentTarget),j=m.parent().parent(),i=j.index(".dataset.paired"),l=this.paired[i],h=prompt("Enter a new name for the pair:",l.name);if(h){l.name=h;l.customizedName=true;m.text(l.name)}},_clickUnpair:function(i){var h=Math.floor($(i.currentTarget).index(".unpair-btn"));this._unpair(this.paired[h])},_dragoverPairedColumns:function(k){k.preventDefault();var i=this.$(".paired-columns .column-datasets");this._checkForAutoscroll(i,k.originalEvent.clientY);var j=this._getNearestPairedDatasetLi(k.originalEvent.clientY);$(".paired-drop-placeholder").remove();var h=$('<div class="paired-drop-placeholder"></div>');if(!j.size()){i.append(h)}else{j.before(h)}},_checkForAutoscroll:function(h,n){var l=2;var m=h.offset(),k=h.scrollTop(),i=n-m.top,j=(m.top+h.outerHeight())-n;if(i>=0&&i<this.autoscrollDist){h.scrollTop(k-l)}else{if(j>=0&&j<this.autoscrollDist){h.scrollTop(k+l)}}},_getNearestPairedDatasetLi:function(o){var l=4,j=this.$(".paired-columns .column-datasets li").toArray();for(var k=0;k<j.length;k++){var n=$(j[k]),m=n.offset().top,h=Math.floor(n.outerHeight()/2)+l;if(m+h>o&&m-h<o){return n}}return $()},_dropPairedColumns:function(i){i.preventDefault();i.dataTransfer.dropEffect="move";var h=this._getNearestPairedDatasetLi(i.originalEvent.clientY);if(h.size()){this.$dragging.insertBefore(h)}else{this.$dragging.insertAfter(this.$(".paired-columns .unpair-btn").last())}this._syncPairsToDom();return false},_syncPairsToDom:function(){var h=[];this.$(".paired-columns .dataset.paired").each(function(){h.push($(this).data("pair"))});this.paired=h;this._renderPaired()},_pairDragstart:function(i,j){j.$el.addClass("selected");var h=this.$(".paired-columns .dataset.selected");this.$dragging=h},_pairDragend:function(h,i){$(".paired-drop-placeholder").remove();this.$dragging=null},toggleExtensions:function(i){var h=this;h.removeExtensions=(i!==undefined)?(i):(!h.removeExtensions);_.each(h.paired,function(j){if(j.customizedName){return}j.name=h._guessNameForPair(j.forward,j.reverse)});h._renderPaired();h._renderFooter()},_changeName:function(h){this._validationWarning("name",!!this._getName())},_nameCheckForEnter:function(h){if(h.keyCode===13){this._clickCreate()}},_getName:function(){return _.escape(this.$(".collection-name").val())},_clickCreate:function(i){var h=this._getName();if(!h){this._validationWarning("name")}else{this.createList()}},_printList:function(i){var h=this;_.each(i,function(j){if(i===h.paired){h._printPair(j)}else{}})},_printPair:function(h){this.debug(h.forward.name,h.reverse.name,": ->",h.name)},toString:function(){return"PairedCollectionCreator"}});e.templates=e.templates||{main:_.template(['<div class="header flex-row no-flex"></div>','<div class="middle flex-row flex-row-container"></div>','<div class="footer flex-row no-flex">'].join("")),header:_.template(['<div class="main-help well clear">','<a class="more-help" href="javascript:void(0);">',d("More help"),"</a>",'<div class="help-content">','<a class="less-help" href="javascript:void(0);">',d("Less"),"</a>","</div>","</div>",'<div class="alert alert-dismissable">','<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>','<span class="alert-message"></span>',"</div>",'<div class="column-headers vertically-spaced flex-column-container">','<div class="forward-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired forward"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter forward-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>",'<div class="paired-column flex-column no-flex column">','<div class="column-header">','<a class="choose-filters-link" href="javascript:void(0)">',d("Choose filters"),"</a>",'<a class="clear-filters-link" href="javascript:void(0);">',d("Clear filters"),"</a><br />",'<a class="autopair-link" href="javascript:void(0);">',d("Auto-pair"),"</a>","</div>","</div>",'<div class="reverse-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired reverse"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter reverse-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>","</div>"].join("")),middle:_.template(['<div class="unpaired-columns flex-column-container scroll-container flex-row">','<div class="forward-column flex-column column">','<ol class="column-datasets"></ol>',"</div>",'<div class="paired-column flex-column no-flex column">','<ol class="column-datasets"></ol>',"</div>",'<div class="reverse-column flex-column column">','<ol class="column-datasets"></ol>',"</div>","</div>",'<div class="flexible-partition">','<div class="flexible-partition-drag" title="',d("Drag to change"),'"></div>','<div class="column-header">','<div class="column-title paired-column-title">','<span class="title"></span>',"</div>",'<a class="unpair-all-link" href="javascript:void(0);">',d("Unpair all"),"</a>","</div>","</div>",'<div class="paired-columns flex-column-container scroll-container flex-row">','<ol class="column-datasets"></ol>',"</div>"].join("")),footer:_.template(['<div class="attributes clear">','<div class="clear">','<label class="remove-extensions-prompt pull-right">',d("Remove file extensions from pair names"),"?",'<input class="remove-extensions pull-right" type="checkbox" />',"</label>","</div>",'<div class="clear">','<input class="collection-name form-control pull-right" ','placeholder="',d("Enter a name for your new list"),'" />','<div class="collection-name-prompt pull-right">',d("Name"),":</div>","</div>","</div>",'<div class="actions clear vertically-spaced">','<div class="other-options pull-left">','<button class="cancel-create btn" tabindex="-1">',d("Cancel"),"</button>",'<div class="create-other btn-group dropup">','<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">',d("Create a different kind of collection"),' <span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">','<li><a href="#">',d("Create a <i>single</i> pair"),"</a></li>",'<li><a href="#">',d("Create a list of <i>unpaired</i> datasets"),"</a></li>","</ul>","</div>","</div>",'<div class="main-options pull-right">','<button class="create-collection btn btn-primary">',d("Create list"),"</button>","</div>","</div>"].join("")),helpContent:_.template(["<p>",d(["Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). ","These collections can be passed to tools and workflows in order to have analyses done on each member of ","the entire group. This interface allows you to create a collection, choose which datasets are paired, ","and re-order the final collection."].join("")),"</p>","<p>",d(['Unpaired datasets are shown in the <i data-target=".unpaired-columns">unpaired section</i> ',"(hover over the underlined words to highlight below). ",'Paired datasets are shown in the <i data-target=".paired-columns">paired section</i>.',"<ul>To pair datasets, you can:","<li>Click a dataset in the ",'<i data-target=".unpaired-columns .forward-column .column-datasets,','.unpaired-columns .forward-column">forward column</i> ',"to select it then click a dataset in the ",'<i data-target=".unpaired-columns .reverse-column .column-datasets,','.unpaired-columns .reverse-column">reverse column</i>.',"</li>",'<li>Click one of the "Pair these datasets" buttons in the ','<i data-target=".unpaired-columns .paired-column .column-datasets,','.unpaired-columns .paired-column">middle column</i> ',"to pair the datasets in a particular row.","</li>",'<li>Click <i data-target=".autopair-link">"Auto-pair"</i> ',"to have your datasets automatically paired based on name.","</li>","</ul>"].join("")),"</p>","<p>",d(["<ul>You can filter what is shown in the unpaired sections by:","<li>Entering partial dataset names in either the ",'<i data-target=".forward-unpaired-filter input">forward filter</i> or ','<i data-target=".reverse-unpaired-filter input">reverse filter</i>.',"</li>","<li>Choosing from a list of preset filters by clicking the ",'<i data-target=".choose-filters-link">"Choose filters" link</i>.',"</li>","<li>Entering regular expressions to match dataset names. See: ",'<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expre…"',' target="_blank">MDN\'s JavaScript Regular Expression Tutorial</a>. ',"Note: forward slashes (\\) are not needed.","</li>","<li>Clearing the filters by clicking the ",'<i data-target=".clear-filters-link">"Clear filters" link</i>.',"</li>","</ul>"].join("")),"</p>","<p>",d(["To unpair individual dataset pairs, click the ",'<i data-target=".unpair-btn">unpair buttons ( <span class="fa fa-unlink"></span> )</i>. ','Click the <i data-target=".unpair-all-link">"Unpair all" link</i> to unpair all pairs.'].join("")),"</p>","<p>",d(['You can include or remove the file extensions (e.g. ".fastq") from your pair names by toggling the ','<i data-target=".remove-extensions-prompt">"Remove file extensions from pair names?"</i> control.'].join("")),"</p>","<p>",d(['Once your collection is complete, enter a <i data-target=".collection-name">name</i> and ','click <i data-target=".create-collection">"Create list"</i>. ',"(Note: you do not have to pair all unpaired datasets to finish.)"].join("")),"</p>"].join(""))};(function(){jQuery.fn.extend({hoverhighlight:function h(j,i){j=j||"body";if(!this.size()){return this}$(this).each(function(){var l=$(this),k=l.data("target");if(k){l.mouseover(function(m){$(k,j).css({background:i})}).mouseout(function(m){$(k).css({background:""})})}});return this}})}());var b=function c(j,h){h=_.defaults(h||{},{datasets:j,oncancel:function(){Galaxy.modal.hide()},oncreate:function(){Galaxy.modal.hide();Galaxy.currHistoryPanel.refreshContents()}});if(!window.Galaxy||!Galaxy.modal){throw new Error("Galaxy or Galaxy.modal not found")}var i=new e(h).render();Galaxy.modal.show({title:"Create a collection of paired datasets",body:i.$el,width:"80%",height:"800px",closing_events:true});window.PCC=i;return i};return{PairedCollectionCreator:e,pairedCollectionCreatorModal:b}});
\ No newline at end of file
+define(["utils/levenshtein","mvc/base-mvc","utils/localization"],function(g,a,d){var f=Backbone.View.extend(a.LoggableMixin).extend({tagName:"li",className:"dataset paired",initialize:function(h){this.pair=h.pair||{}},template:_.template(['<span class="forward-dataset-name flex-column"><%= pair.forward.name %></span>','<span class="pair-name-column flex-column">','<span class="pair-name"><%= pair.name %></span>',"</span>",'<span class="reverse-dataset-name flex-column"><%= pair.reverse.name %></span>'].join("")),render:function(){this.$el.attr("draggable",true).data("pair",this.pair).html(this.template({pair:this.pair})).addClass("flex-column-container");return this},events:{dragstart:"_dragstart",dragend:"_dragend",dragover:"_sendToParent",drop:"_sendToParent"},_dragstart:function(h){h.currentTarget.style.opacity="0.4";if(h.originalEvent){h=h.originalEvent}h.dataTransfer.effectAllowed="move";h.dataTransfer.setData("text/plain",JSON.stringify(this.pair));this.$el.parent().trigger("pair.dragstart",[this])},_dragend:function(h){h.currentTarget.style.opacity="1.0";this.$el.parent().trigger("pair.dragend",[this])},_sendToParent:function(h){this.$el.parent().trigger(h)},toString:function(){return"PairView("+this.pair.name+")"}});var e=Backbone.View.extend(a.LoggableMixin).extend({className:"collection-creator flex-row-container",initialize:function(h){h=_.defaults(h,{datasets:[],filters:this.DEFAULT_FILTERS,automaticallyPair:true,matchPercentage:1,strategy:"lcs"});this.initialList=h.datasets;this.historyId=h.historyId;this.filters=this.commonFilters[h.filters]||this.commonFilters[this.DEFAULT_FILTERS];if(_.isArray(h.filters)){this.filters=h.filters}this.automaticallyPair=h.automaticallyPair;this.matchPercentage=h.matchPercentage;this.strategy=this.strategies[h.strategy]||this.strategies[this.DEFAULT_STRATEGY];if(_.isFunction(h.strategy)){this.strategy=h.strategy}this.removeExtensions=true;this.oncancel=h.oncancel;this.oncreate=h.oncreate;this.autoscrollDist=h.autoscrollDist||24;this.unpairedPanelHidden=false;this.pairedPanelHidden=false;this.$dragging=null;this._setUpBehaviors();this._dataSetUp()},commonFilters:{none:["",""],illumina:["_1","_2"]},DEFAULT_FILTERS:"illumina",strategies:{lcs:"autoPairLCSs",levenshtein:"autoPairLevenshtein"},DEFAULT_STRATEGY:"lcs",_dataSetUp:function(){this.paired=[];this.unpaired=[];this.selectedIds=[];this._sortInitialList();this._ensureIds();this.unpaired=this.initialList.slice(0);if(this.automaticallyPair){this.autoPair();this.once("rendered:initial",function(){this.trigger("autopair")})}},_sortInitialList:function(){this._sortDatasetList(this.initialList)},_sortDatasetList:function(h){h.sort(function(j,i){return naturalSort(j.name,i.name)});return h},_ensureIds:function(){this.initialList.forEach(function(h){if(!h.hasOwnProperty("id")){h.id=_.uniqueId()}});return this.initialList},_splitByFilters:function(k){var j=[],h=[];function i(l){if(this._filterFwdFn(l)){j.push(l)}if(this._filterRevFn(l)){h.push(l)}}this.unpaired.forEach(_.bind(i,this));return[j,h]},_filterFwdFn:function(i){var h=new RegExp(this.filters[0]);return h.test(i.name)},_filterRevFn:function(i){var h=new RegExp(this.filters[1]);return h.test(i.name)},_addToUnpaired:function(i){var h=function(j,l){if(j===l){return j}var k=Math.floor((l-j)/2)+j,m=naturalSort(i.name,this.unpaired[k].name);if(m<0){return h(j,k)}else{if(m>0){return h(k+1,l)}}while(this.unpaired[k]&&this.unpaired[k].name===i.name){k++}return k}.bind(this);this.unpaired.splice(h(0,this.unpaired.length),0,i)},autoPair:function(i){i=i||this.strategy;var h=this.simpleAutoPair();h=h.concat(this[i].call(this));return h},simpleAutoPair:function(){var o=0,m,s=this._splitByFilters(),h=s[0],r=s[1],q,u,k=false,t=[];while(o<h.length){var n=h[o];q=n.name.replace(this.filters[0],"");k=false;for(m=0;m<r.length;m++){var p=r[m];u=p.name.replace(this.filters[1],"");if(n!==p&&q===u){k=true;var l=this._pair(h.splice(o,1)[0],r.splice(m,1)[0],{silent:true});t.push(l);break}}if(!k){o+=1}}return t},autoPairLevenshtein:function(){var p=0,n,u=this._splitByFilters(),h=u[0],s=u[1],r,x,k,t,l,v=[];while(p<h.length){var o=h[p];r=o.name.replace(this.filters[0],"");l=Number.MAX_VALUE;for(n=0;n<s.length;n++){var q=s[n];x=q.name.replace(this.filters[1],"");if(o!==q){if(r===x){t=n;l=0;break}k=levenshteinDistance(r,x);if(k<l){t=n;l=k}}}var w=1-(l/(Math.max(r.length,x.length)));if(w>=this.matchPercentage){var m=this._pair(h.splice(p,1)[0],s.splice(t,1)[0],{silent:true});v.push(m);if(h.length<=0||s.length<=0){return v}}else{p+=1}}return v},autoPairLCSs:function(){var n=0,l,u=this._splitByFilters(),h=u[0],s=u[1],r,y,x,t,p,v=[];if(!h.length||!s.length){return v}while(n<h.length){var m=h[n];r=m.name.replace(this.filters[0],"");p=0;for(l=0;l<s.length;l++){var q=s[l];y=q.name.replace(this.filters[1],"");if(m!==q){if(r===y){t=l;p=r.length;break}var o=this._naiveStartingAndEndingLCS(r,y);x=o.length;if(x>p){t=l;p=x}}}var w=p/(Math.min(r.length,y.length));if(w>=this.matchPercentage){var k=this._pair(h.splice(n,1)[0],s.splice(t,1)[0],{silent:true});v.push(k);if(h.length<=0||s.length<=0){return v}}else{n+=1}}return v},_naiveStartingAndEndingLCS:function(m,k){var n="",o="",l=0,h=0;while(l<m.length&&l<k.length){if(m[l]!==k[l]){break}n+=m[l];l+=1}if(l===m.length){return m}if(l===k.length){return k}l=(m.length-1);h=(k.length-1);while(l>=0&&h>=0){if(m[l]!==k[h]){break}o=[m[l],o].join("");l-=1;h-=1}return n+o},_pair:function(j,h,i){i=i||{};var k=this._createPair(j,h,i.name);this.paired.push(k);this.unpaired=_.without(this.unpaired,j,h);if(!i.silent){this.trigger("pair:new",k)}return k},_createPair:function(j,h,i){if(!(j&&h)||(j===h)){throw new Error("Bad pairing: "+[JSON.stringify(j),JSON.stringify(h)])}i=i||this._guessNameForPair(j,h);return{forward:j,name:i,reverse:h}},_guessNameForPair:function(j,h,k){k=(k!==undefined)?(k):(this.removeExtensions);var i=this._naiveStartingAndEndingLCS(j.name.replace(this.filters[0],""),h.name.replace(this.filters[1],""));if(k){var l=i.lastIndexOf(".");if(l>0){i=i.slice(0,l)}}return i||(j.name+" & "+h.name)},_unpair:function(i,h){h=h||{};if(!i){throw new Error("Bad pair: "+JSON.stringify(i))}this.paired=_.without(this.paired,i);this._addToUnpaired(i.forward);this._addToUnpaired(i.reverse);if(!h.silent){this.trigger("pair:unpair",[i])}return i},unpairAll:function(){var h=[];while(this.paired.length){h.push(this._unpair(this.paired[0],{silent:true}))}this.trigger("pair:unpair",h)},_pairToJSON:function(h){return{collection_type:"paired",src:"new_collection",name:h.name,element_identifiers:[{name:"forward",id:h.forward.id,src:"hda"},{name:"reverse",id:h.reverse.id,src:"hda"}]}},createList:function(j){var k=this,i;if(k.historyId){i="/api/histories/"+this.historyId+"/contents/dataset_collections"}var h={type:"dataset_collection",collection_type:"list:paired",name:_.escape(j||k.$(".collection-name").val()),element_identifiers:k.paired.map(function(l){return k._pairToJSON(l)})};return jQuery.ajax(i,{type:"POST",contentType:"application/json",dataType:"json",data:JSON.stringify(h)}).fail(function(n,l,m){k._ajaxErrHandler(n,l,m)}).done(function(l,m,n){k.trigger("collection:created",l,m,n);if(typeof k.oncreate==="function"){k.oncreate.call(this,l,m,n)}})},_ajaxErrHandler:function(k,h,j){this.error(k,h,j);var i=d("An error occurred while creating this collection");if(k){if(k.readyState===0&&k.status===0){i+=": "+d("Galaxy could not be reached and may be updating.")+d(" Try again in a few minutes.")}else{if(k.responseJSON){i+="<br /><pre>"+JSON.stringify(k.responseJSON)+"</pre>"}else{i+=": "+j}}}creator._showAlert(i,"alert-danger")},render:function(h,i){this.$el.empty().html(e.templates.main());this._renderHeader(h);this._renderMiddle(h);this._renderFooter(h);this._addPluginComponents();this.trigger("rendered",this);return this},_renderHeader:function(i,j){var h=this.$(".header").empty().html(e.templates.header()).find(".help-content").prepend($(e.templates.helpContent()));this._renderFilters();return h},_renderFilters:function(){return this.$(".forward-column .column-header input").val(this.filters[0]).add(this.$(".reverse-column .column-header input").val(this.filters[1]))},_renderMiddle:function(i,j){var h=this.$(".middle").empty().html(e.templates.middle());if(this.unpairedPanelHidden){this.$(".unpaired-columns").hide()}else{if(this.pairedPanelHidden){this.$(".paired-columns").hide()}}this._renderUnpaired();this._renderPaired();return h},_renderUnpaired:function(m,n){var k=this,l,i,h=[],j=this._splitByFilters();this.$(".forward-column .title").text([j[0].length,d("unpaired forward")].join(" "));this.$(".forward-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[0].length));this.$(".reverse-column .title").text([j[1].length,d("unpaired reverse")].join(" "));this.$(".reverse-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[1].length));this.$(".unpaired-columns .column-datasets").empty();this.$(".autopair-link").toggle(this.unpaired.length!==0);if(this.unpaired.length===0){this._renderUnpairedEmpty();return}i=j[1].map(function(p,o){if((j[0][o]!==undefined)&&(j[0][o]!==p)){h.push(k._renderPairButton())}return k._renderUnpairedDataset(p)});l=j[0].map(function(o){return k._renderUnpairedDataset(o)});if(!l.length&&!i.length){this._renderUnpairedNotShown();return}this.$(".unpaired-columns .forward-column .column-datasets").append(l).add(this.$(".unpaired-columns .paired-column .column-datasets").append(h)).add(this.$(".unpaired-columns .reverse-column .column-datasets").append(i));this._adjUnpairedOnScrollbar()},_renderUnpairedDisplayStr:function(h){return["(",h," ",d("filtered out"),")"].join("")},_renderUnpairedDataset:function(h){return $("<li/>").attr("id","dataset-"+h.id).addClass("dataset unpaired").attr("draggable",true).addClass(h.selected?"selected":"").append($("<span/>").addClass("dataset-name").text(h.name)).data("dataset",h)},_renderPairButton:function(){return $("<li/>").addClass("dataset unpaired").append($("<span/>").addClass("dataset-name").text(d("Pair these datasets")))},_renderUnpairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no remaining unpaired datasets")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_renderUnpairedNotShown:function(){var h=$('<div class="empty-message"></div>').text("("+d("no datasets were found matching the current filters")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_adjUnpairedOnScrollbar:function(){var k=this.$(".unpaired-columns").last(),l=this.$(".unpaired-columns .reverse-column .dataset").first();if(!l.size()){return}var h=k.offset().left+k.outerWidth(),j=l.offset().left+l.outerWidth(),i=Math.floor(h)-Math.floor(j);this.$(".unpaired-columns .forward-column").css("margin-left",(i>0)?i:0)},_renderPaired:function(i,j){this.$(".paired-column-title .title").text([this.paired.length,d("paired")].join(" "));this.$(".unpair-all-link").toggle(this.paired.length!==0);if(this.paired.length===0){this._renderPairedEmpty();return}else{this.$(".remove-extensions-link").show()}this.$(".paired-columns .column-datasets").empty();var h=this;this.paired.forEach(function(m,k){var l=new f({pair:m});h.$(".paired-columns .column-datasets").append(l.render().$el).append(['<button class="unpair-btn">','<span class="fa fa-unlink" title="',d("Unpair"),'"></span>',"</button>"].join(""))})},_renderPairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no paired datasets yet")+")");this.$(".paired-columns .column-datasets").empty().prepend(h);return h},_renderFooter:function(i,j){var h=this.$(".footer").empty().html(e.templates.footer());this.$(".remove-extensions").prop("checked",this.removeExtensions);if(typeof this.oncancel==="function"){this.$(".cancel-create.btn").show()}return h},_addPluginComponents:function(){this._chooseFiltersPopover(".choose-filters-link");this.$(".help-content i").hoverhighlight(".collection-creator","rgba( 64, 255, 255, 1.0 )")},_chooseFiltersPopover:function(h){function i(l,k){return['<button class="filter-choice btn" ','data-forward="',l,'" data-reverse="',k,'">',d("Forward"),": ",l,", ",d("Reverse"),": ",k,"</button>"].join("")}var j=$(_.template(['<div class="choose-filters">','<div class="help">',d("Choose from the following filters to change which unpaired reads are shown in the display"),":</div>",i("_1","_2"),i("_R1","_R2"),"</div>"].join(""))({}));return this.$(h).popover({container:".collection-creator",placement:"bottom",html:true,content:j})},_validationWarning:function(i,h){var j="validation-warning";if(i==="name"){i=this.$(".collection-name").add(this.$(".collection-name-prompt"));this.$(".collection-name").focus().select()}if(h){i=i||this.$("."+j);i.removeClass(j)}else{i.addClass(j)}},_setUpBehaviors:function(){this.once("rendered",function(){this.trigger("rendered:initial",this)});this.on("pair:new",function(){this._renderUnpaired();this._renderPaired();this.$(".paired-columns").scrollTop(8000000)});this.on("pair:unpair",function(h){this._renderUnpaired();this._renderPaired();this.splitView()});this.on("filter-change",function(){this.filters=[this.$(".forward-unpaired-filter input").val(),this.$(".reverse-unpaired-filter input").val()];this._renderFilters();this._renderUnpaired()});this.on("autopair",function(){this._renderUnpaired();this._renderPaired();var h,i=null;if(this.paired.length){i="alert-success";h=this.paired.length+" "+d("pairs created");if(!this.unpaired.length){h+=": "+d("all datasets have been successfully paired");this.hideUnpaired();this.$(".collection-name").focus()}}else{h=d("Could not automatically create any pairs from the given dataset names")}this._showAlert(h,i)});return this},events:{"click .more-help":"_clickMoreHelp","click .less-help":"_clickLessHelp","click .header .alert button":"_hideAlert","click .forward-column .column-title":"_clickShowOnlyUnpaired","click .reverse-column .column-title":"_clickShowOnlyUnpaired","click .unpair-all-link":"_clickUnpairAll","change .forward-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .forward-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .autopair-link":"_clickAutopair","click .choose-filters .filter-choice":"_clickFilterChoice","click .clear-filters-link":"_clearFilters","change .reverse-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .reverse-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .forward-column .dataset.unpaired":"_clickUnpairedDataset","click .reverse-column .dataset.unpaired":"_clickUnpairedDataset","click .paired-column .dataset.unpaired":"_clickPairRow","click .unpaired-columns":"clearSelectedUnpaired","mousedown .unpaired-columns .dataset":"_mousedownUnpaired","click .paired-column-title":"_clickShowOnlyPaired","mousedown .flexible-partition-drag":"_startPartitionDrag","click .paired-columns .dataset.paired":"selectPair","click .paired-columns":"clearSelectedPaired","click .paired-columns .pair-name":"_clickPairName","click .unpair-btn":"_clickUnpair","dragover .paired-columns .column-datasets":"_dragoverPairedColumns","drop .paired-columns .column-datasets":"_dropPairedColumns","pair.dragstart .paired-columns .column-datasets":"_pairDragstart","pair.dragend .paired-columns .column-datasets":"_pairDragend","change .remove-extensions":function(h){this.toggleExtensions()},"change .collection-name":"_changeName","keydown .collection-name":"_nameCheckForEnter","click .cancel-create":function(h){if(typeof this.oncancel==="function"){this.oncancel.call(this)}},"click .create-collection":"_clickCreate"},_clickMoreHelp:function(h){this.$(".main-help").addClass("expanded");this.$(".more-help").hide()},_clickLessHelp:function(h){this.$(".main-help").removeClass("expanded");this.$(".more-help").show()},_showAlert:function(i,h){h=h||"alert-danger";this.$(".main-help").hide();this.$(".header .alert").attr("class","alert alert-dismissable").addClass(h).show().find(".alert-message").html(i)},_hideAlert:function(h){this.$(".main-help").show();this.$(".header .alert").hide()},_clickShowOnlyUnpaired:function(h){if(this.$(".paired-columns").is(":visible")){this.hidePaired()}else{this.splitView()}},_clickShowOnlyPaired:function(h){if(this.$(".unpaired-columns").is(":visible")){this.hideUnpaired()}else{this.splitView()}},hideUnpaired:function(h,i){this.unpairedPanelHidden=true;this.pairedPanelHidden=false;this._renderMiddle(h,i)},hidePaired:function(h,i){this.unpairedPanelHidden=false;this.pairedPanelHidden=true;this._renderMiddle(h,i)},splitView:function(h,i){this.unpairedPanelHidden=this.pairedPanelHidden=false;this._renderMiddle(h,i);return this},_clickUnpairAll:function(h){this.unpairAll()},_clickAutopair:function(h){this.autoPair();this.trigger("autopair")},_clickFilterChoice:function(i){var h=$(i.currentTarget);this.$(".forward-unpaired-filter input").val(h.data("forward"));this.$(".reverse-unpaired-filter input").val(h.data("reverse"));this._hideChooseFilters();this.trigger("filter-change")},_hideChooseFilters:function(){this.$(".choose-filters-link").popover("hide");this.$(".popover").css("display","none")},_clearFilters:function(h){this.$(".forward-unpaired-filter input").val("");this.$(".reverse-unpaired-filter input").val("");this.trigger("filter-change")},_clickUnpairedDataset:function(h){h.stopPropagation();return this.toggleSelectUnpaired($(h.currentTarget))},toggleSelectUnpaired:function(j,i){i=i||{};var k=j.data("dataset"),h=i.force!==undefined?i.force:!j.hasClass("selected");if(!j.size()||k===undefined){return j}if(h){j.addClass("selected");if(!i.waitToPair){this.pairAllSelected()}}else{j.removeClass("selected")}return j},pairAllSelected:function(i){i=i||{};var j=this,k=[],h=[],l=[];j.$(".unpaired-columns .forward-column .dataset.selected").each(function(){k.push($(this).data("dataset"))});j.$(".unpaired-columns .reverse-column .dataset.selected").each(function(){h.push($(this).data("dataset"))});k.length=h.length=Math.min(k.length,h.length);k.forEach(function(n,m){try{l.push(j._pair(n,h[m],{silent:true}))}catch(o){j.error(o)}});if(l.length&&!i.silent){this.trigger("pair:new",l)}return l},clearSelectedUnpaired:function(){this.$(".unpaired-columns .dataset.selected").removeClass("selected")},_mousedownUnpaired:function(j){if(j.shiftKey){var i=this,h=$(j.target).addClass("selected"),k=function(l){i.$(l.target).filter(".dataset").addClass("selected")};h.parent().on("mousemove",k);$(document).one("mouseup",function(l){h.parent().off("mousemove",k);i.pairAllSelected()})}},_clickPairRow:function(j){var k=$(j.currentTarget).index(),i=$(".unpaired-columns .forward-column .dataset").eq(k).data("dataset"),h=$(".unpaired-columns .reverse-column .dataset").eq(k).data("dataset");this._pair(i,h)},_startPartitionDrag:function(i){var h=this,l=i.pageY;$("body").css("cursor","ns-resize");h.$(".flexible-partition-drag").css("color","black");function k(m){h.$(".flexible-partition-drag").css("color","");$("body").css("cursor","").unbind("mousemove",j)}function j(m){var n=m.pageY-l;if(!h.adjPartition(n)){$("body").trigger("mouseup")}h._adjUnpairedOnScrollbar();l+=n}$("body").mousemove(j);$("body").one("mouseup",k)},adjPartition:function(i){var h=this.$(".unpaired-columns"),j=this.$(".paired-columns"),k=parseInt(h.css("height"),10),l=parseInt(j.css("height"),10);k=Math.max(10,k+i);l=l-i;var m=i<0;if(m){if(this.unpairedPanelHidden){return false}else{if(k<=10){this.hideUnpaired();return false}}}else{if(this.unpairedPanelHidden){h.show();this.unpairedPanelHidden=false}}if(!m){if(this.pairedPanelHidden){return false}else{if(l<=15){this.hidePaired();return false}}}else{if(this.pairedPanelHidden){j.show();this.pairedPanelHidden=false}}h.css({height:k+"px",flex:"0 0 auto"});return true},selectPair:function(h){h.stopPropagation();$(h.currentTarget).toggleClass("selected")},clearSelectedPaired:function(h){this.$(".paired-columns .dataset.selected").removeClass("selected")},_clickPairName:function(k){k.stopPropagation();var m=$(k.currentTarget),j=m.parent().parent(),i=j.index(".dataset.paired"),l=this.paired[i],h=prompt("Enter a new name for the pair:",l.name);if(h){l.name=h;l.customizedName=true;m.text(l.name)}},_clickUnpair:function(i){var h=Math.floor($(i.currentTarget).index(".unpair-btn"));this._unpair(this.paired[h])},_dragoverPairedColumns:function(k){k.preventDefault();var i=this.$(".paired-columns .column-datasets");this._checkForAutoscroll(i,k.originalEvent.clientY);var j=this._getNearestPairedDatasetLi(k.originalEvent.clientY);$(".paired-drop-placeholder").remove();var h=$('<div class="paired-drop-placeholder"></div>');if(!j.size()){i.append(h)}else{j.before(h)}},_checkForAutoscroll:function(h,n){var l=2;var m=h.offset(),k=h.scrollTop(),i=n-m.top,j=(m.top+h.outerHeight())-n;if(i>=0&&i<this.autoscrollDist){h.scrollTop(k-l)}else{if(j>=0&&j<this.autoscrollDist){h.scrollTop(k+l)}}},_getNearestPairedDatasetLi:function(o){var l=4,j=this.$(".paired-columns .column-datasets li").toArray();for(var k=0;k<j.length;k++){var n=$(j[k]),m=n.offset().top,h=Math.floor(n.outerHeight()/2)+l;if(m+h>o&&m-h<o){return n}}return $()},_dropPairedColumns:function(i){i.preventDefault();i.dataTransfer.dropEffect="move";var h=this._getNearestPairedDatasetLi(i.originalEvent.clientY);if(h.size()){this.$dragging.insertBefore(h)}else{this.$dragging.insertAfter(this.$(".paired-columns .unpair-btn").last())}this._syncPairsToDom();return false},_syncPairsToDom:function(){var h=[];this.$(".paired-columns .dataset.paired").each(function(){h.push($(this).data("pair"))});this.paired=h;this._renderPaired()},_pairDragstart:function(i,j){j.$el.addClass("selected");var h=this.$(".paired-columns .dataset.selected");this.$dragging=h},_pairDragend:function(h,i){$(".paired-drop-placeholder").remove();this.$dragging=null},toggleExtensions:function(i){var h=this;h.removeExtensions=(i!==undefined)?(i):(!h.removeExtensions);_.each(h.paired,function(j){if(j.customizedName){return}j.name=h._guessNameForPair(j.forward,j.reverse)});h._renderPaired();h._renderFooter()},_changeName:function(h){this._validationWarning("name",!!this._getName())},_nameCheckForEnter:function(h){if(h.keyCode===13){this._clickCreate()}},_getName:function(){return _.escape(this.$(".collection-name").val())},_clickCreate:function(i){var h=this._getName();if(!h){this._validationWarning("name")}else{this.createList()}},_printList:function(i){var h=this;_.each(i,function(j){if(i===h.paired){h._printPair(j)}else{}})},_printPair:function(h){this.debug(h.forward.name,h.reverse.name,": ->",h.name)},toString:function(){return"PairedCollectionCreator"}});e.templates=e.templates||{main:_.template(['<div class="header flex-row no-flex"></div>','<div class="middle flex-row flex-row-container"></div>','<div class="footer flex-row no-flex">'].join("")),header:_.template(['<div class="main-help well clear">','<a class="more-help" href="javascript:void(0);">',d("More help"),"</a>",'<div class="help-content">','<a class="less-help" href="javascript:void(0);">',d("Less"),"</a>","</div>","</div>",'<div class="alert alert-dismissable">','<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>','<span class="alert-message"></span>',"</div>",'<div class="column-headers vertically-spaced flex-column-container">','<div class="forward-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired forward"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter forward-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>",'<div class="paired-column flex-column no-flex column">','<div class="column-header">','<a class="choose-filters-link" href="javascript:void(0)">',d("Choose filters"),"</a>",'<a class="clear-filters-link" href="javascript:void(0);">',d("Clear filters"),"</a><br />",'<a class="autopair-link" href="javascript:void(0);">',d("Auto-pair"),"</a>","</div>","</div>",'<div class="reverse-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired reverse"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter reverse-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>","</div>"].join("")),middle:_.template(['<div class="unpaired-columns flex-column-container scroll-container flex-row">','<div class="forward-column flex-column column">','<ol class="column-datasets"></ol>',"</div>",'<div class="paired-column flex-column no-flex column">','<ol class="column-datasets"></ol>',"</div>",'<div class="reverse-column flex-column column">','<ol class="column-datasets"></ol>',"</div>","</div>",'<div class="flexible-partition">','<div class="flexible-partition-drag" title="',d("Drag to change"),'"></div>','<div class="column-header">','<div class="column-title paired-column-title">','<span class="title"></span>',"</div>",'<a class="unpair-all-link" href="javascript:void(0);">',d("Unpair all"),"</a>","</div>","</div>",'<div class="paired-columns flex-column-container scroll-container flex-row">','<ol class="column-datasets"></ol>',"</div>"].join("")),footer:_.template(['<div class="attributes clear">','<div class="clear">','<label class="remove-extensions-prompt pull-right">',d("Remove file extensions from pair names"),"?",'<input class="remove-extensions pull-right" type="checkbox" />',"</label>","</div>",'<div class="clear">','<input class="collection-name form-control pull-right" ','placeholder="',d("Enter a name for your new list"),'" />','<div class="collection-name-prompt pull-right">',d("Name"),":</div>","</div>","</div>",'<div class="actions clear vertically-spaced">','<div class="other-options pull-left">','<button class="cancel-create btn" tabindex="-1">',d("Cancel"),"</button>",'<div class="create-other btn-group dropup">','<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">',d("Create a different kind of collection"),' <span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">','<li><a href="#">',d("Create a <i>single</i> pair"),"</a></li>",'<li><a href="#">',d("Create a list of <i>unpaired</i> datasets"),"</a></li>","</ul>","</div>","</div>",'<div class="main-options pull-right">','<button class="create-collection btn btn-primary">',d("Create list"),"</button>","</div>","</div>"].join("")),helpContent:_.template(["<p>",d(["Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). ","These collections can be passed to tools and workflows in order to have analyses done on each member of ","the entire group. This interface allows you to create a collection, choose which datasets are paired, ","and re-order the final collection."].join("")),"</p>","<p>",d(['Unpaired datasets are shown in the <i data-target=".unpaired-columns">unpaired section</i> ',"(hover over the underlined words to highlight below). ",'Paired datasets are shown in the <i data-target=".paired-columns">paired section</i>.',"<ul>To pair datasets, you can:","<li>Click a dataset in the ",'<i data-target=".unpaired-columns .forward-column .column-datasets,','.unpaired-columns .forward-column">forward column</i> ',"to select it then click a dataset in the ",'<i data-target=".unpaired-columns .reverse-column .column-datasets,','.unpaired-columns .reverse-column">reverse column</i>.',"</li>",'<li>Click one of the "Pair these datasets" buttons in the ','<i data-target=".unpaired-columns .paired-column .column-datasets,','.unpaired-columns .paired-column">middle column</i> ',"to pair the datasets in a particular row.","</li>",'<li>Click <i data-target=".autopair-link">"Auto-pair"</i> ',"to have your datasets automatically paired based on name.","</li>","</ul>"].join("")),"</p>","<p>",d(["<ul>You can filter what is shown in the unpaired sections by:","<li>Entering partial dataset names in either the ",'<i data-target=".forward-unpaired-filter input">forward filter</i> or ','<i data-target=".reverse-unpaired-filter input">reverse filter</i>.',"</li>","<li>Choosing from a list of preset filters by clicking the ",'<i data-target=".choose-filters-link">"Choose filters" link</i>.',"</li>","<li>Entering regular expressions to match dataset names. See: ",'<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expre…"',' target="_blank">MDN\'s JavaScript Regular Expression Tutorial</a>. ',"Note: forward slashes (\\) are not needed.","</li>","<li>Clearing the filters by clicking the ",'<i data-target=".clear-filters-link">"Clear filters" link</i>.',"</li>","</ul>"].join("")),"</p>","<p>",d(["To unpair individual dataset pairs, click the ",'<i data-target=".unpair-btn">unpair buttons ( <span class="fa fa-unlink"></span> )</i>. ','Click the <i data-target=".unpair-all-link">"Unpair all" link</i> to unpair all pairs.'].join("")),"</p>","<p>",d(['You can include or remove the file extensions (e.g. ".fastq") from your pair names by toggling the ','<i data-target=".remove-extensions-prompt">"Remove file extensions from pair names?"</i> control.'].join("")),"</p>","<p>",d(['Once your collection is complete, enter a <i data-target=".collection-name">name</i> and ','click <i data-target=".create-collection">"Create list"</i>. ',"(Note: you do not have to pair all unpaired datasets to finish.)"].join("")),"</p>"].join(""))};(function(){jQuery.fn.extend({hoverhighlight:function h(j,i){j=j||"body";if(!this.size()){return this}$(this).each(function(){var l=$(this),k=l.data("target");if(k){l.mouseover(function(m){$(k,j).css({background:i})}).mouseout(function(m){$(k).css({background:""})})}});return this}})}());var b=function c(j,h){console.log(j);h=_.defaults(h||{},{datasets:j,oncancel:function(){Galaxy.modal.hide()},oncreate:function(){Galaxy.modal.hide();Galaxy.currHistoryPanel.refreshContents()}});if(!window.Galaxy||!Galaxy.modal){throw new Error("Galaxy or Galaxy.modal not found")}var i=new e(h).render();Galaxy.modal.show({title:"Create a collection of paired datasets",body:i.$el,width:"80%",height:"800px",closing_events:true});window.PCC=i;return i};return{PairedCollectionCreator:e,pairedCollectionCreatorModal:b}});
\ No newline at end of file
diff -r 7ef4ebeaa607b32151ca30c96ba774a3fc0d2274 -r 109da695364ceee5c27bf71b6a0bed918813fcda templates/webapps/galaxy/root/index.mako
--- a/templates/webapps/galaxy/root/index.mako
+++ b/templates/webapps/galaxy/root/index.mako
@@ -152,6 +152,12 @@
currPanel.connectToQuotaMeter( Galaxy.quotaMeter );
currPanel.loadCurrentHistory();
Galaxy.currHistoryPanel = currPanel;
+
+currPanel.once( 'rendered', function(){
+ currPanel.showSelectors();
+ currPanel.selectAll();
+ _.last( currPanel.actionsPopup.options ).func();
+});
});
});
</script>
diff -r 7ef4ebeaa607b32151ca30c96ba774a3fc0d2274 -r 109da695364ceee5c27bf71b6a0bed918813fcda test/qunit/test-common.js
--- a/test/qunit/test-common.js
+++ b/test/qunit/test-common.js
@@ -72,7 +72,6 @@
});
-
function bridge_phantomjs( QUnit ) {
// Needed because the grunt task will attempt to inject this bridge assuming
// QUnit is loaded directly - not using require.js.
diff -r 7ef4ebeaa607b32151ca30c96ba774a3fc0d2274 -r 109da695364ceee5c27bf71b6a0bed918813fcda test/qunit/test-data/paired-collection-creator.data.js
--- /dev/null
+++ b/test/qunit/test-data/paired-collection-creator.data.js
@@ -0,0 +1,153 @@
+define([], function(){
+// ============================================================================
+// plain 3 step job chain
+var datasets1 = [
+ { name: 'SET1-01_1.fastq' },
+ { name: 'SET1-01_2.fastq' },
+ { name: 'SET1-02_1.fastq' },
+ { name: 'SET1-02_2.fastq' },
+ { name: 'SET1-03_1.fastq' },
+ { name: 'SET1-03_2.fastq' },
+ { name: 'SET1-04_1.fastq' },
+ { name: 'SET1-04_2.fastq' },
+ { name: 'SET1-05_1.fastq' },
+ { name: 'SET1-05_2.fastq' },
+ { name: 'SET1-06_1.fastq' },
+ { name: 'SET1-06_2.fastq' },
+ { name: 'SET1-07_1.fastq' },
+ { name: 'SET1-07_2.fastq' }
+];
+
+var datasets1CreateRequestJSON = {
+ "type": "dataset_collection",
+ "collection_type": "list:paired",
+ "name": "Heres a collection",
+ "element_identifiers": [
+ {
+ "collection_type": "paired",
+ "src": "new_collection",
+ "name": "SET1-07",
+ "element_identifiers": [
+ {
+ "name": "forward",
+ "id": "2",
+ "src": "hda"
+ },
+ {
+ "name": "reverse",
+ "id": "3",
+ "src": "hda"
+ }
+ ]
+ },
+ {
+ "collection_type": "paired",
+ "src": "new_collection",
+ "name": "SET1-06",
+ "element_identifiers": [
+ {
+ "name": "forward",
+ "id": "4",
+ "src": "hda"
+ },
+ {
+ "name": "reverse",
+ "id": "5",
+ "src": "hda"
+ }
+ ]
+ },
+ {
+ "collection_type": "paired",
+ "src": "new_collection",
+ "name": "SET1-05",
+ "element_identifiers": [
+ {
+ "name": "forward",
+ "id": "6",
+ "src": "hda"
+ },
+ {
+ "name": "reverse",
+ "id": "7",
+ "src": "hda"
+ }
+ ]
+ },
+ {
+ "collection_type": "paired",
+ "src": "new_collection",
+ "name": "SET1-04",
+ "element_identifiers": [
+ {
+ "name": "forward",
+ "id": "8",
+ "src": "hda"
+ },
+ {
+ "name": "reverse",
+ "id": "9",
+ "src": "hda"
+ }
+ ]
+ },
+ {
+ "collection_type": "paired",
+ "src": "new_collection",
+ "name": "SET1-03",
+ "element_identifiers": [
+ {
+ "name": "forward",
+ "id": "10",
+ "src": "hda"
+ },
+ {
+ "name": "reverse",
+ "id": "11",
+ "src": "hda"
+ }
+ ]
+ },
+ {
+ "collection_type": "paired",
+ "src": "new_collection",
+ "name": "SET1-02",
+ "element_identifiers": [
+ {
+ "name": "forward",
+ "id": "12",
+ "src": "hda"
+ },
+ {
+ "name": "reverse",
+ "id": "13",
+ "src": "hda"
+ }
+ ]
+ },
+ {
+ "collection_type": "paired",
+ "src": "new_collection",
+ "name": "SET1-01",
+ "element_identifiers": [
+ {
+ "name": "forward",
+ "id": "14",
+ "src": "hda"
+ },
+ {
+ "name": "reverse",
+ "id": "15",
+ "src": "hda"
+ }
+ ]
+ }
+ ]
+};
+
+// ============================================================================
+ return {
+ _1 : datasets1,
+ _1requestJSON : datasets1CreateRequestJSON
+ };
+});
diff -r 7ef4ebeaa607b32151ca30c96ba774a3fc0d2274 -r 109da695364ceee5c27bf71b6a0bed918813fcda test/qunit/tests/graph.js
--- a/test/qunit/tests/graph.js
+++ b/test/qunit/tests/graph.js
@@ -1,11 +1,8 @@
-// This file isn't really testing anything useful yet, it is just testing
-// (or demonstrating) qunit+backbone interactions.
define([
"utils/graph",
"jquery",
"sinon-qunit"
], function( GRAPH, $, sinon ){
- console.debug( '' );
/*globals equal ok, test module expect deepEqual strictEqual */
"use strict";
diff -r 7ef4ebeaa607b32151ca30c96ba774a3fc0d2274 -r 109da695364ceee5c27bf71b6a0bed918813fcda test/qunit/tests/paired-collection-creator.html
--- /dev/null
+++ b/test/qunit/tests/paired-collection-creator.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<!-- Minimal outline test page for a requirejs+qunit testing setup,
+ test environment is bootstrapped in test-common.js -->
+<html>
+ <head>
+ <script data-main="../test-common" src="../scripts/libs/require.js"></script>
+ </head>
+ <body>
+ </body>
+</html>
diff -r 7ef4ebeaa607b32151ca30c96ba774a3fc0d2274 -r 109da695364ceee5c27bf71b6a0bed918813fcda test/qunit/tests/paired-collection-creator.js
--- /dev/null
+++ b/test/qunit/tests/paired-collection-creator.js
@@ -0,0 +1,79 @@
+define([
+ "mvc/collection/paired-collection-creator",
+ "test-data/paired-collection-creator.data",
+ "jquery",
+ "sinon-qunit",
+ "galaxy.base"
+], function(
+ PAIRED_COLLECTION_CREATOR,
+ // why am I yelling?
+ DATA,
+ $,
+ sinon
+){
+ /*globals equal test module expect deepEqual strictEqual throws ok */
+ "use strict";
+ var PCC = PAIRED_COLLECTION_CREATOR.PairedCollectionCreator;
+
+ module( "Galaxy client app tests" );
+
+ test( "Creator base/empty construction/initializiation defaults", function() {
+ var pcc = new PCC([]);
+ ok( pcc instanceof PCC );
+ ok( pcc.hasOwnProperty( 'options' ) && typeof pcc.options === 'object' );
+ deepEqual( pcc.options.filters, pcc.DEFAULT_FILTERS );
+ ok( pcc.options.automaticallyPair );
+ equal( pcc.options.matchPercentage, 1.0 );
+ equal( pcc.options.strategy, 'lcs' );
+ });
+
+ test( "Creator construction/initializiation with datasets", function() {
+ var pcc = new PCC({
+ datasets : DATA._1
+ });
+ //pcc.initialList.forEach( function( dataset, i ){
+ // console.log( i + ':\n' + JSON.stringify( dataset ) );
+ //});
+ // pcc maintains the original list - which, in this case, is already sorted
+ deepEqual( pcc.initialList, DATA._1 );
+ // datasets 1 has no ids, so the pcc will create them
+ ok( _.every( pcc.initialList, function( dataset ){
+ return dataset.id;
+ }));
+ // datasets 1 is very easy to auto pair
+ equal( pcc.unpaired.length, 0 );
+ equal( pcc.paired.length, pcc.initialList.length / 2 );
+ });
+
+ //TODO:
+ // filters: clearing, setting via popover, regex
+ // partition: maximize paired, maximize unpaired, split evenly
+ // pairing: manually pairing and unpairing
+ // misc: renaming pairs, removing file extensions
+
+ test( "Collection creation", function() {
+ var pcc = new PCC({
+ datasets : DATA._1,
+ historyId : 'fakeHistoryId'
+ }),
+ server = sinon.fakeServer.create();
+
+ var requestJSON;
+ server.respondWith( 'POST', '/api/histories/fakeHistoryId/contents/dataset_collections', function( request ){
+ requestJSON = JSON.parse( request.requestBody );
+ request.respond(
+ 200,
+ { "Content-Type": "application/json" },
+ JSON.stringify({
+ fakeResponse: 'yes'
+ })
+ );
+ });
+
+ console.debug( 'requestBody:', JSON.stringify( requestJSON, null, ' ' ) );
+ pcc.createList( 'Heres a collection' );
+ server.respond();
+ deepEqual( requestJSON, DATA._1requestJSON );
+ });
+
+});
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dannon: Merged in nsoranzo/galaxy-central (pull request #658)
by commits-noreply@bitbucket.org 10 Feb '15
by commits-noreply@bitbucket.org 10 Feb '15
10 Feb '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/7ef4ebeaa607/
Changeset: 7ef4ebeaa607
User: dannon
Date: 2015-02-10 18:14:21+00:00
Summary: Merged in nsoranzo/galaxy-central (pull request #658)
Don't abort restart if stop_daemon() failed.
Affected #: 1 file
diff -r 23df5eac97f7c05da1e06fb63a0385b1c416d535 -r 7ef4ebeaa607b32151ca30c96ba774a3fc0d2274 lib/galaxy/util/pastescript/serve.py
--- a/lib/galaxy/util/pastescript/serve.py
+++ b/lib/galaxy/util/pastescript/serve.py
@@ -559,11 +559,7 @@
if cmd == 'restart' or cmd == 'stop':
result = self.stop_daemon()
if result:
- if cmd == 'restart':
- print "Could not stop daemon; aborting"
- else:
- print "Could not stop daemon"
- return result
+ print "Could not stop daemon"
if cmd == 'stop':
return result
self.options.daemon = True
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e2aabc243d30/
Changeset: e2aabc243d30
User: nsoranzo
Date: 2015-02-03 11:51:07+00:00
Summary: Don't abort restart if stop_daemon() failed.
Affected #: 1 file
diff -r adcb595753b02cc9757a8f36a34898d4ea2233e7 -r e2aabc243d30093d086ced855eae2e6cbfc089cd lib/galaxy/util/pastescript/serve.py
--- a/lib/galaxy/util/pastescript/serve.py
+++ b/lib/galaxy/util/pastescript/serve.py
@@ -559,11 +559,7 @@
if cmd == 'restart' or cmd == 'stop':
result = self.stop_daemon()
if result:
- if cmd == 'restart':
- print "Could not stop daemon; aborting"
- else:
- print "Could not stop daemon"
- return result
+ print "Could not stop daemon"
if cmd == 'stop':
return result
self.options.daemon = True
https://bitbucket.org/galaxy/galaxy-central/commits/7ef4ebeaa607/
Changeset: 7ef4ebeaa607
User: dannon
Date: 2015-02-10 18:14:21+00:00
Summary: Merged in nsoranzo/galaxy-central (pull request #658)
Don't abort restart if stop_daemon() failed.
Affected #: 1 file
diff -r 23df5eac97f7c05da1e06fb63a0385b1c416d535 -r 7ef4ebeaa607b32151ca30c96ba774a3fc0d2274 lib/galaxy/util/pastescript/serve.py
--- a/lib/galaxy/util/pastescript/serve.py
+++ b/lib/galaxy/util/pastescript/serve.py
@@ -559,11 +559,7 @@
if cmd == 'restart' or cmd == 'stop':
result = self.stop_daemon()
if result:
- if cmd == 'restart':
- print "Could not stop daemon; aborting"
- else:
- print "Could not stop daemon"
- return result
+ print "Could not stop daemon"
if cmd == 'stop':
return result
self.options.daemon = True
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/23ca47b22816/
Changeset: 23ca47b22816
Branch: fix-multipart-upload-in-swift-backend
User: dannon
Date: 2015-02-10 14:55:53+00:00
Summary: Branch prune.
Affected #: 0 files
https://bitbucket.org/galaxy/galaxy-central/commits/c42cf5c21c63/
Changeset: c42cf5c21c63
Branch: tool_shed_test_fix-DB_initialization
User: dannon
Date: 2015-02-10 14:56:16+00:00
Summary: Branch prune.
Affected #: 0 files
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
4 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/bbdf4a2c3f56/
Changeset: bbdf4a2c3f56
User: dannon
Date: 2015-02-09 22:37:16+00:00
Summary: Update objectstore sample to supply better defaults (and not host/port, which are unnecessary for s3).
Affected #: 1 file
diff -r 35a718a57a32ec73c9e12bbb01bc47cc3d48042e -r bbdf4a2c3f56e1e2fe6142803e170b8868883c33 config/object_store_conf.xml.sample
--- a/config/object_store_conf.xml.sample
+++ b/config/object_store_conf.xml.sample
@@ -24,9 +24,8 @@
<object_store type="s3"><auth access_key="...." secret_key="....." />
- <bucket name="unique_bucket_name" use_reduced_redundancy="False" />
- <connection host="" port="" is_secure="" conn_path="" />
- <cache path="database/files/" size="100" />
+ <bucket name="unique_bucket_name_all_lowercase" use_reduced_redundancy="False" />
+ <cache path="database/files/" size="1000" /></object_store>
-->
https://bitbucket.org/galaxy/galaxy-central/commits/cf105e43d141/
Changeset: cf105e43d141
User: dannon
Date: 2015-02-10 14:48:46+00:00
Summary: Actually use reduced redundancy only when specified.
Affected #: 1 file
diff -r bbdf4a2c3f56e1e2fe6142803e170b8868883c33 -r cf105e43d141b258dbf200d49bd3cce5f4d7dddc lib/galaxy/objectstore/s3.py
--- a/lib/galaxy/objectstore/s3.py
+++ b/lib/galaxy/objectstore/s3.py
@@ -13,7 +13,7 @@
from datetime import datetime
from galaxy.exceptions import ObjectNotFound
-from galaxy.util import umask_fix_perms
+from galaxy.util import umask_fix_perms, string_as_bool
from galaxy.util.directory_hash import directory_hash_id
from galaxy.util.sleeper import Sleeper
from .s3_multipart_upload import multipart_upload
@@ -76,7 +76,7 @@
self.secret_key = a_xml.get('secret_key')
b_xml = config_xml.findall('bucket')[0]
self.bucket = b_xml.get('name')
- self.use_rr = b_xml.get('use_reduced_redundancy', False)
+ self.use_rr = string_as_bool(b_xml.get('use_reduced_redundancy', "False"))
cn_xml = config_xml.findall('connection')
if not cn_xml:
cn_xml = {}
https://bitbucket.org/galaxy/galaxy-central/commits/487461afaba5/
Changeset: 487461afaba5
User: dannon
Date: 2015-02-10 14:51:33+00:00
Summary: Merge.
Affected #: 10 files
diff -r cf105e43d141b258dbf200d49bd3cce5f4d7dddc -r 487461afaba5cc7f0f6bb38397be3773cf46ce45 client/galaxy/scripts/mvc/collection/paired-collection-creator.js
--- a/client/galaxy/scripts/mvc/collection/paired-collection-creator.js
+++ b/client/galaxy/scripts/mvc/collection/paired-collection-creator.js
@@ -150,6 +150,9 @@
/** fn to call when the collection is created (scoped to this) */
this.oncreate = attributes.oncreate;
+ /** fn to call when the cancel button is clicked (scoped to this) - if falsy, no btn is displayed */
+ this.autoscrollDist = attributes.autoscrollDist || 24;
+
/** is the unpaired panel shown? */
this.unpairedPanelHidden = false;
/** is the paired panel shown? */
@@ -873,7 +876,7 @@
filterChoice( '_1', '_2' ),
filterChoice( '_R1', '_R2' ),
'</div>'
- ].join(''), {}));
+ ].join(''))({}));
return this.$( selector ).popover({
container : '.collection-creator',
@@ -1025,7 +1028,6 @@
/** show an alert on the top of the interface containing message (alertClass is bootstrap's alert-*)*/
_showAlert : function( message, alertClass ){
- console.debug( 'alert:', message, alertClass );
alertClass = alertClass || 'alert-danger';
this.$( '.main-help' ).hide();
this.$( '.header .alert' ).attr( 'class', 'alert alert-dismissable' ).addClass( alertClass ).show()
@@ -1305,8 +1307,10 @@
/** rename a pair when the pair name is clicked */
_clickPairName : function( ev ){
ev.stopPropagation();
- var $control = $( ev.currentTarget ),
- pair = this.paired[ $control.parent().parent().index() / 2 ],
+ 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 );
if( response ){
pair.name = response;
@@ -1314,7 +1318,7 @@
// when adding/removing extensions
//TODO: kinda hacky
pair.customizedName = true;
- $control.text( pair.name );
+ $name.text( pair.name );
}
},
@@ -1322,7 +1326,7 @@
_clickUnpair : function( ev ){
//if( !ev.currentTarget ){ return true; }
//TODO: this is a hack bc each paired rev now has two elems (dataset, button)
- var pairIndex = Math.floor( $( ev.currentTarget ).index() / 2 );
+ var pairIndex = Math.floor( $( ev.currentTarget ).index( '.unpair-btn' ) );
//this.debug( 'pair:', pairIndex );
//TODO: animate
this._unpair( this.paired[ pairIndex ] );
@@ -1340,27 +1344,41 @@
//console.debug( '_dragoverPairedColumns:', ev );
ev.preventDefault();
- var $list = this.$( '.paired-columns .column-datasets' ),
- offset = $list.offset();
+ var $list = this.$( '.paired-columns .column-datasets' );
+ this._checkForAutoscroll( $list, ev.originalEvent.clientY );
//console.debug( ev.originalEvent.clientX, ev.originalEvent.clientY );
var $nearest = this._getNearestPairedDatasetLi( ev.originalEvent.clientY );
- //console.debug( ev.originalEvent.clientX - offset.left, ev.originalEvent.clientY - offset.top );
$( '.paired-drop-placeholder' ).remove();
- var $placeholder = $( '<div class="paired-drop-placeholder"></div>')
+ var $placeholder = $( '<div class="paired-drop-placeholder"></div>' );
if( !$nearest.size() ){
$list.append( $placeholder );
} else {
$nearest.before( $placeholder );
}
},
+
+ /** 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;
+ //console.debug( '_checkForAutoscroll:', scrollTop, upperDist, lowerDist );
+ if( upperDist >= 0 && upperDist < this.autoscrollDist ){
+ $element.scrollTop( scrollTop - AUTOSCROLL_SPEED );
+ } else if( lowerDist >= 0 && lowerDist < this.autoscrollDist ){
+ $element.scrollTop( scrollTop + AUTOSCROLL_SPEED );
+ }
+ },
+
/** get the nearest *previous* paired dataset PairView based on the mouse's Y coordinate.
* 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();
-//TODO: better way?
for( var i=0; i<lis.length; i++ ){
var $li = $( lis[i] ),
top = $li.offset().top,
diff -r cf105e43d141b258dbf200d49bd3cce5f4d7dddc -r 487461afaba5cc7f0f6bb38397be3773cf46ce45 client/galaxy/scripts/utils/LazyDataLoader.js
--- a/client/galaxy/scripts/utils/LazyDataLoader.js
+++ /dev/null
@@ -1,228 +0,0 @@
-//==============================================================================
-/*
-TODO:
- ?? superclass dataloader, subclass lazydataloader??
-
-*/
-//==============================================================================
-/**
- * Object to progressively load JSON data from a REST url, delaying some time between loading chunks
- *
- * Will load size amount of data every delay ms, starting at start and ending at total.
- *
- * NOTE: Data from ajax loading is aggregated in a list, with one element for each ajax response.
- * It's up to the calling code to combine the results in a meaningful, correct way.
- *
- * example:
- * var loader = new scatterplot.LazyDataLoader({
- * //logger : console,
- * url : ( apiDatasetsURL + '/' + hda.id + '?data_type=raw_data'
- * + '&columns=[10,14]' ),
- * total : hda.metadata_data_lines,
- * size : 500,
- *
- * initialize : function( config ){
- * // ... do some stuff
- * },
- *
- * buildUrl : function( start, size ){
- * // change the formation of start, size in query string
- * return loader.url + '&' + jQuery.param({
- * start_val: start,
- * max_vals: size
- * });
- * },
- * });
- *
- * // you can use events
- * $( loader ).bind( 'error', function( event, xhr, status, error ){
- * alert( loader + ' ERROR:' + status + '\n' + error );
- * // bail out...
- * });
- * $( loader ).bind( 'loaded.new', function( event, response ){
- * console.info( 'new data available:', event, response );
- * // ... do stuff with new data
- * });
- * $( loader ).bind( 'complete', function( event, allDataArray, total ){
- * console.info( 'final load complete:', event, allDataArray, total );
- * // ... do stuff with all data
- * });
- *
- * // ...or use a callback called when all data is loaded
- * loader.load( function( dataArray ){ console.debug( 'FINISHED!', x, y, z ); } );
- */
-function LazyDataLoader( config ){
- // for now assume:
- // get, async, and params sent via url query string
- // we want json
- // we know the size of the data on the server beforehand
- var loader = this,
- // events to trigger when new or all data has been loaded
- // new batches of data (including last). Will be sent: the ajax response data, start value, and size
- LOADED_NEW_EVENT = 'loaded.new',
- // all data has been loaded: the final loader's data array and the total
- LOADED_ALL_EVENT = 'complete';
- // error from ajax
- ERROR_EVENT = 'error';
-
- jQuery.extend( loader, LoggableMixin );
- jQuery.extend( loader, {
-
- //NOTE: the next two need to be sent in config (required)
- // total size of data on server
- total : undefined,
- // url of service to get the data
- url : undefined,
-
- // holds the interval id for the current load delay
- currentIntervalId : undefined,
-
- // each load call will add an element to this array
- // it's the responsibility of the code using this to combine them properly
- data : [],
- // ms btwn recursive loads
- delay : 4000,
- // starting line, element, whatever
- start : 0,
- // size to fetch per load
- size : 4000,
-
- // loader init func: extends loader with config and calls config.init if there
- //@param {object} config : object containing variables to override (or additional)
- initialize : function( config ){
- jQuery.extend( loader, config );
-
- // call the custom initialize function if any
- // only dangerous if the user tries LazyDataLoader.prototype.init
- if( config.hasOwnProperty( 'initialize' ) ){
- config.initialize.call( loader, config );
- }
- this.log( this + ' initialized:', loader );
- },
-
- // returns query string formatted start and size (for the next fetch) appended to the loader.url
- //OVERRIDE: to change how params are passed, param names, etc.
- //@param {int} start : the line/row/datum indicating where in the dataset the next load begins
- //@param {int} size : the number of lines/rows/data to get on the next load
- buildUrl : function( start, size ){
- // currently VERY SPECIFIC to using data_providers.py start_val, max_vals params
- return this.url + '&' + jQuery.param({
- start_val: start,
- max_vals: size
- });
- },
-
- //OVERRIDE: to handle ajax errors differently
- ajaxErrorFn : function( xhr, status, error ){
- console.error( 'ERROR fetching data:', error );
- },
-
- // converters passed to the jQuery ajax call for data type parsing
- //OVERRIDE: to provide custom parsing
- converters : {
- '* text' : window.String,
- 'text html' : true,
- 'text xml' : jQuery.parseXML,
- 'text json' : jQuery.parseJSON
- },
-
- // interface to begin load (and first recursive call)
- //@param {Function} callback : function to execute when all data is loaded. callback is passed loader.data
- load : function( callback ){
- this.log( this + '.load' );
-
- // ensure necessary stuff
- if( !loader.url ){ throw( loader + ' requires a url' ); }
-
- if( this.total === null ){
- this.log( '\t total is null (will load all)' );
- } else {
- this.log( '\t total:', this.total );
- }
- //if( !loader.total ){ throw( loader + ' requires a total (total size of the data)' ); }
-
- //FIRST RECURSION: start
- var startingSize = loader.size;
- if( ( loader.total !== null ) && ( loader.total < loader.size ) ){
- startingSize = loader.total;
- }
- loader.log( loader + '\t beginning recursion' );
- loadHelper( loader.start, startingSize );
-
- //FIRST, SUBSEQUENT RECURSION function
- function loadHelper( start, size ){
- loader.log( loader + '.loadHelper, start:', start, 'size:', size );
- var url = loader.buildUrl( start, size );
- loader.log( '\t url:', url );
-
- jQuery.ajax({
- url : loader.buildUrl( start, size ),
- converters : loader.converters,
- dataType : 'json',
-
- error : function( xhr, status, error ){
- loader.log( '\t ajax error, status:', status, 'error:', error );
- if( loader.currentIntervalId ){
- clearInterval( loader.currentIntervalId );
- }
- $( loader ).trigger( ERROR_EVENT, [ status, error ] );
- loader.ajaxErrorFn( xhr, status, error );
- },
-
- success : function( response ){
- loader.log( '\t ajax success, response:', response, 'next:', next, 'remainder:', remainder );
-
- if( response !== null ){
- // store the response as is in a new element
- //TODO:?? store start, size as well?
- loader.data.push( response );
-
- //TODO: these might not be the best way to split this up
- // fire the first load event (if this is the first batch) AND partial
- $( loader ).trigger( LOADED_NEW_EVENT, [ response, start, size ] );
-
- //RECURSION:
- var next = start + size,
- remainder = loader.size;
-
- if( loader.total !== null ){
- remainder = Math.min( loader.total - next, loader.size );
- }
- loader.log( '\t next recursion, start:', next, 'size:', remainder );
-
- // if we haven't gotten everything yet, so set up for next recursive call and set the timer
- if( loader.total === null || remainder > 0 ){
- loader.currentIntervalId = setTimeout(
- function(){ loadHelper( next, remainder ); },
- loader.delay
- );
- loader.log( '\t currentIntervalId:', loader.currentIntervalId );
-
- // otherwise (base-case), don't do anything
- } else {
- loadFinished();
- }
-
- } else { //response === null --> base-case, server sez nuthin left
- loadFinished();
- }
- }
- });
- }
-
- //HANDLE BASE-CASE, LAST RECURSION
- function loadFinished(){
- loader.log( loader + '.loadHelper, has finished:', loader.data );
- $( loader ).trigger( LOADED_ALL_EVENT, [ loader.data, loader.total ] );
- if( callback ){ callback( loader.data ); }
- }
- },
-
- toString : function(){ return 'LazyDataLoader'; }
- });
-
- loader.initialize( config );
- return loader;
-}
-
-//==============================================================================
diff -r cf105e43d141b258dbf200d49bd3cce5f4d7dddc -r 487461afaba5cc7f0f6bb38397be3773cf46ce45 lib/galaxy/objectstore/s3.py
--- a/lib/galaxy/objectstore/s3.py
+++ b/lib/galaxy/objectstore/s3.py
@@ -14,6 +14,7 @@
from galaxy.exceptions import ObjectNotFound
from galaxy.util import umask_fix_perms, string_as_bool
+from galaxy.util import string_as_bool
from galaxy.util.directory_hash import directory_hash_id
from galaxy.util.sleeper import Sleeper
from .s3_multipart_upload import multipart_upload
@@ -77,6 +78,7 @@
b_xml = config_xml.findall('bucket')[0]
self.bucket = b_xml.get('name')
self.use_rr = string_as_bool(b_xml.get('use_reduced_redundancy', "False"))
+ self.max_chunk_size = int(b_xml.get('max_chunk_size', 250))
cn_xml = config_xml.findall('connection')
if not cn_xml:
cn_xml = {}
@@ -84,11 +86,24 @@
cn_xml = cn_xml[0]
self.host = cn_xml.get('host', None)
self.port = int(cn_xml.get('port', 6000))
- self.is_secure = cn_xml.get('is_secure', True)
+ self.multipart = string_as_bool(cn_xml.get('multipart', 'True'))
+ self.is_secure = string_as_bool(cn_xml.get('is_secure', 'True'))
self.conn_path = cn_xml.get('conn_path', '/')
c_xml = config_xml.findall('cache')[0]
self.cache_size = float(c_xml.get('size', -1))
self.cache_path = c_xml.get('path')
+
+ # for multipart upload
+ self.s3server = {'access_key': self.access_key,
+ 'secret_key': self.secret_key,
+ 'is_secure': self.is_secure,
+ 'max_chunk_size': self.max_chunk_size,
+ 'host': self.host,
+ 'port': self.port,
+ 'use_rr': self.use_rr,
+ 'conn_path': self.conn_path}
+
+
except Exception:
# Toss it back up after logging, we can't continue loading at this point.
log.exception("Malformed ObjectStore Configuration XML -- unable to continue")
@@ -328,14 +343,14 @@
start_time = datetime.now()
log.debug("Pushing cache file '%s' of size %s bytes to key '%s'" % (source_file, os.path.getsize(source_file), rel_path))
mb_size = os.path.getsize(source_file) / 1e6
- if mb_size < 10 or type(self) == SwiftObjectStore:
+ if mb_size < 10 or (not self.multipart):
self.transfer_progress = 0 # Reset transfer progress counter
key.set_contents_from_filename(source_file,
reduced_redundancy=self.use_rr,
cb=self._transfer_cb,
num_cb=10)
else:
- multipart_upload(self.bucket, key.name, source_file, mb_size, self.access_key, self.secret_key, use_rr=self.use_rr)
+ multipart_upload(self.s3server, self.bucket, key.name, source_file, mb_size)
end_time = datetime.now()
log.debug("Pushed cache file '%s' to key '%s' (%s bytes transfered in %s sec)" % (source_file, rel_path, os.path.getsize(source_file), end_time - start_time))
return True
diff -r cf105e43d141b258dbf200d49bd3cce5f4d7dddc -r 487461afaba5cc7f0f6bb38397be3773cf46ce45 lib/galaxy/objectstore/s3_multipart_upload.py
--- a/lib/galaxy/objectstore/s3_multipart_upload.py
+++ b/lib/galaxy/objectstore/s3_multipart_upload.py
@@ -34,13 +34,23 @@
return wrapper
-def mp_from_ids(mp_id, mp_keyname, mp_bucketname, aws_access_key_id, aws_secret_access_key):
+def mp_from_ids(s3server, mp_id, mp_keyname, mp_bucketname):
"""Get the multipart upload from the bucket and multipart IDs.
This allows us to reconstitute a connection to the upload
from within multiprocessing functions.
"""
- conn = S3Connection(aws_access_key_id, aws_secret_access_key)
+ if s3server['host']:
+ conn = boto.connect_s3(aws_access_key_id=s3server['access_key'],
+ aws_secret_access_key=s3server['secret_key'],
+ is_secure=s3server['is_secure'],
+ host=s3server['host'],
+ port=s3server['port'],
+ calling_format=boto.s3.connection.OrdinaryCallingFormat(),
+ path=s3server['conn_path'])
+ else:
+ conn = S3Connection(s3server['access_key'], s3server['secret_key'])
+
bucket = conn.lookup(mp_bucketname)
mp = boto.s3.multipart.MultiPartUpload(bucket)
mp.key_name = mp_keyname
@@ -49,33 +59,36 @@
@map_wrap
-def transfer_part(mp_id, mp_keyname, mp_bucketname, i, part, aws_access_key_id, aws_secret_access_key):
+def transfer_part(s3server, mp_id, mp_keyname, mp_bucketname, i, part):
"""Transfer a part of a multipart upload. Designed to be run in parallel.
"""
- mp = mp_from_ids(mp_id, mp_keyname, mp_bucketname, aws_access_key_id, aws_secret_access_key)
+ mp = mp_from_ids(s3server, mp_id, mp_keyname, mp_bucketname)
with open(part) as t_handle:
mp.upload_part_from_file(t_handle, i + 1)
os.remove(part)
-def multipart_upload(bucket, s3_key_name, tarball, mb_size, aws_access_key_id, aws_secret_access_key, use_rr=True):
+def multipart_upload(s3server, bucket, s3_key_name, tarball, mb_size):
"""Upload large files using Amazon's multipart upload functionality.
"""
cores = multiprocessing.cpu_count()
def split_file(in_file, mb_size, split_num=5):
prefix = os.path.join(os.path.dirname(in_file),
- "%sS3PART" % (os.path.basename(s3_key_name)))
- # Split chunks so they are 5MB < chunk < 250MB
- split_size = int(max(min(mb_size / (split_num * 2.0), 250), 5))
+ "%sS3PART" % (os.path.basename(s3_key_name)))
+ max_chunk = s3server['max_chunk_size']
+ # Split chunks so they are 5MB < chunk < 250MB(max_chunk_size)
+ split_size = int(max(min(mb_size / (split_num * 2.0), max_chunk), 5))
if not os.path.exists("%saa" % prefix):
cl = ["split", "-b%sm" % split_size, in_file, prefix]
subprocess.check_call(cl)
return sorted(glob.glob("%s*" % prefix))
- mp = bucket.initiate_multipart_upload(s3_key_name, reduced_redundancy=use_rr)
+ mp = bucket.initiate_multipart_upload(s3_key_name,
+ reduced_redundancy=s3server['use_rr'])
+
with multimap(cores) as pmap:
- for _ in pmap(transfer_part, ((mp.id, mp.key_name, mp.bucket_name, i, part, aws_access_key_id, aws_secret_access_key)
+ for _ in pmap(transfer_part, ((s3server, mp.id, mp.key_name, mp.bucket_name, i, part)
for (i, part) in
enumerate(split_file(tarball, mb_size, cores)))):
pass
diff -r cf105e43d141b258dbf200d49bd3cce5f4d7dddc -r 487461afaba5cc7f0f6bb38397be3773cf46ce45 static/scripts/mvc/collection/paired-collection-creator.js
--- a/static/scripts/mvc/collection/paired-collection-creator.js
+++ b/static/scripts/mvc/collection/paired-collection-creator.js
@@ -150,6 +150,9 @@
/** fn to call when the collection is created (scoped to this) */
this.oncreate = attributes.oncreate;
+ /** fn to call when the cancel button is clicked (scoped to this) - if falsy, no btn is displayed */
+ this.autoscrollDist = attributes.autoscrollDist || 24;
+
/** is the unpaired panel shown? */
this.unpairedPanelHidden = false;
/** is the paired panel shown? */
@@ -873,7 +876,7 @@
filterChoice( '_1', '_2' ),
filterChoice( '_R1', '_R2' ),
'</div>'
- ].join(''), {}));
+ ].join(''))({}));
return this.$( selector ).popover({
container : '.collection-creator',
@@ -1025,7 +1028,6 @@
/** show an alert on the top of the interface containing message (alertClass is bootstrap's alert-*)*/
_showAlert : function( message, alertClass ){
- console.debug( 'alert:', message, alertClass );
alertClass = alertClass || 'alert-danger';
this.$( '.main-help' ).hide();
this.$( '.header .alert' ).attr( 'class', 'alert alert-dismissable' ).addClass( alertClass ).show()
@@ -1305,8 +1307,10 @@
/** rename a pair when the pair name is clicked */
_clickPairName : function( ev ){
ev.stopPropagation();
- var $control = $( ev.currentTarget ),
- pair = this.paired[ $control.parent().parent().index() / 2 ],
+ 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 );
if( response ){
pair.name = response;
@@ -1314,7 +1318,7 @@
// when adding/removing extensions
//TODO: kinda hacky
pair.customizedName = true;
- $control.text( pair.name );
+ $name.text( pair.name );
}
},
@@ -1322,7 +1326,7 @@
_clickUnpair : function( ev ){
//if( !ev.currentTarget ){ return true; }
//TODO: this is a hack bc each paired rev now has two elems (dataset, button)
- var pairIndex = Math.floor( $( ev.currentTarget ).index() / 2 );
+ var pairIndex = Math.floor( $( ev.currentTarget ).index( '.unpair-btn' ) );
//this.debug( 'pair:', pairIndex );
//TODO: animate
this._unpair( this.paired[ pairIndex ] );
@@ -1340,27 +1344,41 @@
//console.debug( '_dragoverPairedColumns:', ev );
ev.preventDefault();
- var $list = this.$( '.paired-columns .column-datasets' ),
- offset = $list.offset();
+ var $list = this.$( '.paired-columns .column-datasets' );
+ this._checkForAutoscroll( $list, ev.originalEvent.clientY );
//console.debug( ev.originalEvent.clientX, ev.originalEvent.clientY );
var $nearest = this._getNearestPairedDatasetLi( ev.originalEvent.clientY );
- //console.debug( ev.originalEvent.clientX - offset.left, ev.originalEvent.clientY - offset.top );
$( '.paired-drop-placeholder' ).remove();
- var $placeholder = $( '<div class="paired-drop-placeholder"></div>')
+ var $placeholder = $( '<div class="paired-drop-placeholder"></div>' );
if( !$nearest.size() ){
$list.append( $placeholder );
} else {
$nearest.before( $placeholder );
}
},
+
+ /** 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;
+ //console.debug( '_checkForAutoscroll:', scrollTop, upperDist, lowerDist );
+ if( upperDist >= 0 && upperDist < this.autoscrollDist ){
+ $element.scrollTop( scrollTop - AUTOSCROLL_SPEED );
+ } else if( lowerDist >= 0 && lowerDist < this.autoscrollDist ){
+ $element.scrollTop( scrollTop + AUTOSCROLL_SPEED );
+ }
+ },
+
/** get the nearest *previous* paired dataset PairView based on the mouse's Y coordinate.
* 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();
-//TODO: better way?
for( var i=0; i<lis.length; i++ ){
var $li = $( lis[i] ),
top = $li.offset().top,
diff -r cf105e43d141b258dbf200d49bd3cce5f4d7dddc -r 487461afaba5cc7f0f6bb38397be3773cf46ce45 static/scripts/packed/mvc/collection/paired-collection-creator.js
--- a/static/scripts/packed/mvc/collection/paired-collection-creator.js
+++ b/static/scripts/packed/mvc/collection/paired-collection-creator.js
@@ -1,1 +1,1 @@
-define(["utils/levenshtein","mvc/base-mvc","utils/localization"],function(g,a,d){var f=Backbone.View.extend(a.LoggableMixin).extend({tagName:"li",className:"dataset paired",initialize:function(h){this.pair=h.pair||{}},template:_.template(['<span class="forward-dataset-name flex-column"><%= pair.forward.name %></span>','<span class="pair-name-column flex-column">','<span class="pair-name"><%= pair.name %></span>',"</span>",'<span class="reverse-dataset-name flex-column"><%= pair.reverse.name %></span>'].join("")),render:function(){this.$el.attr("draggable",true).data("pair",this.pair).html(this.template({pair:this.pair})).addClass("flex-column-container");return this},events:{dragstart:"_dragstart",dragend:"_dragend",dragover:"_sendToParent",drop:"_sendToParent"},_dragstart:function(h){h.currentTarget.style.opacity="0.4";if(h.originalEvent){h=h.originalEvent}h.dataTransfer.effectAllowed="move";h.dataTransfer.setData("text/plain",JSON.stringify(this.pair));this.$el.parent().trigger("pair.dragstart",[this])},_dragend:function(h){h.currentTarget.style.opacity="1.0";this.$el.parent().trigger("pair.dragend",[this])},_sendToParent:function(h){this.$el.parent().trigger(h)},toString:function(){return"PairView("+this.pair.name+")"}});var e=Backbone.View.extend(a.LoggableMixin).extend({className:"collection-creator flex-row-container",initialize:function(h){h=_.defaults(h,{datasets:[],filters:this.DEFAULT_FILTERS,automaticallyPair:true,matchPercentage:1,strategy:"lcs"});this.initialList=h.datasets;this.historyId=h.historyId;this.filters=this.commonFilters[h.filters]||this.commonFilters[this.DEFAULT_FILTERS];if(_.isArray(h.filters)){this.filters=h.filters}this.automaticallyPair=h.automaticallyPair;this.matchPercentage=h.matchPercentage;this.strategy=this.strategies[h.strategy]||this.strategies[this.DEFAULT_STRATEGY];if(_.isFunction(h.strategy)){this.strategy=h.strategy}this.removeExtensions=true;this.oncancel=h.oncancel;this.oncreate=h.oncreate;this.unpairedPanelHidden=false;this.pairedPanelHidden=false;this.$dragging=null;this._setUpBehaviors();this._dataSetUp()},commonFilters:{none:["",""],illumina:["_1","_2"]},DEFAULT_FILTERS:"illumina",strategies:{lcs:"autoPairLCSs",levenshtein:"autoPairLevenshtein"},DEFAULT_STRATEGY:"lcs",_dataSetUp:function(){this.paired=[];this.unpaired=[];this.selectedIds=[];this._sortInitialList();this._ensureIds();this.unpaired=this.initialList.slice(0);if(this.automaticallyPair){this.autoPair();this.once("rendered:initial",function(){this.trigger("autopair")})}},_sortInitialList:function(){this._sortDatasetList(this.initialList)},_sortDatasetList:function(h){h.sort(function(j,i){return naturalSort(j.name,i.name)});return h},_ensureIds:function(){this.initialList.forEach(function(h){if(!h.hasOwnProperty("id")){h.id=_.uniqueId()}});return this.initialList},_splitByFilters:function(j){var i=[],h=[];this.unpaired.forEach(function(k){if(this._filterFwdFn(k)){i.push(k)}if(this._filterRevFn(k)){h.push(k)}}.bind(this));return[i,h]},_filterFwdFn:function(i){var h=new RegExp(this.filters[0]);return h.test(i.name)},_filterRevFn:function(i){var h=new RegExp(this.filters[1]);return h.test(i.name)},_addToUnpaired:function(i){var h=function(j,l){if(j===l){return j}var k=Math.floor((l-j)/2)+j,m=naturalSort(i.name,this.unpaired[k].name);if(m<0){return h(j,k)}else{if(m>0){return h(k+1,l)}}while(this.unpaired[k]&&this.unpaired[k].name===i.name){k++}return k}.bind(this);this.unpaired.splice(h(0,this.unpaired.length),0,i)},autoPair:function(i){i=i||this.strategy;var h=this.simpleAutoPair();h=h.concat(this[i].call(this));return h},simpleAutoPair:function(){var o=0,m,s=this._splitByFilters(),h=s[0],r=s[1],q,u,k=false,t=[];while(o<h.length){var n=h[o];q=n.name.replace(this.filters[0],"");k=false;for(m=0;m<r.length;m++){var p=r[m];u=p.name.replace(this.filters[1],"");if(n!==p&&q===u){k=true;var l=this._pair(h.splice(o,1)[0],r.splice(m,1)[0],{silent:true});t.push(l);break}}if(!k){o+=1}}return t},autoPairLevenshtein:function(){var p=0,n,u=this._splitByFilters(),h=u[0],s=u[1],r,x,k,t,l,v=[];while(p<h.length){var o=h[p];r=o.name.replace(this.filters[0],"");l=Number.MAX_VALUE;for(n=0;n<s.length;n++){var q=s[n];x=q.name.replace(this.filters[1],"");if(o!==q){if(r===x){t=n;l=0;break}k=levenshteinDistance(r,x);if(k<l){t=n;l=k}}}var w=1-(l/(Math.max(r.length,x.length)));if(w>=this.matchPercentage){var m=this._pair(h.splice(p,1)[0],s.splice(t,1)[0],{silent:true});v.push(m);if(h.length<=0||s.length<=0){return v}}else{p+=1}}return v},autoPairLCSs:function(){var n=0,l,u=this._splitByFilters(),h=u[0],s=u[1],r,y,x,t,p,v=[];if(!h.length||!s.length){return v}while(n<h.length){var m=h[n];r=m.name.replace(this.filters[0],"");p=0;for(l=0;l<s.length;l++){var q=s[l];y=q.name.replace(this.filters[1],"");if(m!==q){if(r===y){t=l;p=r.length;break}var o=this._naiveStartingAndEndingLCS(r,y);x=o.length;if(x>p){t=l;p=x}}}var w=p/(Math.min(r.length,y.length));if(w>=this.matchPercentage){var k=this._pair(h.splice(n,1)[0],s.splice(t,1)[0],{silent:true});v.push(k);if(h.length<=0||s.length<=0){return v}}else{n+=1}}return v},_naiveStartingAndEndingLCS:function(m,k){var n="",o="",l=0,h=0;while(l<m.length&&l<k.length){if(m[l]!==k[l]){break}n+=m[l];l+=1}if(l===m.length){return m}if(l===k.length){return k}l=(m.length-1);h=(k.length-1);while(l>=0&&h>=0){if(m[l]!==k[h]){break}o=[m[l],o].join("");l-=1;h-=1}return n+o},_pair:function(j,h,i){i=i||{};var k=this._createPair(j,h,i.name);this.paired.push(k);this.unpaired=_.without(this.unpaired,j,h);if(!i.silent){this.trigger("pair:new",k)}return k},_createPair:function(j,h,i){if(!(j&&h)||(j===h)){throw new Error("Bad pairing: "+[JSON.stringify(j),JSON.stringify(h)])}i=i||this._guessNameForPair(j,h);return{forward:j,name:i,reverse:h}},_guessNameForPair:function(j,h,k){k=(k!==undefined)?(k):(this.removeExtensions);var i=this._naiveStartingAndEndingLCS(j.name.replace(this.filters[0],""),h.name.replace(this.filters[1],""));if(k){var l=i.lastIndexOf(".");if(l>0){i=i.slice(0,l)}}return i||(j.name+" & "+h.name)},_unpair:function(i,h){h=h||{};if(!i){throw new Error("Bad pair: "+JSON.stringify(i))}this.paired=_.without(this.paired,i);this._addToUnpaired(i.forward);this._addToUnpaired(i.reverse);if(!h.silent){this.trigger("pair:unpair",[i])}return i},unpairAll:function(){var h=[];while(this.paired.length){h.push(this._unpair(this.paired[0],{silent:true}))}this.trigger("pair:unpair",h)},_pairToJSON:function(h){return{collection_type:"paired",src:"new_collection",name:h.name,element_identifiers:[{name:"forward",id:h.forward.id,src:"hda"},{name:"reverse",id:h.reverse.id,src:"hda"}]}},createList:function(){var j=this,i;if(j.historyId){i="/api/histories/"+this.historyId+"/contents/dataset_collections"}var h={type:"dataset_collection",collection_type:"list:paired",name:_.escape(j.$(".collection-name").val()),element_identifiers:j.paired.map(function(k){return j._pairToJSON(k)})};return jQuery.ajax(i,{type:"POST",contentType:"application/json",dataType:"json",data:JSON.stringify(h)}).fail(function(m,k,l){j._ajaxErrHandler(m,k,l)}).done(function(k,l,m){j.trigger("collection:created",k,l,m);if(typeof j.oncreate==="function"){j.oncreate.call(this,k,l,m)}})},_ajaxErrHandler:function(k,h,j){this.error(k,h,j);var i=d("An error occurred while creating this collection");if(k){if(k.readyState===0&&k.status===0){i+=": "+d("Galaxy could not be reached and may be updating.")+d(" Try again in a few minutes.")}else{if(k.responseJSON){i+="<br /><pre>"+JSON.stringify(k.responseJSON)+"</pre>"}else{i+=": "+j}}}creator._showAlert(i,"alert-danger")},render:function(h,i){this.$el.empty().html(e.templates.main());this._renderHeader(h);this._renderMiddle(h);this._renderFooter(h);this._addPluginComponents();this.trigger("rendered",this);return this},_renderHeader:function(i,j){var h=this.$(".header").empty().html(e.templates.header()).find(".help-content").prepend($(e.templates.helpContent()));this._renderFilters();return h},_renderFilters:function(){return this.$(".forward-column .column-header input").val(this.filters[0]).add(this.$(".reverse-column .column-header input").val(this.filters[1]))},_renderMiddle:function(i,j){var h=this.$(".middle").empty().html(e.templates.middle());if(this.unpairedPanelHidden){this.$(".unpaired-columns").hide()}else{if(this.pairedPanelHidden){this.$(".paired-columns").hide()}}this._renderUnpaired();this._renderPaired();return h},_renderUnpaired:function(m,n){var k=this,l,i,h=[],j=this._splitByFilters();this.$(".forward-column .title").text([j[0].length,d("unpaired forward")].join(" "));this.$(".forward-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[0].length));this.$(".reverse-column .title").text([j[1].length,d("unpaired reverse")].join(" "));this.$(".reverse-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[1].length));this.$(".unpaired-columns .column-datasets").empty();this.$(".autopair-link").toggle(this.unpaired.length!==0);if(this.unpaired.length===0){this._renderUnpairedEmpty();return}i=j[1].map(function(p,o){if((j[0][o]!==undefined)&&(j[0][o]!==p)){h.push(k._renderPairButton())}return k._renderUnpairedDataset(p)});l=j[0].map(function(o){return k._renderUnpairedDataset(o)});if(!l.length&&!i.length){this._renderUnpairedNotShown();return}this.$(".unpaired-columns .forward-column .column-datasets").append(l).add(this.$(".unpaired-columns .paired-column .column-datasets").append(h)).add(this.$(".unpaired-columns .reverse-column .column-datasets").append(i));this._adjUnpairedOnScrollbar()},_renderUnpairedDisplayStr:function(h){return["(",h," ",d("filtered out"),")"].join("")},_renderUnpairedDataset:function(h){return $("<li/>").attr("id","dataset-"+h.id).addClass("dataset unpaired").attr("draggable",true).addClass(h.selected?"selected":"").append($("<span/>").addClass("dataset-name").text(h.name)).data("dataset",h)},_renderPairButton:function(){return $("<li/>").addClass("dataset unpaired").append($("<span/>").addClass("dataset-name").text(d("Pair these datasets")))},_renderUnpairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no remaining unpaired datasets")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_renderUnpairedNotShown:function(){var h=$('<div class="empty-message"></div>').text("("+d("no datasets were found matching the current filters")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_adjUnpairedOnScrollbar:function(){var k=this.$(".unpaired-columns").last(),l=this.$(".unpaired-columns .reverse-column .dataset").first();if(!l.size()){return}var h=k.offset().left+k.outerWidth(),j=l.offset().left+l.outerWidth(),i=Math.floor(h)-Math.floor(j);this.$(".unpaired-columns .forward-column").css("margin-left",(i>0)?i:0)},_renderPaired:function(i,j){this.$(".paired-column-title .title").text([this.paired.length,d("paired")].join(" "));this.$(".unpair-all-link").toggle(this.paired.length!==0);if(this.paired.length===0){this._renderPairedEmpty();return}else{this.$(".remove-extensions-link").show()}this.$(".paired-columns .column-datasets").empty();var h=this;this.paired.forEach(function(m,k){var l=new f({pair:m});h.$(".paired-columns .column-datasets").append(l.render().$el).append(['<button class="unpair-btn">','<span class="fa fa-unlink" title="',d("Unpair"),'"></span>',"</button>"].join(""))})},_renderPairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no paired datasets yet")+")");this.$(".paired-columns .column-datasets").empty().prepend(h);return h},_renderFooter:function(i,j){var h=this.$(".footer").empty().html(e.templates.footer());this.$(".remove-extensions").prop("checked",this.removeExtensions);if(typeof this.oncancel==="function"){this.$(".cancel-create.btn").show()}return h},_addPluginComponents:function(){this._chooseFiltersPopover(".choose-filters-link");this.$(".help-content i").hoverhighlight(".collection-creator","rgba( 64, 255, 255, 1.0 )")},_chooseFiltersPopover:function(h){function i(l,k){return['<button class="filter-choice btn" ','data-forward="',l,'" data-reverse="',k,'">',d("Forward"),": ",l,", ",d("Reverse"),": ",k,"</button>"].join("")}var j=$(_.template(['<div class="choose-filters">','<div class="help">',d("Choose from the following filters to change which unpaired reads are shown in the display"),":</div>",i("_1","_2"),i("_R1","_R2"),"</div>"].join(""),{}));return this.$(h).popover({container:".collection-creator",placement:"bottom",html:true,content:j})},_validationWarning:function(i,h){var j="validation-warning";if(i==="name"){i=this.$(".collection-name").add(this.$(".collection-name-prompt"));this.$(".collection-name").focus().select()}if(h){i=i||this.$("."+j);i.removeClass(j)}else{i.addClass(j)}},_setUpBehaviors:function(){this.once("rendered",function(){this.trigger("rendered:initial",this)});this.on("pair:new",function(){this._renderUnpaired();this._renderPaired();this.$(".paired-columns").scrollTop(8000000)});this.on("pair:unpair",function(h){this._renderUnpaired();this._renderPaired();this.splitView()});this.on("filter-change",function(){this.filters=[this.$(".forward-unpaired-filter input").val(),this.$(".reverse-unpaired-filter input").val()];this._renderFilters();this._renderUnpaired()});this.on("autopair",function(){this._renderUnpaired();this._renderPaired();var h,i=null;if(this.paired.length){i="alert-success";h=this.paired.length+" "+d("pairs created");if(!this.unpaired.length){h+=": "+d("all datasets have been successfully paired");this.hideUnpaired();this.$(".collection-name").focus()}}else{h=d("Could not automatically create any pairs from the given dataset names")}this._showAlert(h,i)});return this},events:{"click .more-help":"_clickMoreHelp","click .less-help":"_clickLessHelp","click .header .alert button":"_hideAlert","click .forward-column .column-title":"_clickShowOnlyUnpaired","click .reverse-column .column-title":"_clickShowOnlyUnpaired","click .unpair-all-link":"_clickUnpairAll","change .forward-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .forward-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .autopair-link":"_clickAutopair","click .choose-filters .filter-choice":"_clickFilterChoice","click .clear-filters-link":"_clearFilters","change .reverse-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .reverse-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .forward-column .dataset.unpaired":"_clickUnpairedDataset","click .reverse-column .dataset.unpaired":"_clickUnpairedDataset","click .paired-column .dataset.unpaired":"_clickPairRow","click .unpaired-columns":"clearSelectedUnpaired","mousedown .unpaired-columns .dataset":"_mousedownUnpaired","click .paired-column-title":"_clickShowOnlyPaired","mousedown .flexible-partition-drag":"_startPartitionDrag","click .paired-columns .dataset.paired":"selectPair","click .paired-columns":"clearSelectedPaired","click .paired-columns .pair-name":"_clickPairName","click .unpair-btn":"_clickUnpair","dragover .paired-columns .column-datasets":"_dragoverPairedColumns","drop .paired-columns .column-datasets":"_dropPairedColumns","pair.dragstart .paired-columns .column-datasets":"_pairDragstart","pair.dragend .paired-columns .column-datasets":"_pairDragend","change .remove-extensions":function(h){this.toggleExtensions()},"change .collection-name":"_changeName","keydown .collection-name":"_nameCheckForEnter","click .cancel-create":function(h){if(typeof this.oncancel==="function"){this.oncancel.call(this)}},"click .create-collection":"_clickCreate"},_clickMoreHelp:function(h){this.$(".main-help").addClass("expanded");this.$(".more-help").hide()},_clickLessHelp:function(h){this.$(".main-help").removeClass("expanded");this.$(".more-help").show()},_showAlert:function(i,h){console.debug("alert:",i,h);h=h||"alert-danger";this.$(".main-help").hide();this.$(".header .alert").attr("class","alert alert-dismissable").addClass(h).show().find(".alert-message").html(i)},_hideAlert:function(h){this.$(".main-help").show();this.$(".header .alert").hide()},_clickShowOnlyUnpaired:function(h){if(this.$(".paired-columns").is(":visible")){this.hidePaired()}else{this.splitView()}},_clickShowOnlyPaired:function(h){if(this.$(".unpaired-columns").is(":visible")){this.hideUnpaired()}else{this.splitView()}},hideUnpaired:function(h,i){this.unpairedPanelHidden=true;this.pairedPanelHidden=false;this._renderMiddle(h,i)},hidePaired:function(h,i){this.unpairedPanelHidden=false;this.pairedPanelHidden=true;this._renderMiddle(h,i)},splitView:function(h,i){this.unpairedPanelHidden=this.pairedPanelHidden=false;this._renderMiddle(h,i);return this},_clickUnpairAll:function(h){this.unpairAll()},_clickAutopair:function(h){this.autoPair();this.trigger("autopair")},_clickFilterChoice:function(i){var h=$(i.currentTarget);this.$(".forward-unpaired-filter input").val(h.data("forward"));this.$(".reverse-unpaired-filter input").val(h.data("reverse"));this._hideChooseFilters();this.trigger("filter-change")},_hideChooseFilters:function(){this.$(".choose-filters-link").popover("hide");this.$(".popover").css("display","none")},_clearFilters:function(h){this.$(".forward-unpaired-filter input").val("");this.$(".reverse-unpaired-filter input").val("");this.trigger("filter-change")},_clickUnpairedDataset:function(h){h.stopPropagation();return this.toggleSelectUnpaired($(h.currentTarget))},toggleSelectUnpaired:function(j,i){i=i||{};var k=j.data("dataset"),h=i.force!==undefined?i.force:!j.hasClass("selected");if(!j.size()||k===undefined){return j}if(h){j.addClass("selected");if(!i.waitToPair){this.pairAllSelected()}}else{j.removeClass("selected")}return j},pairAllSelected:function(i){i=i||{};var j=this,k=[],h=[],l=[];j.$(".unpaired-columns .forward-column .dataset.selected").each(function(){k.push($(this).data("dataset"))});j.$(".unpaired-columns .reverse-column .dataset.selected").each(function(){h.push($(this).data("dataset"))});k.length=h.length=Math.min(k.length,h.length);k.forEach(function(n,m){try{l.push(j._pair(n,h[m],{silent:true}))}catch(o){j.error(o)}});if(l.length&&!i.silent){this.trigger("pair:new",l)}return l},clearSelectedUnpaired:function(){this.$(".unpaired-columns .dataset.selected").removeClass("selected")},_mousedownUnpaired:function(j){if(j.shiftKey){var i=this,h=$(j.target).addClass("selected"),k=function(l){i.$(l.target).filter(".dataset").addClass("selected")};h.parent().on("mousemove",k);$(document).one("mouseup",function(l){h.parent().off("mousemove",k);i.pairAllSelected()})}},_clickPairRow:function(j){var k=$(j.currentTarget).index(),i=$(".unpaired-columns .forward-column .dataset").eq(k).data("dataset"),h=$(".unpaired-columns .reverse-column .dataset").eq(k).data("dataset");this._pair(i,h)},_startPartitionDrag:function(i){var h=this,l=i.pageY;$("body").css("cursor","ns-resize");h.$(".flexible-partition-drag").css("color","black");function k(m){h.$(".flexible-partition-drag").css("color","");$("body").css("cursor","").unbind("mousemove",j)}function j(m){var n=m.pageY-l;if(!h.adjPartition(n)){$("body").trigger("mouseup")}h._adjUnpairedOnScrollbar();l+=n}$("body").mousemove(j);$("body").one("mouseup",k)},adjPartition:function(i){var h=this.$(".unpaired-columns"),j=this.$(".paired-columns"),k=parseInt(h.css("height"),10),l=parseInt(j.css("height"),10);k=Math.max(10,k+i);l=l-i;var m=i<0;if(m){if(this.unpairedPanelHidden){return false}else{if(k<=10){this.hideUnpaired();return false}}}else{if(this.unpairedPanelHidden){h.show();this.unpairedPanelHidden=false}}if(!m){if(this.pairedPanelHidden){return false}else{if(l<=15){this.hidePaired();return false}}}else{if(this.pairedPanelHidden){j.show();this.pairedPanelHidden=false}}h.css({height:k+"px",flex:"0 0 auto"});return true},selectPair:function(h){h.stopPropagation();$(h.currentTarget).toggleClass("selected")},clearSelectedPaired:function(h){this.$(".paired-columns .dataset.selected").removeClass("selected")},_clickPairName:function(j){j.stopPropagation();var i=$(j.currentTarget),k=this.paired[i.parent().parent().index()/2],h=prompt("Enter a new name for the pair:",k.name);if(h){k.name=h;k.customizedName=true;i.text(k.name)}},_clickUnpair:function(i){var h=Math.floor($(i.currentTarget).index()/2);this._unpair(this.paired[h])},_dragoverPairedColumns:function(k){k.preventDefault();var i=this.$(".paired-columns .column-datasets"),l=i.offset();var j=this._getNearestPairedDatasetLi(k.originalEvent.clientY);$(".paired-drop-placeholder").remove();var h=$('<div class="paired-drop-placeholder"></div>');if(!j.size()){i.append(h)}else{j.before(h)}},_getNearestPairedDatasetLi:function(o){var l=4,j=this.$(".paired-columns .column-datasets li").toArray();for(var k=0;k<j.length;k++){var n=$(j[k]),m=n.offset().top,h=Math.floor(n.outerHeight()/2)+l;if(m+h>o&&m-h<o){return n}}return $()},_dropPairedColumns:function(i){i.preventDefault();i.dataTransfer.dropEffect="move";var h=this._getNearestPairedDatasetLi(i.originalEvent.clientY);if(h.size()){this.$dragging.insertBefore(h)}else{this.$dragging.insertAfter(this.$(".paired-columns .unpair-btn").last())}this._syncPairsToDom();return false},_syncPairsToDom:function(){var h=[];this.$(".paired-columns .dataset.paired").each(function(){h.push($(this).data("pair"))});this.paired=h;this._renderPaired()},_pairDragstart:function(i,j){j.$el.addClass("selected");var h=this.$(".paired-columns .dataset.selected");this.$dragging=h},_pairDragend:function(h,i){$(".paired-drop-placeholder").remove();this.$dragging=null},toggleExtensions:function(i){var h=this;h.removeExtensions=(i!==undefined)?(i):(!h.removeExtensions);_.each(h.paired,function(j){if(j.customizedName){return}j.name=h._guessNameForPair(j.forward,j.reverse)});h._renderPaired();h._renderFooter()},_changeName:function(h){this._validationWarning("name",!!this._getName())},_nameCheckForEnter:function(h){if(h.keyCode===13){this._clickCreate()}},_getName:function(){return _.escape(this.$(".collection-name").val())},_clickCreate:function(i){var h=this._getName();if(!h){this._validationWarning("name")}else{this.createList()}},_printList:function(i){var h=this;_.each(i,function(j){if(i===h.paired){h._printPair(j)}else{}})},_printPair:function(h){this.debug(h.forward.name,h.reverse.name,": ->",h.name)},toString:function(){return"PairedCollectionCreator"}});e.templates=e.templates||{main:_.template(['<div class="header flex-row no-flex"></div>','<div class="middle flex-row flex-row-container"></div>','<div class="footer flex-row no-flex">'].join("")),header:_.template(['<div class="main-help well clear">','<a class="more-help" href="javascript:void(0);">',d("More help"),"</a>",'<div class="help-content">','<a class="less-help" href="javascript:void(0);">',d("Less"),"</a>","</div>","</div>",'<div class="alert alert-dismissable">','<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>','<span class="alert-message"></span>',"</div>",'<div class="column-headers vertically-spaced flex-column-container">','<div class="forward-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired forward"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter forward-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>",'<div class="paired-column flex-column no-flex column">','<div class="column-header">','<a class="choose-filters-link" href="javascript:void(0)">',d("Choose filters"),"</a>",'<a class="clear-filters-link" href="javascript:void(0);">',d("Clear filters"),"</a><br />",'<a class="autopair-link" href="javascript:void(0);">',d("Auto-pair"),"</a>","</div>","</div>",'<div class="reverse-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired reverse"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter reverse-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>","</div>"].join("")),middle:_.template(['<div class="unpaired-columns flex-column-container scroll-container flex-row">','<div class="forward-column flex-column column">','<ol class="column-datasets"></ol>',"</div>",'<div class="paired-column flex-column no-flex column">','<ol class="column-datasets"></ol>',"</div>",'<div class="reverse-column flex-column column">','<ol class="column-datasets"></ol>',"</div>","</div>",'<div class="flexible-partition">','<div class="flexible-partition-drag" title="',d("Drag to change"),'"></div>','<div class="column-header">','<div class="column-title paired-column-title">','<span class="title"></span>',"</div>",'<a class="unpair-all-link" href="javascript:void(0);">',d("Unpair all"),"</a>","</div>","</div>",'<div class="paired-columns flex-column-container scroll-container flex-row">','<ol class="column-datasets"></ol>',"</div>"].join("")),footer:_.template(['<div class="attributes clear">','<div class="clear">','<label class="remove-extensions-prompt pull-right">',d("Remove file extensions from pair names"),"?",'<input class="remove-extensions pull-right" type="checkbox" />',"</label>","</div>",'<div class="clear">','<input class="collection-name form-control pull-right" ','placeholder="',d("Enter a name for your new list"),'" />','<div class="collection-name-prompt pull-right">',d("Name"),":</div>","</div>","</div>",'<div class="actions clear vertically-spaced">','<div class="other-options pull-left">','<button class="cancel-create btn" tabindex="-1">',d("Cancel"),"</button>",'<div class="create-other btn-group dropup">','<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">',d("Create a different kind of collection"),' <span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">','<li><a href="#">',d("Create a <i>single</i> pair"),"</a></li>",'<li><a href="#">',d("Create a list of <i>unpaired</i> datasets"),"</a></li>","</ul>","</div>","</div>",'<div class="main-options pull-right">','<button class="create-collection btn btn-primary">',d("Create list"),"</button>","</div>","</div>"].join("")),helpContent:_.template(["<p>",d(["Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). ","These collections can be passed to tools and workflows in order to have analyses done on each member of ","the entire group. This interface allows you to create a collection, choose which datasets are paired, ","and re-order the final collection."].join("")),"</p>","<p>",d(['Unpaired datasets are shown in the <i data-target=".unpaired-columns">unpaired section</i> ',"(hover over the underlined words to highlight below). ",'Paired datasets are shown in the <i data-target=".paired-columns">paired section</i>.',"<ul>To pair datasets, you can:","<li>Click a dataset in the ",'<i data-target=".unpaired-columns .forward-column .column-datasets,','.unpaired-columns .forward-column">forward column</i> ',"to select it then click a dataset in the ",'<i data-target=".unpaired-columns .reverse-column .column-datasets,','.unpaired-columns .reverse-column">reverse column</i>.',"</li>",'<li>Click one of the "Pair these datasets" buttons in the ','<i data-target=".unpaired-columns .paired-column .column-datasets,','.unpaired-columns .paired-column">middle column</i> ',"to pair the datasets in a particular row.","</li>",'<li>Click <i data-target=".autopair-link">"Auto-pair"</i> ',"to have your datasets automatically paired based on name.","</li>","</ul>"].join("")),"</p>","<p>",d(["<ul>You can filter what is shown in the unpaired sections by:","<li>Entering partial dataset names in either the ",'<i data-target=".forward-unpaired-filter input">forward filter</i> or ','<i data-target=".reverse-unpaired-filter input">reverse filter</i>.',"</li>","<li>Choosing from a list of preset filters by clicking the ",'<i data-target=".choose-filters-link">"Choose filters" link</i>.',"</li>","<li>Entering regular expressions to match dataset names. See: ",'<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expre…"',' target="_blank">MDN\'s JavaScript Regular Expression Tutorial</a>. ',"Note: forward slashes (\\) are not needed.","</li>","<li>Clearing the filters by clicking the ",'<i data-target=".clear-filters-link">"Clear filters" link</i>.',"</li>","</ul>"].join("")),"</p>","<p>",d(["To unpair individual dataset pairs, click the ",'<i data-target=".unpair-btn">unpair buttons ( <span class="fa fa-unlink"></span> )</i>. ','Click the <i data-target=".unpair-all-link">"Unpair all" link</i> to unpair all pairs.'].join("")),"</p>","<p>",d(['You can include or remove the file extensions (e.g. ".fastq") from your pair names by toggling the ','<i data-target=".remove-extensions-prompt">"Remove file extensions from pair names?"</i> control.'].join("")),"</p>","<p>",d(['Once your collection is complete, enter a <i data-target=".collection-name">name</i> and ','click <i data-target=".create-collection">"Create list"</i>. ',"(Note: you do not have to pair all unpaired datasets to finish.)"].join("")),"</p>"].join(""))};(function(){jQuery.fn.extend({hoverhighlight:function h(j,i){j=j||"body";if(!this.size()){return this}$(this).each(function(){var l=$(this),k=l.data("target");if(k){l.mouseover(function(m){$(k,j).css({background:i})}).mouseout(function(m){$(k).css({background:""})})}});return this}})}());var b=function c(j,h){h=_.defaults(h||{},{datasets:j,oncancel:function(){Galaxy.modal.hide()},oncreate:function(){Galaxy.modal.hide();Galaxy.currHistoryPanel.refreshContents()}});if(!window.Galaxy||!Galaxy.modal){throw new Error("Galaxy or Galaxy.modal not found")}var i=new e(h).render();Galaxy.modal.show({title:"Create a collection of paired datasets",body:i.$el,width:"80%",height:"800px",closing_events:true});window.PCC=i;return i};return{PairedCollectionCreator:e,pairedCollectionCreatorModal:b}});
\ No newline at end of file
+define(["utils/levenshtein","mvc/base-mvc","utils/localization"],function(g,a,d){var f=Backbone.View.extend(a.LoggableMixin).extend({tagName:"li",className:"dataset paired",initialize:function(h){this.pair=h.pair||{}},template:_.template(['<span class="forward-dataset-name flex-column"><%= pair.forward.name %></span>','<span class="pair-name-column flex-column">','<span class="pair-name"><%= pair.name %></span>',"</span>",'<span class="reverse-dataset-name flex-column"><%= pair.reverse.name %></span>'].join("")),render:function(){this.$el.attr("draggable",true).data("pair",this.pair).html(this.template({pair:this.pair})).addClass("flex-column-container");return this},events:{dragstart:"_dragstart",dragend:"_dragend",dragover:"_sendToParent",drop:"_sendToParent"},_dragstart:function(h){h.currentTarget.style.opacity="0.4";if(h.originalEvent){h=h.originalEvent}h.dataTransfer.effectAllowed="move";h.dataTransfer.setData("text/plain",JSON.stringify(this.pair));this.$el.parent().trigger("pair.dragstart",[this])},_dragend:function(h){h.currentTarget.style.opacity="1.0";this.$el.parent().trigger("pair.dragend",[this])},_sendToParent:function(h){this.$el.parent().trigger(h)},toString:function(){return"PairView("+this.pair.name+")"}});var e=Backbone.View.extend(a.LoggableMixin).extend({className:"collection-creator flex-row-container",initialize:function(h){h=_.defaults(h,{datasets:[],filters:this.DEFAULT_FILTERS,automaticallyPair:true,matchPercentage:1,strategy:"lcs"});this.initialList=h.datasets;this.historyId=h.historyId;this.filters=this.commonFilters[h.filters]||this.commonFilters[this.DEFAULT_FILTERS];if(_.isArray(h.filters)){this.filters=h.filters}this.automaticallyPair=h.automaticallyPair;this.matchPercentage=h.matchPercentage;this.strategy=this.strategies[h.strategy]||this.strategies[this.DEFAULT_STRATEGY];if(_.isFunction(h.strategy)){this.strategy=h.strategy}this.removeExtensions=true;this.oncancel=h.oncancel;this.oncreate=h.oncreate;this.autoscrollDist=h.autoscrollDist||24;this.unpairedPanelHidden=false;this.pairedPanelHidden=false;this.$dragging=null;this._setUpBehaviors();this._dataSetUp()},commonFilters:{none:["",""],illumina:["_1","_2"]},DEFAULT_FILTERS:"illumina",strategies:{lcs:"autoPairLCSs",levenshtein:"autoPairLevenshtein"},DEFAULT_STRATEGY:"lcs",_dataSetUp:function(){this.paired=[];this.unpaired=[];this.selectedIds=[];this._sortInitialList();this._ensureIds();this.unpaired=this.initialList.slice(0);if(this.automaticallyPair){this.autoPair();this.once("rendered:initial",function(){this.trigger("autopair")})}},_sortInitialList:function(){this._sortDatasetList(this.initialList)},_sortDatasetList:function(h){h.sort(function(j,i){return naturalSort(j.name,i.name)});return h},_ensureIds:function(){this.initialList.forEach(function(h){if(!h.hasOwnProperty("id")){h.id=_.uniqueId()}});return this.initialList},_splitByFilters:function(j){var i=[],h=[];this.unpaired.forEach(function(k){if(this._filterFwdFn(k)){i.push(k)}if(this._filterRevFn(k)){h.push(k)}}.bind(this));return[i,h]},_filterFwdFn:function(i){var h=new RegExp(this.filters[0]);return h.test(i.name)},_filterRevFn:function(i){var h=new RegExp(this.filters[1]);return h.test(i.name)},_addToUnpaired:function(i){var h=function(j,l){if(j===l){return j}var k=Math.floor((l-j)/2)+j,m=naturalSort(i.name,this.unpaired[k].name);if(m<0){return h(j,k)}else{if(m>0){return h(k+1,l)}}while(this.unpaired[k]&&this.unpaired[k].name===i.name){k++}return k}.bind(this);this.unpaired.splice(h(0,this.unpaired.length),0,i)},autoPair:function(i){i=i||this.strategy;var h=this.simpleAutoPair();h=h.concat(this[i].call(this));return h},simpleAutoPair:function(){var o=0,m,s=this._splitByFilters(),h=s[0],r=s[1],q,u,k=false,t=[];while(o<h.length){var n=h[o];q=n.name.replace(this.filters[0],"");k=false;for(m=0;m<r.length;m++){var p=r[m];u=p.name.replace(this.filters[1],"");if(n!==p&&q===u){k=true;var l=this._pair(h.splice(o,1)[0],r.splice(m,1)[0],{silent:true});t.push(l);break}}if(!k){o+=1}}return t},autoPairLevenshtein:function(){var p=0,n,u=this._splitByFilters(),h=u[0],s=u[1],r,x,k,t,l,v=[];while(p<h.length){var o=h[p];r=o.name.replace(this.filters[0],"");l=Number.MAX_VALUE;for(n=0;n<s.length;n++){var q=s[n];x=q.name.replace(this.filters[1],"");if(o!==q){if(r===x){t=n;l=0;break}k=levenshteinDistance(r,x);if(k<l){t=n;l=k}}}var w=1-(l/(Math.max(r.length,x.length)));if(w>=this.matchPercentage){var m=this._pair(h.splice(p,1)[0],s.splice(t,1)[0],{silent:true});v.push(m);if(h.length<=0||s.length<=0){return v}}else{p+=1}}return v},autoPairLCSs:function(){var n=0,l,u=this._splitByFilters(),h=u[0],s=u[1],r,y,x,t,p,v=[];if(!h.length||!s.length){return v}while(n<h.length){var m=h[n];r=m.name.replace(this.filters[0],"");p=0;for(l=0;l<s.length;l++){var q=s[l];y=q.name.replace(this.filters[1],"");if(m!==q){if(r===y){t=l;p=r.length;break}var o=this._naiveStartingAndEndingLCS(r,y);x=o.length;if(x>p){t=l;p=x}}}var w=p/(Math.min(r.length,y.length));if(w>=this.matchPercentage){var k=this._pair(h.splice(n,1)[0],s.splice(t,1)[0],{silent:true});v.push(k);if(h.length<=0||s.length<=0){return v}}else{n+=1}}return v},_naiveStartingAndEndingLCS:function(m,k){var n="",o="",l=0,h=0;while(l<m.length&&l<k.length){if(m[l]!==k[l]){break}n+=m[l];l+=1}if(l===m.length){return m}if(l===k.length){return k}l=(m.length-1);h=(k.length-1);while(l>=0&&h>=0){if(m[l]!==k[h]){break}o=[m[l],o].join("");l-=1;h-=1}return n+o},_pair:function(j,h,i){i=i||{};var k=this._createPair(j,h,i.name);this.paired.push(k);this.unpaired=_.without(this.unpaired,j,h);if(!i.silent){this.trigger("pair:new",k)}return k},_createPair:function(j,h,i){if(!(j&&h)||(j===h)){throw new Error("Bad pairing: "+[JSON.stringify(j),JSON.stringify(h)])}i=i||this._guessNameForPair(j,h);return{forward:j,name:i,reverse:h}},_guessNameForPair:function(j,h,k){k=(k!==undefined)?(k):(this.removeExtensions);var i=this._naiveStartingAndEndingLCS(j.name.replace(this.filters[0],""),h.name.replace(this.filters[1],""));if(k){var l=i.lastIndexOf(".");if(l>0){i=i.slice(0,l)}}return i||(j.name+" & "+h.name)},_unpair:function(i,h){h=h||{};if(!i){throw new Error("Bad pair: "+JSON.stringify(i))}this.paired=_.without(this.paired,i);this._addToUnpaired(i.forward);this._addToUnpaired(i.reverse);if(!h.silent){this.trigger("pair:unpair",[i])}return i},unpairAll:function(){var h=[];while(this.paired.length){h.push(this._unpair(this.paired[0],{silent:true}))}this.trigger("pair:unpair",h)},_pairToJSON:function(h){return{collection_type:"paired",src:"new_collection",name:h.name,element_identifiers:[{name:"forward",id:h.forward.id,src:"hda"},{name:"reverse",id:h.reverse.id,src:"hda"}]}},createList:function(){var j=this,i;if(j.historyId){i="/api/histories/"+this.historyId+"/contents/dataset_collections"}var h={type:"dataset_collection",collection_type:"list:paired",name:_.escape(j.$(".collection-name").val()),element_identifiers:j.paired.map(function(k){return j._pairToJSON(k)})};return jQuery.ajax(i,{type:"POST",contentType:"application/json",dataType:"json",data:JSON.stringify(h)}).fail(function(m,k,l){j._ajaxErrHandler(m,k,l)}).done(function(k,l,m){j.trigger("collection:created",k,l,m);if(typeof j.oncreate==="function"){j.oncreate.call(this,k,l,m)}})},_ajaxErrHandler:function(k,h,j){this.error(k,h,j);var i=d("An error occurred while creating this collection");if(k){if(k.readyState===0&&k.status===0){i+=": "+d("Galaxy could not be reached and may be updating.")+d(" Try again in a few minutes.")}else{if(k.responseJSON){i+="<br /><pre>"+JSON.stringify(k.responseJSON)+"</pre>"}else{i+=": "+j}}}creator._showAlert(i,"alert-danger")},render:function(h,i){this.$el.empty().html(e.templates.main());this._renderHeader(h);this._renderMiddle(h);this._renderFooter(h);this._addPluginComponents();this.trigger("rendered",this);return this},_renderHeader:function(i,j){var h=this.$(".header").empty().html(e.templates.header()).find(".help-content").prepend($(e.templates.helpContent()));this._renderFilters();return h},_renderFilters:function(){return this.$(".forward-column .column-header input").val(this.filters[0]).add(this.$(".reverse-column .column-header input").val(this.filters[1]))},_renderMiddle:function(i,j){var h=this.$(".middle").empty().html(e.templates.middle());if(this.unpairedPanelHidden){this.$(".unpaired-columns").hide()}else{if(this.pairedPanelHidden){this.$(".paired-columns").hide()}}this._renderUnpaired();this._renderPaired();return h},_renderUnpaired:function(m,n){var k=this,l,i,h=[],j=this._splitByFilters();this.$(".forward-column .title").text([j[0].length,d("unpaired forward")].join(" "));this.$(".forward-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[0].length));this.$(".reverse-column .title").text([j[1].length,d("unpaired reverse")].join(" "));this.$(".reverse-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[1].length));this.$(".unpaired-columns .column-datasets").empty();this.$(".autopair-link").toggle(this.unpaired.length!==0);if(this.unpaired.length===0){this._renderUnpairedEmpty();return}i=j[1].map(function(p,o){if((j[0][o]!==undefined)&&(j[0][o]!==p)){h.push(k._renderPairButton())}return k._renderUnpairedDataset(p)});l=j[0].map(function(o){return k._renderUnpairedDataset(o)});if(!l.length&&!i.length){this._renderUnpairedNotShown();return}this.$(".unpaired-columns .forward-column .column-datasets").append(l).add(this.$(".unpaired-columns .paired-column .column-datasets").append(h)).add(this.$(".unpaired-columns .reverse-column .column-datasets").append(i));this._adjUnpairedOnScrollbar()},_renderUnpairedDisplayStr:function(h){return["(",h," ",d("filtered out"),")"].join("")},_renderUnpairedDataset:function(h){return $("<li/>").attr("id","dataset-"+h.id).addClass("dataset unpaired").attr("draggable",true).addClass(h.selected?"selected":"").append($("<span/>").addClass("dataset-name").text(h.name)).data("dataset",h)},_renderPairButton:function(){return $("<li/>").addClass("dataset unpaired").append($("<span/>").addClass("dataset-name").text(d("Pair these datasets")))},_renderUnpairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no remaining unpaired datasets")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_renderUnpairedNotShown:function(){var h=$('<div class="empty-message"></div>').text("("+d("no datasets were found matching the current filters")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_adjUnpairedOnScrollbar:function(){var k=this.$(".unpaired-columns").last(),l=this.$(".unpaired-columns .reverse-column .dataset").first();if(!l.size()){return}var h=k.offset().left+k.outerWidth(),j=l.offset().left+l.outerWidth(),i=Math.floor(h)-Math.floor(j);this.$(".unpaired-columns .forward-column").css("margin-left",(i>0)?i:0)},_renderPaired:function(i,j){this.$(".paired-column-title .title").text([this.paired.length,d("paired")].join(" "));this.$(".unpair-all-link").toggle(this.paired.length!==0);if(this.paired.length===0){this._renderPairedEmpty();return}else{this.$(".remove-extensions-link").show()}this.$(".paired-columns .column-datasets").empty();var h=this;this.paired.forEach(function(m,k){var l=new f({pair:m});h.$(".paired-columns .column-datasets").append(l.render().$el).append(['<button class="unpair-btn">','<span class="fa fa-unlink" title="',d("Unpair"),'"></span>',"</button>"].join(""))})},_renderPairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no paired datasets yet")+")");this.$(".paired-columns .column-datasets").empty().prepend(h);return h},_renderFooter:function(i,j){var h=this.$(".footer").empty().html(e.templates.footer());this.$(".remove-extensions").prop("checked",this.removeExtensions);if(typeof this.oncancel==="function"){this.$(".cancel-create.btn").show()}return h},_addPluginComponents:function(){this._chooseFiltersPopover(".choose-filters-link");this.$(".help-content i").hoverhighlight(".collection-creator","rgba( 64, 255, 255, 1.0 )")},_chooseFiltersPopover:function(h){function i(l,k){return['<button class="filter-choice btn" ','data-forward="',l,'" data-reverse="',k,'">',d("Forward"),": ",l,", ",d("Reverse"),": ",k,"</button>"].join("")}var j=$(_.template(['<div class="choose-filters">','<div class="help">',d("Choose from the following filters to change which unpaired reads are shown in the display"),":</div>",i("_1","_2"),i("_R1","_R2"),"</div>"].join(""))({}));return this.$(h).popover({container:".collection-creator",placement:"bottom",html:true,content:j})},_validationWarning:function(i,h){var j="validation-warning";if(i==="name"){i=this.$(".collection-name").add(this.$(".collection-name-prompt"));this.$(".collection-name").focus().select()}if(h){i=i||this.$("."+j);i.removeClass(j)}else{i.addClass(j)}},_setUpBehaviors:function(){this.once("rendered",function(){this.trigger("rendered:initial",this)});this.on("pair:new",function(){this._renderUnpaired();this._renderPaired();this.$(".paired-columns").scrollTop(8000000)});this.on("pair:unpair",function(h){this._renderUnpaired();this._renderPaired();this.splitView()});this.on("filter-change",function(){this.filters=[this.$(".forward-unpaired-filter input").val(),this.$(".reverse-unpaired-filter input").val()];this._renderFilters();this._renderUnpaired()});this.on("autopair",function(){this._renderUnpaired();this._renderPaired();var h,i=null;if(this.paired.length){i="alert-success";h=this.paired.length+" "+d("pairs created");if(!this.unpaired.length){h+=": "+d("all datasets have been successfully paired");this.hideUnpaired();this.$(".collection-name").focus()}}else{h=d("Could not automatically create any pairs from the given dataset names")}this._showAlert(h,i)});return this},events:{"click .more-help":"_clickMoreHelp","click .less-help":"_clickLessHelp","click .header .alert button":"_hideAlert","click .forward-column .column-title":"_clickShowOnlyUnpaired","click .reverse-column .column-title":"_clickShowOnlyUnpaired","click .unpair-all-link":"_clickUnpairAll","change .forward-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .forward-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .autopair-link":"_clickAutopair","click .choose-filters .filter-choice":"_clickFilterChoice","click .clear-filters-link":"_clearFilters","change .reverse-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .reverse-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .forward-column .dataset.unpaired":"_clickUnpairedDataset","click .reverse-column .dataset.unpaired":"_clickUnpairedDataset","click .paired-column .dataset.unpaired":"_clickPairRow","click .unpaired-columns":"clearSelectedUnpaired","mousedown .unpaired-columns .dataset":"_mousedownUnpaired","click .paired-column-title":"_clickShowOnlyPaired","mousedown .flexible-partition-drag":"_startPartitionDrag","click .paired-columns .dataset.paired":"selectPair","click .paired-columns":"clearSelectedPaired","click .paired-columns .pair-name":"_clickPairName","click .unpair-btn":"_clickUnpair","dragover .paired-columns .column-datasets":"_dragoverPairedColumns","drop .paired-columns .column-datasets":"_dropPairedColumns","pair.dragstart .paired-columns .column-datasets":"_pairDragstart","pair.dragend .paired-columns .column-datasets":"_pairDragend","change .remove-extensions":function(h){this.toggleExtensions()},"change .collection-name":"_changeName","keydown .collection-name":"_nameCheckForEnter","click .cancel-create":function(h){if(typeof this.oncancel==="function"){this.oncancel.call(this)}},"click .create-collection":"_clickCreate"},_clickMoreHelp:function(h){this.$(".main-help").addClass("expanded");this.$(".more-help").hide()},_clickLessHelp:function(h){this.$(".main-help").removeClass("expanded");this.$(".more-help").show()},_showAlert:function(i,h){h=h||"alert-danger";this.$(".main-help").hide();this.$(".header .alert").attr("class","alert alert-dismissable").addClass(h).show().find(".alert-message").html(i)},_hideAlert:function(h){this.$(".main-help").show();this.$(".header .alert").hide()},_clickShowOnlyUnpaired:function(h){if(this.$(".paired-columns").is(":visible")){this.hidePaired()}else{this.splitView()}},_clickShowOnlyPaired:function(h){if(this.$(".unpaired-columns").is(":visible")){this.hideUnpaired()}else{this.splitView()}},hideUnpaired:function(h,i){this.unpairedPanelHidden=true;this.pairedPanelHidden=false;this._renderMiddle(h,i)},hidePaired:function(h,i){this.unpairedPanelHidden=false;this.pairedPanelHidden=true;this._renderMiddle(h,i)},splitView:function(h,i){this.unpairedPanelHidden=this.pairedPanelHidden=false;this._renderMiddle(h,i);return this},_clickUnpairAll:function(h){this.unpairAll()},_clickAutopair:function(h){this.autoPair();this.trigger("autopair")},_clickFilterChoice:function(i){var h=$(i.currentTarget);this.$(".forward-unpaired-filter input").val(h.data("forward"));this.$(".reverse-unpaired-filter input").val(h.data("reverse"));this._hideChooseFilters();this.trigger("filter-change")},_hideChooseFilters:function(){this.$(".choose-filters-link").popover("hide");this.$(".popover").css("display","none")},_clearFilters:function(h){this.$(".forward-unpaired-filter input").val("");this.$(".reverse-unpaired-filter input").val("");this.trigger("filter-change")},_clickUnpairedDataset:function(h){h.stopPropagation();return this.toggleSelectUnpaired($(h.currentTarget))},toggleSelectUnpaired:function(j,i){i=i||{};var k=j.data("dataset"),h=i.force!==undefined?i.force:!j.hasClass("selected");if(!j.size()||k===undefined){return j}if(h){j.addClass("selected");if(!i.waitToPair){this.pairAllSelected()}}else{j.removeClass("selected")}return j},pairAllSelected:function(i){i=i||{};var j=this,k=[],h=[],l=[];j.$(".unpaired-columns .forward-column .dataset.selected").each(function(){k.push($(this).data("dataset"))});j.$(".unpaired-columns .reverse-column .dataset.selected").each(function(){h.push($(this).data("dataset"))});k.length=h.length=Math.min(k.length,h.length);k.forEach(function(n,m){try{l.push(j._pair(n,h[m],{silent:true}))}catch(o){j.error(o)}});if(l.length&&!i.silent){this.trigger("pair:new",l)}return l},clearSelectedUnpaired:function(){this.$(".unpaired-columns .dataset.selected").removeClass("selected")},_mousedownUnpaired:function(j){if(j.shiftKey){var i=this,h=$(j.target).addClass("selected"),k=function(l){i.$(l.target).filter(".dataset").addClass("selected")};h.parent().on("mousemove",k);$(document).one("mouseup",function(l){h.parent().off("mousemove",k);i.pairAllSelected()})}},_clickPairRow:function(j){var k=$(j.currentTarget).index(),i=$(".unpaired-columns .forward-column .dataset").eq(k).data("dataset"),h=$(".unpaired-columns .reverse-column .dataset").eq(k).data("dataset");this._pair(i,h)},_startPartitionDrag:function(i){var h=this,l=i.pageY;$("body").css("cursor","ns-resize");h.$(".flexible-partition-drag").css("color","black");function k(m){h.$(".flexible-partition-drag").css("color","");$("body").css("cursor","").unbind("mousemove",j)}function j(m){var n=m.pageY-l;if(!h.adjPartition(n)){$("body").trigger("mouseup")}h._adjUnpairedOnScrollbar();l+=n}$("body").mousemove(j);$("body").one("mouseup",k)},adjPartition:function(i){var h=this.$(".unpaired-columns"),j=this.$(".paired-columns"),k=parseInt(h.css("height"),10),l=parseInt(j.css("height"),10);k=Math.max(10,k+i);l=l-i;var m=i<0;if(m){if(this.unpairedPanelHidden){return false}else{if(k<=10){this.hideUnpaired();return false}}}else{if(this.unpairedPanelHidden){h.show();this.unpairedPanelHidden=false}}if(!m){if(this.pairedPanelHidden){return false}else{if(l<=15){this.hidePaired();return false}}}else{if(this.pairedPanelHidden){j.show();this.pairedPanelHidden=false}}h.css({height:k+"px",flex:"0 0 auto"});return true},selectPair:function(h){h.stopPropagation();$(h.currentTarget).toggleClass("selected")},clearSelectedPaired:function(h){this.$(".paired-columns .dataset.selected").removeClass("selected")},_clickPairName:function(k){k.stopPropagation();var m=$(k.currentTarget),j=m.parent().parent(),i=j.index(".dataset.paired"),l=this.paired[i],h=prompt("Enter a new name for the pair:",l.name);if(h){l.name=h;l.customizedName=true;m.text(l.name)}},_clickUnpair:function(i){var h=Math.floor($(i.currentTarget).index(".unpair-btn"));this._unpair(this.paired[h])},_dragoverPairedColumns:function(k){k.preventDefault();var i=this.$(".paired-columns .column-datasets");this._checkForAutoscroll(i,k.originalEvent.clientY);var j=this._getNearestPairedDatasetLi(k.originalEvent.clientY);$(".paired-drop-placeholder").remove();var h=$('<div class="paired-drop-placeholder"></div>');if(!j.size()){i.append(h)}else{j.before(h)}},_checkForAutoscroll:function(h,n){var l=2;var m=h.offset(),k=h.scrollTop(),i=n-m.top,j=(m.top+h.outerHeight())-n;if(i>=0&&i<this.autoscrollDist){h.scrollTop(k-l)}else{if(j>=0&&j<this.autoscrollDist){h.scrollTop(k+l)}}},_getNearestPairedDatasetLi:function(o){var l=4,j=this.$(".paired-columns .column-datasets li").toArray();for(var k=0;k<j.length;k++){var n=$(j[k]),m=n.offset().top,h=Math.floor(n.outerHeight()/2)+l;if(m+h>o&&m-h<o){return n}}return $()},_dropPairedColumns:function(i){i.preventDefault();i.dataTransfer.dropEffect="move";var h=this._getNearestPairedDatasetLi(i.originalEvent.clientY);if(h.size()){this.$dragging.insertBefore(h)}else{this.$dragging.insertAfter(this.$(".paired-columns .unpair-btn").last())}this._syncPairsToDom();return false},_syncPairsToDom:function(){var h=[];this.$(".paired-columns .dataset.paired").each(function(){h.push($(this).data("pair"))});this.paired=h;this._renderPaired()},_pairDragstart:function(i,j){j.$el.addClass("selected");var h=this.$(".paired-columns .dataset.selected");this.$dragging=h},_pairDragend:function(h,i){$(".paired-drop-placeholder").remove();this.$dragging=null},toggleExtensions:function(i){var h=this;h.removeExtensions=(i!==undefined)?(i):(!h.removeExtensions);_.each(h.paired,function(j){if(j.customizedName){return}j.name=h._guessNameForPair(j.forward,j.reverse)});h._renderPaired();h._renderFooter()},_changeName:function(h){this._validationWarning("name",!!this._getName())},_nameCheckForEnter:function(h){if(h.keyCode===13){this._clickCreate()}},_getName:function(){return _.escape(this.$(".collection-name").val())},_clickCreate:function(i){var h=this._getName();if(!h){this._validationWarning("name")}else{this.createList()}},_printList:function(i){var h=this;_.each(i,function(j){if(i===h.paired){h._printPair(j)}else{}})},_printPair:function(h){this.debug(h.forward.name,h.reverse.name,": ->",h.name)},toString:function(){return"PairedCollectionCreator"}});e.templates=e.templates||{main:_.template(['<div class="header flex-row no-flex"></div>','<div class="middle flex-row flex-row-container"></div>','<div class="footer flex-row no-flex">'].join("")),header:_.template(['<div class="main-help well clear">','<a class="more-help" href="javascript:void(0);">',d("More help"),"</a>",'<div class="help-content">','<a class="less-help" href="javascript:void(0);">',d("Less"),"</a>","</div>","</div>",'<div class="alert alert-dismissable">','<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>','<span class="alert-message"></span>',"</div>",'<div class="column-headers vertically-spaced flex-column-container">','<div class="forward-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired forward"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter forward-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>",'<div class="paired-column flex-column no-flex column">','<div class="column-header">','<a class="choose-filters-link" href="javascript:void(0)">',d("Choose filters"),"</a>",'<a class="clear-filters-link" href="javascript:void(0);">',d("Clear filters"),"</a><br />",'<a class="autopair-link" href="javascript:void(0);">',d("Auto-pair"),"</a>","</div>","</div>",'<div class="reverse-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired reverse"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter reverse-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>","</div>"].join("")),middle:_.template(['<div class="unpaired-columns flex-column-container scroll-container flex-row">','<div class="forward-column flex-column column">','<ol class="column-datasets"></ol>',"</div>",'<div class="paired-column flex-column no-flex column">','<ol class="column-datasets"></ol>',"</div>",'<div class="reverse-column flex-column column">','<ol class="column-datasets"></ol>',"</div>","</div>",'<div class="flexible-partition">','<div class="flexible-partition-drag" title="',d("Drag to change"),'"></div>','<div class="column-header">','<div class="column-title paired-column-title">','<span class="title"></span>',"</div>",'<a class="unpair-all-link" href="javascript:void(0);">',d("Unpair all"),"</a>","</div>","</div>",'<div class="paired-columns flex-column-container scroll-container flex-row">','<ol class="column-datasets"></ol>',"</div>"].join("")),footer:_.template(['<div class="attributes clear">','<div class="clear">','<label class="remove-extensions-prompt pull-right">',d("Remove file extensions from pair names"),"?",'<input class="remove-extensions pull-right" type="checkbox" />',"</label>","</div>",'<div class="clear">','<input class="collection-name form-control pull-right" ','placeholder="',d("Enter a name for your new list"),'" />','<div class="collection-name-prompt pull-right">',d("Name"),":</div>","</div>","</div>",'<div class="actions clear vertically-spaced">','<div class="other-options pull-left">','<button class="cancel-create btn" tabindex="-1">',d("Cancel"),"</button>",'<div class="create-other btn-group dropup">','<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">',d("Create a different kind of collection"),' <span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">','<li><a href="#">',d("Create a <i>single</i> pair"),"</a></li>",'<li><a href="#">',d("Create a list of <i>unpaired</i> datasets"),"</a></li>","</ul>","</div>","</div>",'<div class="main-options pull-right">','<button class="create-collection btn btn-primary">',d("Create list"),"</button>","</div>","</div>"].join("")),helpContent:_.template(["<p>",d(["Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). ","These collections can be passed to tools and workflows in order to have analyses done on each member of ","the entire group. This interface allows you to create a collection, choose which datasets are paired, ","and re-order the final collection."].join("")),"</p>","<p>",d(['Unpaired datasets are shown in the <i data-target=".unpaired-columns">unpaired section</i> ',"(hover over the underlined words to highlight below). ",'Paired datasets are shown in the <i data-target=".paired-columns">paired section</i>.',"<ul>To pair datasets, you can:","<li>Click a dataset in the ",'<i data-target=".unpaired-columns .forward-column .column-datasets,','.unpaired-columns .forward-column">forward column</i> ',"to select it then click a dataset in the ",'<i data-target=".unpaired-columns .reverse-column .column-datasets,','.unpaired-columns .reverse-column">reverse column</i>.',"</li>",'<li>Click one of the "Pair these datasets" buttons in the ','<i data-target=".unpaired-columns .paired-column .column-datasets,','.unpaired-columns .paired-column">middle column</i> ',"to pair the datasets in a particular row.","</li>",'<li>Click <i data-target=".autopair-link">"Auto-pair"</i> ',"to have your datasets automatically paired based on name.","</li>","</ul>"].join("")),"</p>","<p>",d(["<ul>You can filter what is shown in the unpaired sections by:","<li>Entering partial dataset names in either the ",'<i data-target=".forward-unpaired-filter input">forward filter</i> or ','<i data-target=".reverse-unpaired-filter input">reverse filter</i>.',"</li>","<li>Choosing from a list of preset filters by clicking the ",'<i data-target=".choose-filters-link">"Choose filters" link</i>.',"</li>","<li>Entering regular expressions to match dataset names. See: ",'<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expre…"',' target="_blank">MDN\'s JavaScript Regular Expression Tutorial</a>. ',"Note: forward slashes (\\) are not needed.","</li>","<li>Clearing the filters by clicking the ",'<i data-target=".clear-filters-link">"Clear filters" link</i>.',"</li>","</ul>"].join("")),"</p>","<p>",d(["To unpair individual dataset pairs, click the ",'<i data-target=".unpair-btn">unpair buttons ( <span class="fa fa-unlink"></span> )</i>. ','Click the <i data-target=".unpair-all-link">"Unpair all" link</i> to unpair all pairs.'].join("")),"</p>","<p>",d(['You can include or remove the file extensions (e.g. ".fastq") from your pair names by toggling the ','<i data-target=".remove-extensions-prompt">"Remove file extensions from pair names?"</i> control.'].join("")),"</p>","<p>",d(['Once your collection is complete, enter a <i data-target=".collection-name">name</i> and ','click <i data-target=".create-collection">"Create list"</i>. ',"(Note: you do not have to pair all unpaired datasets to finish.)"].join("")),"</p>"].join(""))};(function(){jQuery.fn.extend({hoverhighlight:function h(j,i){j=j||"body";if(!this.size()){return this}$(this).each(function(){var l=$(this),k=l.data("target");if(k){l.mouseover(function(m){$(k,j).css({background:i})}).mouseout(function(m){$(k).css({background:""})})}});return this}})}());var b=function c(j,h){h=_.defaults(h||{},{datasets:j,oncancel:function(){Galaxy.modal.hide()},oncreate:function(){Galaxy.modal.hide();Galaxy.currHistoryPanel.refreshContents()}});if(!window.Galaxy||!Galaxy.modal){throw new Error("Galaxy or Galaxy.modal not found")}var i=new e(h).render();Galaxy.modal.show({title:"Create a collection of paired datasets",body:i.$el,width:"80%",height:"800px",closing_events:true});window.PCC=i;return i};return{PairedCollectionCreator:e,pairedCollectionCreatorModal:b}});
\ No newline at end of file
diff -r cf105e43d141b258dbf200d49bd3cce5f4d7dddc -r 487461afaba5cc7f0f6bb38397be3773cf46ce45 static/scripts/packed/utils/LazyDataLoader.js
--- a/static/scripts/packed/utils/LazyDataLoader.js
+++ /dev/null
@@ -1,1 +0,0 @@
-function LazyDataLoader(c){var a=this,d="loaded.new",b="complete";ERROR_EVENT="error";jQuery.extend(a,LoggableMixin);jQuery.extend(a,{total:undefined,url:undefined,currentIntervalId:undefined,data:[],delay:4000,start:0,size:4000,initialize:function(e){jQuery.extend(a,e);if(e.hasOwnProperty("initialize")){e.initialize.call(a,e)}this.log(this+" initialized:",a)},buildUrl:function(f,e){return this.url+"&"+jQuery.param({start_val:f,max_vals:e})},ajaxErrorFn:function(g,e,f){console.error("ERROR fetching data:",f)},converters:{"* text":window.String,"text html":true,"text xml":jQuery.parseXML,"text json":jQuery.parseJSON},load:function(h){this.log(this+".load");if(!a.url){throw (a+" requires a url")}if(this.total===null){this.log("\t total is null (will load all)")}else{this.log("\t total:",this.total)}var g=a.size;if((a.total!==null)&&(a.total<a.size)){g=a.total}a.log(a+"\t beginning recursion");f(a.start,g);function f(k,j){a.log(a+".loadHelper, start:",k,"size:",j);var i=a.buildUrl(k,j);a.log("\t url:",i);jQuery.ajax({url:a.buildUrl(k,j),converters:a.converters,dataType:"json",error:function(n,l,m){a.log("\t ajax error, status:",l,"error:",m);if(a.currentIntervalId){clearInterval(a.currentIntervalId)}$(a).trigger(ERROR_EVENT,[l,m]);a.ajaxErrorFn(n,l,m)},success:function(l){a.log("\t ajax success, response:",l,"next:",m,"remainder:",n);if(l!==null){a.data.push(l);$(a).trigger(d,[l,k,j]);var m=k+j,n=a.size;if(a.total!==null){n=Math.min(a.total-m,a.size)}a.log("\t next recursion, start:",m,"size:",n);if(a.total===null||n>0){a.currentIntervalId=setTimeout(function(){f(m,n)},a.delay);a.log("\t currentIntervalId:",a.currentIntervalId)}else{e()}}else{e()}}})}function e(){a.log(a+".loadHelper, has finished:",a.data);$(a).trigger(b,[a.data,a.total]);if(h){h(a.data)}}},toString:function(){return"LazyDataLoader"}});a.initialize(c);return a};
\ No newline at end of file
diff -r cf105e43d141b258dbf200d49bd3cce5f4d7dddc -r 487461afaba5cc7f0f6bb38397be3773cf46ce45 static/scripts/utils/LazyDataLoader.js
--- a/static/scripts/utils/LazyDataLoader.js
+++ /dev/null
@@ -1,228 +0,0 @@
-//==============================================================================
-/*
-TODO:
- ?? superclass dataloader, subclass lazydataloader??
-
-*/
-//==============================================================================
-/**
- * Object to progressively load JSON data from a REST url, delaying some time between loading chunks
- *
- * Will load size amount of data every delay ms, starting at start and ending at total.
- *
- * NOTE: Data from ajax loading is aggregated in a list, with one element for each ajax response.
- * It's up to the calling code to combine the results in a meaningful, correct way.
- *
- * example:
- * var loader = new scatterplot.LazyDataLoader({
- * //logger : console,
- * url : ( apiDatasetsURL + '/' + hda.id + '?data_type=raw_data'
- * + '&columns=[10,14]' ),
- * total : hda.metadata_data_lines,
- * size : 500,
- *
- * initialize : function( config ){
- * // ... do some stuff
- * },
- *
- * buildUrl : function( start, size ){
- * // change the formation of start, size in query string
- * return loader.url + '&' + jQuery.param({
- * start_val: start,
- * max_vals: size
- * });
- * },
- * });
- *
- * // you can use events
- * $( loader ).bind( 'error', function( event, xhr, status, error ){
- * alert( loader + ' ERROR:' + status + '\n' + error );
- * // bail out...
- * });
- * $( loader ).bind( 'loaded.new', function( event, response ){
- * console.info( 'new data available:', event, response );
- * // ... do stuff with new data
- * });
- * $( loader ).bind( 'complete', function( event, allDataArray, total ){
- * console.info( 'final load complete:', event, allDataArray, total );
- * // ... do stuff with all data
- * });
- *
- * // ...or use a callback called when all data is loaded
- * loader.load( function( dataArray ){ console.debug( 'FINISHED!', x, y, z ); } );
- */
-function LazyDataLoader( config ){
- // for now assume:
- // get, async, and params sent via url query string
- // we want json
- // we know the size of the data on the server beforehand
- var loader = this,
- // events to trigger when new or all data has been loaded
- // new batches of data (including last). Will be sent: the ajax response data, start value, and size
- LOADED_NEW_EVENT = 'loaded.new',
- // all data has been loaded: the final loader's data array and the total
- LOADED_ALL_EVENT = 'complete';
- // error from ajax
- ERROR_EVENT = 'error';
-
- jQuery.extend( loader, LoggableMixin );
- jQuery.extend( loader, {
-
- //NOTE: the next two need to be sent in config (required)
- // total size of data on server
- total : undefined,
- // url of service to get the data
- url : undefined,
-
- // holds the interval id for the current load delay
- currentIntervalId : undefined,
-
- // each load call will add an element to this array
- // it's the responsibility of the code using this to combine them properly
- data : [],
- // ms btwn recursive loads
- delay : 4000,
- // starting line, element, whatever
- start : 0,
- // size to fetch per load
- size : 4000,
-
- // loader init func: extends loader with config and calls config.init if there
- //@param {object} config : object containing variables to override (or additional)
- initialize : function( config ){
- jQuery.extend( loader, config );
-
- // call the custom initialize function if any
- // only dangerous if the user tries LazyDataLoader.prototype.init
- if( config.hasOwnProperty( 'initialize' ) ){
- config.initialize.call( loader, config );
- }
- this.log( this + ' initialized:', loader );
- },
-
- // returns query string formatted start and size (for the next fetch) appended to the loader.url
- //OVERRIDE: to change how params are passed, param names, etc.
- //@param {int} start : the line/row/datum indicating where in the dataset the next load begins
- //@param {int} size : the number of lines/rows/data to get on the next load
- buildUrl : function( start, size ){
- // currently VERY SPECIFIC to using data_providers.py start_val, max_vals params
- return this.url + '&' + jQuery.param({
- start_val: start,
- max_vals: size
- });
- },
-
- //OVERRIDE: to handle ajax errors differently
- ajaxErrorFn : function( xhr, status, error ){
- console.error( 'ERROR fetching data:', error );
- },
-
- // converters passed to the jQuery ajax call for data type parsing
- //OVERRIDE: to provide custom parsing
- converters : {
- '* text' : window.String,
- 'text html' : true,
- 'text xml' : jQuery.parseXML,
- 'text json' : jQuery.parseJSON
- },
-
- // interface to begin load (and first recursive call)
- //@param {Function} callback : function to execute when all data is loaded. callback is passed loader.data
- load : function( callback ){
- this.log( this + '.load' );
-
- // ensure necessary stuff
- if( !loader.url ){ throw( loader + ' requires a url' ); }
-
- if( this.total === null ){
- this.log( '\t total is null (will load all)' );
- } else {
- this.log( '\t total:', this.total );
- }
- //if( !loader.total ){ throw( loader + ' requires a total (total size of the data)' ); }
-
- //FIRST RECURSION: start
- var startingSize = loader.size;
- if( ( loader.total !== null ) && ( loader.total < loader.size ) ){
- startingSize = loader.total;
- }
- loader.log( loader + '\t beginning recursion' );
- loadHelper( loader.start, startingSize );
-
- //FIRST, SUBSEQUENT RECURSION function
- function loadHelper( start, size ){
- loader.log( loader + '.loadHelper, start:', start, 'size:', size );
- var url = loader.buildUrl( start, size );
- loader.log( '\t url:', url );
-
- jQuery.ajax({
- url : loader.buildUrl( start, size ),
- converters : loader.converters,
- dataType : 'json',
-
- error : function( xhr, status, error ){
- loader.log( '\t ajax error, status:', status, 'error:', error );
- if( loader.currentIntervalId ){
- clearInterval( loader.currentIntervalId );
- }
- $( loader ).trigger( ERROR_EVENT, [ status, error ] );
- loader.ajaxErrorFn( xhr, status, error );
- },
-
- success : function( response ){
- loader.log( '\t ajax success, response:', response, 'next:', next, 'remainder:', remainder );
-
- if( response !== null ){
- // store the response as is in a new element
- //TODO:?? store start, size as well?
- loader.data.push( response );
-
- //TODO: these might not be the best way to split this up
- // fire the first load event (if this is the first batch) AND partial
- $( loader ).trigger( LOADED_NEW_EVENT, [ response, start, size ] );
-
- //RECURSION:
- var next = start + size,
- remainder = loader.size;
-
- if( loader.total !== null ){
- remainder = Math.min( loader.total - next, loader.size );
- }
- loader.log( '\t next recursion, start:', next, 'size:', remainder );
-
- // if we haven't gotten everything yet, so set up for next recursive call and set the timer
- if( loader.total === null || remainder > 0 ){
- loader.currentIntervalId = setTimeout(
- function(){ loadHelper( next, remainder ); },
- loader.delay
- );
- loader.log( '\t currentIntervalId:', loader.currentIntervalId );
-
- // otherwise (base-case), don't do anything
- } else {
- loadFinished();
- }
-
- } else { //response === null --> base-case, server sez nuthin left
- loadFinished();
- }
- }
- });
- }
-
- //HANDLE BASE-CASE, LAST RECURSION
- function loadFinished(){
- loader.log( loader + '.loadHelper, has finished:', loader.data );
- $( loader ).trigger( LOADED_ALL_EVENT, [ loader.data, loader.total ] );
- if( callback ){ callback( loader.data ); }
- }
- },
-
- toString : function(){ return 'LazyDataLoader'; }
- });
-
- loader.initialize( config );
- return loader;
-}
-
-//==============================================================================
https://bitbucket.org/galaxy/galaxy-central/commits/23df5eac97f7/
Changeset: 23df5eac97f7
User: dannon
Date: 2015-02-10 14:55:03+00:00
Summary: Add more accurate sample for specifying a swift object store in object_store_conf.sample
Affected #: 1 file
diff -r 487461afaba5cc7f0f6bb38397be3773cf46ce45 -r 23df5eac97f7c05da1e06fb63a0385b1c416d535 config/object_store_conf.xml.sample
--- a/config/object_store_conf.xml.sample
+++ b/config/object_store_conf.xml.sample
@@ -20,15 +20,24 @@
<extra_dir type="temp" path="database/tmp3"/><extra_dir type="job_work" path="database/job_working_directory3"/></object_store>
+
<!-- Sample S3 Object Store
-
<object_store type="s3"><auth access_key="...." secret_key="....." /><bucket name="unique_bucket_name_all_lowercase" use_reduced_redundancy="False" /><cache path="database/files/" size="1000" /></object_store>
+ -->
- -->
+ <!-- Sample Swift Object Store
+ <object_store type="swift">
+ <auth access_key="...." secret_key="....." />
+ <bucket name="unique_bucket_name" use_reduced_redundancy="False" max_chunk_size="250"/>
+ <connection host="" port="" is_secure="" conn_path="" multipart="True"/>
+ <cache path="database/files/" size="1000" />
+ </object_store>
+ -->
+
</backends></object_store>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dannon: Merged in charles_hsu/galaxy-central/fix-multipart-upload-in-swift-backend (pull request #648)
by commits-noreply@bitbucket.org 10 Feb '15
by commits-noreply@bitbucket.org 10 Feb '15
10 Feb '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/40ab1d00a1b6/
Changeset: 40ab1d00a1b6
User: dannon
Date: 2015-02-10 14:49:01+00:00
Summary: Merged in charles_hsu/galaxy-central/fix-multipart-upload-in-swift-backend (pull request #648)
Fixed multipart-upload issue while use swift as object storage backend
Affected #: 3 files
diff -r c3eefbdaaa1ab242a1c81b65482ef2fbe943a390 -r 40ab1d00a1b6ef6749998d70cdd5bf7d8e19befa config/object_store_conf.xml.sample
--- a/config/object_store_conf.xml.sample
+++ b/config/object_store_conf.xml.sample
@@ -24,8 +24,8 @@
<object_store type="s3"><auth access_key="...." secret_key="....." />
- <bucket name="unique_bucket_name" use_reduced_redundancy="False" />
- <connection host="" port="" is_secure="" conn_path="" />
+ <bucket name="unique_bucket_name" use_reduced_redundancy="False" max_chunk_size="250"/>
+ <connection host="" port="" is_secure="" conn_path="" multipart="True"/><cache path="database/files/" size="100" /></object_store>
diff -r c3eefbdaaa1ab242a1c81b65482ef2fbe943a390 -r 40ab1d00a1b6ef6749998d70cdd5bf7d8e19befa lib/galaxy/objectstore/s3.py
--- a/lib/galaxy/objectstore/s3.py
+++ b/lib/galaxy/objectstore/s3.py
@@ -14,6 +14,7 @@
from galaxy.exceptions import ObjectNotFound
from galaxy.util import umask_fix_perms
+from galaxy.util import string_as_bool
from galaxy.util.directory_hash import directory_hash_id
from galaxy.util.sleeper import Sleeper
from .s3_multipart_upload import multipart_upload
@@ -76,7 +77,8 @@
self.secret_key = a_xml.get('secret_key')
b_xml = config_xml.findall('bucket')[0]
self.bucket = b_xml.get('name')
- self.use_rr = b_xml.get('use_reduced_redundancy', False)
+ self.use_rr= string_as_bool(b_xml.get('use_reduced_redundancy', 'False'))
+ self.max_chunk_size = int(b_xml.get('max_chunk_size', 250))
cn_xml = config_xml.findall('connection')
if not cn_xml:
cn_xml = {}
@@ -84,11 +86,24 @@
cn_xml = cn_xml[0]
self.host = cn_xml.get('host', None)
self.port = int(cn_xml.get('port', 6000))
- self.is_secure = cn_xml.get('is_secure', True)
+ self.multipart = string_as_bool(cn_xml.get('multipart', 'True'))
+ self.is_secure = string_as_bool(cn_xml.get('is_secure', 'True'))
self.conn_path = cn_xml.get('conn_path', '/')
c_xml = config_xml.findall('cache')[0]
self.cache_size = float(c_xml.get('size', -1))
self.cache_path = c_xml.get('path')
+
+ # for multipart upload
+ self.s3server = {'access_key': self.access_key,
+ 'secret_key': self.secret_key,
+ 'is_secure': self.is_secure,
+ 'max_chunk_size': self.max_chunk_size,
+ 'host': self.host,
+ 'port': self.port,
+ 'use_rr': self.use_rr,
+ 'conn_path': self.conn_path}
+
+
except Exception:
# Toss it back up after logging, we can't continue loading at this point.
log.exception("Malformed ObjectStore Configuration XML -- unable to continue")
@@ -328,14 +343,14 @@
start_time = datetime.now()
log.debug("Pushing cache file '%s' of size %s bytes to key '%s'" % (source_file, os.path.getsize(source_file), rel_path))
mb_size = os.path.getsize(source_file) / 1e6
- if mb_size < 10 or type(self) == SwiftObjectStore:
+ if mb_size < 10 or (not self.multipart):
self.transfer_progress = 0 # Reset transfer progress counter
key.set_contents_from_filename(source_file,
reduced_redundancy=self.use_rr,
cb=self._transfer_cb,
num_cb=10)
else:
- multipart_upload(self.bucket, key.name, source_file, mb_size, self.access_key, self.secret_key, use_rr=self.use_rr)
+ multipart_upload(self.s3server, self.bucket, key.name, source_file, mb_size)
end_time = datetime.now()
log.debug("Pushed cache file '%s' to key '%s' (%s bytes transfered in %s sec)" % (source_file, rel_path, os.path.getsize(source_file), end_time - start_time))
return True
diff -r c3eefbdaaa1ab242a1c81b65482ef2fbe943a390 -r 40ab1d00a1b6ef6749998d70cdd5bf7d8e19befa lib/galaxy/objectstore/s3_multipart_upload.py
--- a/lib/galaxy/objectstore/s3_multipart_upload.py
+++ b/lib/galaxy/objectstore/s3_multipart_upload.py
@@ -34,13 +34,23 @@
return wrapper
-def mp_from_ids(mp_id, mp_keyname, mp_bucketname, aws_access_key_id, aws_secret_access_key):
+def mp_from_ids(s3server, mp_id, mp_keyname, mp_bucketname):
"""Get the multipart upload from the bucket and multipart IDs.
This allows us to reconstitute a connection to the upload
from within multiprocessing functions.
"""
- conn = S3Connection(aws_access_key_id, aws_secret_access_key)
+ if s3server['host']:
+ conn = boto.connect_s3(aws_access_key_id=s3server['access_key'],
+ aws_secret_access_key=s3server['secret_key'],
+ is_secure=s3server['is_secure'],
+ host=s3server['host'],
+ port=s3server['port'],
+ calling_format=boto.s3.connection.OrdinaryCallingFormat(),
+ path=s3server['conn_path'])
+ else:
+ conn = S3Connection(s3server['access_key'], s3server['secret_key'])
+
bucket = conn.lookup(mp_bucketname)
mp = boto.s3.multipart.MultiPartUpload(bucket)
mp.key_name = mp_keyname
@@ -49,33 +59,36 @@
@map_wrap
-def transfer_part(mp_id, mp_keyname, mp_bucketname, i, part, aws_access_key_id, aws_secret_access_key):
+def transfer_part(s3server, mp_id, mp_keyname, mp_bucketname, i, part):
"""Transfer a part of a multipart upload. Designed to be run in parallel.
"""
- mp = mp_from_ids(mp_id, mp_keyname, mp_bucketname, aws_access_key_id, aws_secret_access_key)
+ mp = mp_from_ids(s3server, mp_id, mp_keyname, mp_bucketname)
with open(part) as t_handle:
mp.upload_part_from_file(t_handle, i + 1)
os.remove(part)
-def multipart_upload(bucket, s3_key_name, tarball, mb_size, aws_access_key_id, aws_secret_access_key, use_rr=True):
+def multipart_upload(s3server, bucket, s3_key_name, tarball, mb_size):
"""Upload large files using Amazon's multipart upload functionality.
"""
cores = multiprocessing.cpu_count()
def split_file(in_file, mb_size, split_num=5):
prefix = os.path.join(os.path.dirname(in_file),
- "%sS3PART" % (os.path.basename(s3_key_name)))
- # Split chunks so they are 5MB < chunk < 250MB
- split_size = int(max(min(mb_size / (split_num * 2.0), 250), 5))
+ "%sS3PART" % (os.path.basename(s3_key_name)))
+ max_chunk = s3server['max_chunk_size']
+ # Split chunks so they are 5MB < chunk < 250MB(max_chunk_size)
+ split_size = int(max(min(mb_size / (split_num * 2.0), max_chunk), 5))
if not os.path.exists("%saa" % prefix):
cl = ["split", "-b%sm" % split_size, in_file, prefix]
subprocess.check_call(cl)
return sorted(glob.glob("%s*" % prefix))
- mp = bucket.initiate_multipart_upload(s3_key_name, reduced_redundancy=use_rr)
+ mp = bucket.initiate_multipart_upload(s3_key_name,
+ reduced_redundancy=s3server['use_rr'])
+
with multimap(cores) as pmap:
- for _ in pmap(transfer_part, ((mp.id, mp.key_name, mp.bucket_name, i, part, aws_access_key_id, aws_secret_access_key)
+ for _ in pmap(transfer_part, ((s3server, mp.id, mp.key_name, mp.bucket_name, i, part)
for (i, part) in
enumerate(split_file(tarball, mb_size, cores)))):
pass
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
4 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9afda176f5df/
Changeset: 9afda176f5df
Branch: fix-multipart-upload-in-swift-backend
User: charles_hsu
Date: 2015-01-27 06:17:30+00:00
Summary: Fix type of in_secure(should be boolean, not string).
---
lib/galaxy/objectstore/s3.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
Affected #: 1 file
diff -r 1096077cabbd4046b7da9ce45cecf1151b7ebc75 -r 9afda176f5df5857100759eb3184e884a6e3bb80 lib/galaxy/objectstore/s3.py
--- a/lib/galaxy/objectstore/s3.py
+++ b/lib/galaxy/objectstore/s3.py
@@ -84,7 +84,8 @@
cn_xml = cn_xml[0]
self.host = cn_xml.get('host', None)
self.port = int(cn_xml.get('port', 6000))
- self.is_secure = cn_xml.get('is_secure', True)
+ self.is_secure = {'true': True,
+ 'false': False}.get(cn_xml.get('is_secure', 'True').lower())
self.conn_path = cn_xml.get('conn_path', '/')
c_xml = config_xml.findall('cache')[0]
self.cache_size = float(c_xml.get('size', -1))
https://bitbucket.org/galaxy/galaxy-central/commits/f69c2f6c7ef1/
Changeset: f69c2f6c7ef1
Branch: fix-multipart-upload-in-swift-backend
User: charles_hsu
Date: 2015-01-27 06:17:45+00:00
Summary: Fixed cannot use multipart-upload for 'swift' backend with swift3 middleware.
Add two options('multipart' and 'max_chunk_size').
---
config/object_store_conf.xml.sample | 4 +--
lib/galaxy/objectstore/s3.py | 22 ++++++++++++++---
lib/galaxy/objectstore/s3_multipart_upload.py | 33 +++++++++++++++++--------
3 files changed, 44 insertions(+), 15 deletions(-)
Affected #: 3 files
diff -r 9afda176f5df5857100759eb3184e884a6e3bb80 -r f69c2f6c7ef176f4a6c9251c486649eb56585dbb config/object_store_conf.xml.sample
--- a/config/object_store_conf.xml.sample
+++ b/config/object_store_conf.xml.sample
@@ -24,8 +24,8 @@
<object_store type="s3"><auth access_key="...." secret_key="....." />
- <bucket name="unique_bucket_name" use_reduced_redundancy="False" />
- <connection host="" port="" is_secure="" conn_path="" />
+ <bucket name="unique_bucket_name" use_reduced_redundancy="False" max_chunk_size="250"/>
+ <connection host="" port="" is_secure="" conn_path="" multipart="True"/><cache path="database/files/" size="100" /></object_store>
diff -r 9afda176f5df5857100759eb3184e884a6e3bb80 -r f69c2f6c7ef176f4a6c9251c486649eb56585dbb lib/galaxy/objectstore/s3.py
--- a/lib/galaxy/objectstore/s3.py
+++ b/lib/galaxy/objectstore/s3.py
@@ -76,7 +76,9 @@
self.secret_key = a_xml.get('secret_key')
b_xml = config_xml.findall('bucket')[0]
self.bucket = b_xml.get('name')
- self.use_rr = b_xml.get('use_reduced_redundancy', False)
+ self.use_rr= {'true': True,
+ 'false': False}.get(b_xml.get('use_reduced_redundancy', 'False').lower())
+ self.max_chunk_size = int(b_xml.get('max_chunk_size', 250))
cn_xml = config_xml.findall('connection')
if not cn_xml:
cn_xml = {}
@@ -84,12 +86,26 @@
cn_xml = cn_xml[0]
self.host = cn_xml.get('host', None)
self.port = int(cn_xml.get('port', 6000))
+ self.multipart = {'true': True,
+ 'false': False}.get(cn_xml.get('multipart', 'True').lower())
self.is_secure = {'true': True,
'false': False}.get(cn_xml.get('is_secure', 'True').lower())
self.conn_path = cn_xml.get('conn_path', '/')
c_xml = config_xml.findall('cache')[0]
self.cache_size = float(c_xml.get('size', -1))
self.cache_path = c_xml.get('path')
+
+ # for multipart upload
+ self.s3server = {'access_key': self.access_key,
+ 'secret_key': self.secret_key,
+ 'is_secure': self.is_secure,
+ 'max_chunk_size': self.max_chunk_size,
+ 'host': self.host,
+ 'port': self.port,
+ 'use_rr': self.use_rr,
+ 'conn_path': self.conn_path}
+
+
except Exception:
# Toss it back up after logging, we can't continue loading at this point.
log.exception("Malformed ObjectStore Configuration XML -- unable to continue")
@@ -329,14 +345,14 @@
start_time = datetime.now()
log.debug("Pushing cache file '%s' of size %s bytes to key '%s'" % (source_file, os.path.getsize(source_file), rel_path))
mb_size = os.path.getsize(source_file) / 1e6
- if mb_size < 10 or type(self) == SwiftObjectStore:
+ if mb_size < 10 or (not self.multipart):
self.transfer_progress = 0 # Reset transfer progress counter
key.set_contents_from_filename(source_file,
reduced_redundancy=self.use_rr,
cb=self._transfer_cb,
num_cb=10)
else:
- multipart_upload(self.bucket, key.name, source_file, mb_size, self.access_key, self.secret_key, use_rr=self.use_rr)
+ multipart_upload(self.s3server, self.bucket, key.name, source_file, mb_size)
end_time = datetime.now()
log.debug("Pushed cache file '%s' to key '%s' (%s bytes transfered in %s sec)" % (source_file, rel_path, os.path.getsize(source_file), end_time - start_time))
return True
diff -r 9afda176f5df5857100759eb3184e884a6e3bb80 -r f69c2f6c7ef176f4a6c9251c486649eb56585dbb lib/galaxy/objectstore/s3_multipart_upload.py
--- a/lib/galaxy/objectstore/s3_multipart_upload.py
+++ b/lib/galaxy/objectstore/s3_multipart_upload.py
@@ -34,13 +34,23 @@
return wrapper
-def mp_from_ids(mp_id, mp_keyname, mp_bucketname, aws_access_key_id, aws_secret_access_key):
+def mp_from_ids(s3server, mp_id, mp_keyname, mp_bucketname):
"""Get the multipart upload from the bucket and multipart IDs.
This allows us to reconstitute a connection to the upload
from within multiprocessing functions.
"""
- conn = S3Connection(aws_access_key_id, aws_secret_access_key)
+ if s3server['host']:
+ conn = boto.connect_s3(aws_access_key_id=s3server['access_key'],
+ aws_secret_access_key=s3server['secret_key'],
+ is_secure=s3server['is_secure'],
+ host=s3server['host'],
+ port=s3server['port'],
+ calling_format=boto.s3.connection.OrdinaryCallingFormat(),
+ path=s3server['conn_path'])
+ else:
+ conn = S3Connection(s3server['access_key'], s3server['secret_key'])
+
bucket = conn.lookup(mp_bucketname)
mp = boto.s3.multipart.MultiPartUpload(bucket)
mp.key_name = mp_keyname
@@ -49,33 +59,36 @@
@map_wrap
-def transfer_part(mp_id, mp_keyname, mp_bucketname, i, part, aws_access_key_id, aws_secret_access_key):
+def transfer_part(s3server, mp_id, mp_keyname, mp_bucketname, i, part):
"""Transfer a part of a multipart upload. Designed to be run in parallel.
"""
- mp = mp_from_ids(mp_id, mp_keyname, mp_bucketname, aws_access_key_id, aws_secret_access_key)
+ mp = mp_from_ids(s3server, mp_id, mp_keyname, mp_bucketname)
with open(part) as t_handle:
mp.upload_part_from_file(t_handle, i + 1)
os.remove(part)
-def multipart_upload(bucket, s3_key_name, tarball, mb_size, aws_access_key_id, aws_secret_access_key, use_rr=True):
+def multipart_upload(s3server, bucket, s3_key_name, tarball, mb_size):
"""Upload large files using Amazon's multipart upload functionality.
"""
cores = multiprocessing.cpu_count()
def split_file(in_file, mb_size, split_num=5):
prefix = os.path.join(os.path.dirname(in_file),
- "%sS3PART" % (os.path.basename(s3_key_name)))
- # Split chunks so they are 5MB < chunk < 250MB
- split_size = int(max(min(mb_size / (split_num * 2.0), 250), 5))
+ "%sS3PART" % (os.path.basename(s3_key_name)))
+ max_chunk = s3server['max_chunk_size']
+ # Split chunks so they are 5MB < chunk < 250MB(max_chunk_size)
+ split_size = int(max(min(mb_size / (split_num * 2.0), max_chunk), 5))
if not os.path.exists("%saa" % prefix):
cl = ["split", "-b%sm" % split_size, in_file, prefix]
subprocess.check_call(cl)
return sorted(glob.glob("%s*" % prefix))
- mp = bucket.initiate_multipart_upload(s3_key_name, reduced_redundancy=use_rr)
+ mp = bucket.initiate_multipart_upload(s3_key_name,
+ reduced_redundancy=s3server['use_rr'])
+
with multimap(cores) as pmap:
- for _ in pmap(transfer_part, ((mp.id, mp.key_name, mp.bucket_name, i, part, aws_access_key_id, aws_secret_access_key)
+ for _ in pmap(transfer_part, ((s3server, mp.id, mp.key_name, mp.bucket_name, i, part)
for (i, part) in
enumerate(split_file(tarball, mb_size, cores)))):
pass
https://bitbucket.org/galaxy/galaxy-central/commits/6c24937ea01e/
Changeset: 6c24937ea01e
Branch: fix-multipart-upload-in-swift-backend
User: charles_hsu
Date: 2015-01-27 15:13:55+00:00
Summary: Use string_as_bool().
---
lib/galaxy/objectstore/s3.py | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
Affected #: 1 file
diff -r f69c2f6c7ef176f4a6c9251c486649eb56585dbb -r 6c24937ea01ee68dc453ad946bbd3b2ce66d83e5 lib/galaxy/objectstore/s3.py
--- a/lib/galaxy/objectstore/s3.py
+++ b/lib/galaxy/objectstore/s3.py
@@ -14,6 +14,7 @@
from galaxy.exceptions import ObjectNotFound
from galaxy.util import umask_fix_perms
+from galaxy.util import string_as_bool
from galaxy.util.directory_hash import directory_hash_id
from galaxy.util.sleeper import Sleeper
from .s3_multipart_upload import multipart_upload
@@ -76,8 +77,7 @@
self.secret_key = a_xml.get('secret_key')
b_xml = config_xml.findall('bucket')[0]
self.bucket = b_xml.get('name')
- self.use_rr= {'true': True,
- 'false': False}.get(b_xml.get('use_reduced_redundancy', 'False').lower())
+ self.use_rr= string_as_bool(b_xml.get('use_reduced_redundancy', 'False'))
self.max_chunk_size = int(b_xml.get('max_chunk_size', 250))
cn_xml = config_xml.findall('connection')
if not cn_xml:
@@ -86,10 +86,8 @@
cn_xml = cn_xml[0]
self.host = cn_xml.get('host', None)
self.port = int(cn_xml.get('port', 6000))
- self.multipart = {'true': True,
- 'false': False}.get(cn_xml.get('multipart', 'True').lower())
- self.is_secure = {'true': True,
- 'false': False}.get(cn_xml.get('is_secure', 'True').lower())
+ self.multipart = string_as_bool(cn_xml.get('multipart', 'True'))
+ self.is_secure = string_as_bool(cn_xml.get('is_secure', 'True'))
self.conn_path = cn_xml.get('conn_path', '/')
c_xml = config_xml.findall('cache')[0]
self.cache_size = float(c_xml.get('size', -1))
https://bitbucket.org/galaxy/galaxy-central/commits/40ab1d00a1b6/
Changeset: 40ab1d00a1b6
User: dannon
Date: 2015-02-10 14:49:01+00:00
Summary: Merged in charles_hsu/galaxy-central/fix-multipart-upload-in-swift-backend (pull request #648)
Fixed multipart-upload issue while use swift as object storage backend
Affected #: 3 files
diff -r c3eefbdaaa1ab242a1c81b65482ef2fbe943a390 -r 40ab1d00a1b6ef6749998d70cdd5bf7d8e19befa config/object_store_conf.xml.sample
--- a/config/object_store_conf.xml.sample
+++ b/config/object_store_conf.xml.sample
@@ -24,8 +24,8 @@
<object_store type="s3"><auth access_key="...." secret_key="....." />
- <bucket name="unique_bucket_name" use_reduced_redundancy="False" />
- <connection host="" port="" is_secure="" conn_path="" />
+ <bucket name="unique_bucket_name" use_reduced_redundancy="False" max_chunk_size="250"/>
+ <connection host="" port="" is_secure="" conn_path="" multipart="True"/><cache path="database/files/" size="100" /></object_store>
diff -r c3eefbdaaa1ab242a1c81b65482ef2fbe943a390 -r 40ab1d00a1b6ef6749998d70cdd5bf7d8e19befa lib/galaxy/objectstore/s3.py
--- a/lib/galaxy/objectstore/s3.py
+++ b/lib/galaxy/objectstore/s3.py
@@ -14,6 +14,7 @@
from galaxy.exceptions import ObjectNotFound
from galaxy.util import umask_fix_perms
+from galaxy.util import string_as_bool
from galaxy.util.directory_hash import directory_hash_id
from galaxy.util.sleeper import Sleeper
from .s3_multipart_upload import multipart_upload
@@ -76,7 +77,8 @@
self.secret_key = a_xml.get('secret_key')
b_xml = config_xml.findall('bucket')[0]
self.bucket = b_xml.get('name')
- self.use_rr = b_xml.get('use_reduced_redundancy', False)
+ self.use_rr= string_as_bool(b_xml.get('use_reduced_redundancy', 'False'))
+ self.max_chunk_size = int(b_xml.get('max_chunk_size', 250))
cn_xml = config_xml.findall('connection')
if not cn_xml:
cn_xml = {}
@@ -84,11 +86,24 @@
cn_xml = cn_xml[0]
self.host = cn_xml.get('host', None)
self.port = int(cn_xml.get('port', 6000))
- self.is_secure = cn_xml.get('is_secure', True)
+ self.multipart = string_as_bool(cn_xml.get('multipart', 'True'))
+ self.is_secure = string_as_bool(cn_xml.get('is_secure', 'True'))
self.conn_path = cn_xml.get('conn_path', '/')
c_xml = config_xml.findall('cache')[0]
self.cache_size = float(c_xml.get('size', -1))
self.cache_path = c_xml.get('path')
+
+ # for multipart upload
+ self.s3server = {'access_key': self.access_key,
+ 'secret_key': self.secret_key,
+ 'is_secure': self.is_secure,
+ 'max_chunk_size': self.max_chunk_size,
+ 'host': self.host,
+ 'port': self.port,
+ 'use_rr': self.use_rr,
+ 'conn_path': self.conn_path}
+
+
except Exception:
# Toss it back up after logging, we can't continue loading at this point.
log.exception("Malformed ObjectStore Configuration XML -- unable to continue")
@@ -328,14 +343,14 @@
start_time = datetime.now()
log.debug("Pushing cache file '%s' of size %s bytes to key '%s'" % (source_file, os.path.getsize(source_file), rel_path))
mb_size = os.path.getsize(source_file) / 1e6
- if mb_size < 10 or type(self) == SwiftObjectStore:
+ if mb_size < 10 or (not self.multipart):
self.transfer_progress = 0 # Reset transfer progress counter
key.set_contents_from_filename(source_file,
reduced_redundancy=self.use_rr,
cb=self._transfer_cb,
num_cb=10)
else:
- multipart_upload(self.bucket, key.name, source_file, mb_size, self.access_key, self.secret_key, use_rr=self.use_rr)
+ multipart_upload(self.s3server, self.bucket, key.name, source_file, mb_size)
end_time = datetime.now()
log.debug("Pushed cache file '%s' to key '%s' (%s bytes transfered in %s sec)" % (source_file, rel_path, os.path.getsize(source_file), end_time - start_time))
return True
diff -r c3eefbdaaa1ab242a1c81b65482ef2fbe943a390 -r 40ab1d00a1b6ef6749998d70cdd5bf7d8e19befa lib/galaxy/objectstore/s3_multipart_upload.py
--- a/lib/galaxy/objectstore/s3_multipart_upload.py
+++ b/lib/galaxy/objectstore/s3_multipart_upload.py
@@ -34,13 +34,23 @@
return wrapper
-def mp_from_ids(mp_id, mp_keyname, mp_bucketname, aws_access_key_id, aws_secret_access_key):
+def mp_from_ids(s3server, mp_id, mp_keyname, mp_bucketname):
"""Get the multipart upload from the bucket and multipart IDs.
This allows us to reconstitute a connection to the upload
from within multiprocessing functions.
"""
- conn = S3Connection(aws_access_key_id, aws_secret_access_key)
+ if s3server['host']:
+ conn = boto.connect_s3(aws_access_key_id=s3server['access_key'],
+ aws_secret_access_key=s3server['secret_key'],
+ is_secure=s3server['is_secure'],
+ host=s3server['host'],
+ port=s3server['port'],
+ calling_format=boto.s3.connection.OrdinaryCallingFormat(),
+ path=s3server['conn_path'])
+ else:
+ conn = S3Connection(s3server['access_key'], s3server['secret_key'])
+
bucket = conn.lookup(mp_bucketname)
mp = boto.s3.multipart.MultiPartUpload(bucket)
mp.key_name = mp_keyname
@@ -49,33 +59,36 @@
@map_wrap
-def transfer_part(mp_id, mp_keyname, mp_bucketname, i, part, aws_access_key_id, aws_secret_access_key):
+def transfer_part(s3server, mp_id, mp_keyname, mp_bucketname, i, part):
"""Transfer a part of a multipart upload. Designed to be run in parallel.
"""
- mp = mp_from_ids(mp_id, mp_keyname, mp_bucketname, aws_access_key_id, aws_secret_access_key)
+ mp = mp_from_ids(s3server, mp_id, mp_keyname, mp_bucketname)
with open(part) as t_handle:
mp.upload_part_from_file(t_handle, i + 1)
os.remove(part)
-def multipart_upload(bucket, s3_key_name, tarball, mb_size, aws_access_key_id, aws_secret_access_key, use_rr=True):
+def multipart_upload(s3server, bucket, s3_key_name, tarball, mb_size):
"""Upload large files using Amazon's multipart upload functionality.
"""
cores = multiprocessing.cpu_count()
def split_file(in_file, mb_size, split_num=5):
prefix = os.path.join(os.path.dirname(in_file),
- "%sS3PART" % (os.path.basename(s3_key_name)))
- # Split chunks so they are 5MB < chunk < 250MB
- split_size = int(max(min(mb_size / (split_num * 2.0), 250), 5))
+ "%sS3PART" % (os.path.basename(s3_key_name)))
+ max_chunk = s3server['max_chunk_size']
+ # Split chunks so they are 5MB < chunk < 250MB(max_chunk_size)
+ split_size = int(max(min(mb_size / (split_num * 2.0), max_chunk), 5))
if not os.path.exists("%saa" % prefix):
cl = ["split", "-b%sm" % split_size, in_file, prefix]
subprocess.check_call(cl)
return sorted(glob.glob("%s*" % prefix))
- mp = bucket.initiate_multipart_upload(s3_key_name, reduced_redundancy=use_rr)
+ mp = bucket.initiate_multipart_upload(s3_key_name,
+ reduced_redundancy=s3server['use_rr'])
+
with multimap(cores) as pmap:
- for _ in pmap(transfer_part, ((mp.id, mp.key_name, mp.bucket_name, i, part, aws_access_key_id, aws_secret_access_key)
+ for _ in pmap(transfer_part, ((s3server, mp.id, mp.key_name, mp.bucket_name, i, part)
for (i, part) in
enumerate(split_file(tarball, mb_size, cores)))):
pass
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: UI, Paired collection creator: use scoped version of $.index instead of clumsy calculation
by commits-noreply@bitbucket.org 09 Feb '15
by commits-noreply@bitbucket.org 09 Feb '15
09 Feb '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c3eefbdaaa1a/
Changeset: c3eefbdaaa1a
User: carlfeberhard
Date: 2015-02-09 23:09:27+00:00
Summary: UI, Paired collection creator: use scoped version of $.index instead of clumsy calculation
Affected #: 3 files
diff -r 3764ca243a9366a8f7ccd9403ef7bc7df45cc4ae -r c3eefbdaaa1ab242a1c81b65482ef2fbe943a390 client/galaxy/scripts/mvc/collection/paired-collection-creator.js
--- a/client/galaxy/scripts/mvc/collection/paired-collection-creator.js
+++ b/client/galaxy/scripts/mvc/collection/paired-collection-creator.js
@@ -1307,8 +1307,10 @@
/** rename a pair when the pair name is clicked */
_clickPairName : function( ev ){
ev.stopPropagation();
- var $control = $( ev.currentTarget ),
- pair = this.paired[ $control.parent().parent().index() / 2 ],
+ 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 );
if( response ){
pair.name = response;
@@ -1316,7 +1318,7 @@
// when adding/removing extensions
//TODO: kinda hacky
pair.customizedName = true;
- $control.text( pair.name );
+ $name.text( pair.name );
}
},
@@ -1324,7 +1326,7 @@
_clickUnpair : function( ev ){
//if( !ev.currentTarget ){ return true; }
//TODO: this is a hack bc each paired rev now has two elems (dataset, button)
- var pairIndex = Math.floor( $( ev.currentTarget ).index() / 2 );
+ var pairIndex = Math.floor( $( ev.currentTarget ).index( '.unpair-btn' ) );
//this.debug( 'pair:', pairIndex );
//TODO: animate
this._unpair( this.paired[ pairIndex ] );
diff -r 3764ca243a9366a8f7ccd9403ef7bc7df45cc4ae -r c3eefbdaaa1ab242a1c81b65482ef2fbe943a390 static/scripts/mvc/collection/paired-collection-creator.js
--- a/static/scripts/mvc/collection/paired-collection-creator.js
+++ b/static/scripts/mvc/collection/paired-collection-creator.js
@@ -1307,8 +1307,10 @@
/** rename a pair when the pair name is clicked */
_clickPairName : function( ev ){
ev.stopPropagation();
- var $control = $( ev.currentTarget ),
- pair = this.paired[ $control.parent().parent().index() / 2 ],
+ 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 );
if( response ){
pair.name = response;
@@ -1316,7 +1318,7 @@
// when adding/removing extensions
//TODO: kinda hacky
pair.customizedName = true;
- $control.text( pair.name );
+ $name.text( pair.name );
}
},
@@ -1324,7 +1326,7 @@
_clickUnpair : function( ev ){
//if( !ev.currentTarget ){ return true; }
//TODO: this is a hack bc each paired rev now has two elems (dataset, button)
- var pairIndex = Math.floor( $( ev.currentTarget ).index() / 2 );
+ var pairIndex = Math.floor( $( ev.currentTarget ).index( '.unpair-btn' ) );
//this.debug( 'pair:', pairIndex );
//TODO: animate
this._unpair( this.paired[ pairIndex ] );
diff -r 3764ca243a9366a8f7ccd9403ef7bc7df45cc4ae -r c3eefbdaaa1ab242a1c81b65482ef2fbe943a390 static/scripts/packed/mvc/collection/paired-collection-creator.js
--- a/static/scripts/packed/mvc/collection/paired-collection-creator.js
+++ b/static/scripts/packed/mvc/collection/paired-collection-creator.js
@@ -1,1 +1,1 @@
-define(["utils/levenshtein","mvc/base-mvc","utils/localization"],function(g,a,d){var f=Backbone.View.extend(a.LoggableMixin).extend({tagName:"li",className:"dataset paired",initialize:function(h){this.pair=h.pair||{}},template:_.template(['<span class="forward-dataset-name flex-column"><%= pair.forward.name %></span>','<span class="pair-name-column flex-column">','<span class="pair-name"><%= pair.name %></span>',"</span>",'<span class="reverse-dataset-name flex-column"><%= pair.reverse.name %></span>'].join("")),render:function(){this.$el.attr("draggable",true).data("pair",this.pair).html(this.template({pair:this.pair})).addClass("flex-column-container");return this},events:{dragstart:"_dragstart",dragend:"_dragend",dragover:"_sendToParent",drop:"_sendToParent"},_dragstart:function(h){h.currentTarget.style.opacity="0.4";if(h.originalEvent){h=h.originalEvent}h.dataTransfer.effectAllowed="move";h.dataTransfer.setData("text/plain",JSON.stringify(this.pair));this.$el.parent().trigger("pair.dragstart",[this])},_dragend:function(h){h.currentTarget.style.opacity="1.0";this.$el.parent().trigger("pair.dragend",[this])},_sendToParent:function(h){this.$el.parent().trigger(h)},toString:function(){return"PairView("+this.pair.name+")"}});var e=Backbone.View.extend(a.LoggableMixin).extend({className:"collection-creator flex-row-container",initialize:function(h){h=_.defaults(h,{datasets:[],filters:this.DEFAULT_FILTERS,automaticallyPair:true,matchPercentage:1,strategy:"lcs"});this.initialList=h.datasets;this.historyId=h.historyId;this.filters=this.commonFilters[h.filters]||this.commonFilters[this.DEFAULT_FILTERS];if(_.isArray(h.filters)){this.filters=h.filters}this.automaticallyPair=h.automaticallyPair;this.matchPercentage=h.matchPercentage;this.strategy=this.strategies[h.strategy]||this.strategies[this.DEFAULT_STRATEGY];if(_.isFunction(h.strategy)){this.strategy=h.strategy}this.removeExtensions=true;this.oncancel=h.oncancel;this.oncreate=h.oncreate;this.autoscrollDist=h.autoscrollDist||24;this.unpairedPanelHidden=false;this.pairedPanelHidden=false;this.$dragging=null;this._setUpBehaviors();this._dataSetUp()},commonFilters:{none:["",""],illumina:["_1","_2"]},DEFAULT_FILTERS:"illumina",strategies:{lcs:"autoPairLCSs",levenshtein:"autoPairLevenshtein"},DEFAULT_STRATEGY:"lcs",_dataSetUp:function(){this.paired=[];this.unpaired=[];this.selectedIds=[];this._sortInitialList();this._ensureIds();this.unpaired=this.initialList.slice(0);if(this.automaticallyPair){this.autoPair();this.once("rendered:initial",function(){this.trigger("autopair")})}},_sortInitialList:function(){this._sortDatasetList(this.initialList)},_sortDatasetList:function(h){h.sort(function(j,i){return naturalSort(j.name,i.name)});return h},_ensureIds:function(){this.initialList.forEach(function(h){if(!h.hasOwnProperty("id")){h.id=_.uniqueId()}});return this.initialList},_splitByFilters:function(j){var i=[],h=[];this.unpaired.forEach(function(k){if(this._filterFwdFn(k)){i.push(k)}if(this._filterRevFn(k)){h.push(k)}}.bind(this));return[i,h]},_filterFwdFn:function(i){var h=new RegExp(this.filters[0]);return h.test(i.name)},_filterRevFn:function(i){var h=new RegExp(this.filters[1]);return h.test(i.name)},_addToUnpaired:function(i){var h=function(j,l){if(j===l){return j}var k=Math.floor((l-j)/2)+j,m=naturalSort(i.name,this.unpaired[k].name);if(m<0){return h(j,k)}else{if(m>0){return h(k+1,l)}}while(this.unpaired[k]&&this.unpaired[k].name===i.name){k++}return k}.bind(this);this.unpaired.splice(h(0,this.unpaired.length),0,i)},autoPair:function(i){i=i||this.strategy;var h=this.simpleAutoPair();h=h.concat(this[i].call(this));return h},simpleAutoPair:function(){var o=0,m,s=this._splitByFilters(),h=s[0],r=s[1],q,u,k=false,t=[];while(o<h.length){var n=h[o];q=n.name.replace(this.filters[0],"");k=false;for(m=0;m<r.length;m++){var p=r[m];u=p.name.replace(this.filters[1],"");if(n!==p&&q===u){k=true;var l=this._pair(h.splice(o,1)[0],r.splice(m,1)[0],{silent:true});t.push(l);break}}if(!k){o+=1}}return t},autoPairLevenshtein:function(){var p=0,n,u=this._splitByFilters(),h=u[0],s=u[1],r,x,k,t,l,v=[];while(p<h.length){var o=h[p];r=o.name.replace(this.filters[0],"");l=Number.MAX_VALUE;for(n=0;n<s.length;n++){var q=s[n];x=q.name.replace(this.filters[1],"");if(o!==q){if(r===x){t=n;l=0;break}k=levenshteinDistance(r,x);if(k<l){t=n;l=k}}}var w=1-(l/(Math.max(r.length,x.length)));if(w>=this.matchPercentage){var m=this._pair(h.splice(p,1)[0],s.splice(t,1)[0],{silent:true});v.push(m);if(h.length<=0||s.length<=0){return v}}else{p+=1}}return v},autoPairLCSs:function(){var n=0,l,u=this._splitByFilters(),h=u[0],s=u[1],r,y,x,t,p,v=[];if(!h.length||!s.length){return v}while(n<h.length){var m=h[n];r=m.name.replace(this.filters[0],"");p=0;for(l=0;l<s.length;l++){var q=s[l];y=q.name.replace(this.filters[1],"");if(m!==q){if(r===y){t=l;p=r.length;break}var o=this._naiveStartingAndEndingLCS(r,y);x=o.length;if(x>p){t=l;p=x}}}var w=p/(Math.min(r.length,y.length));if(w>=this.matchPercentage){var k=this._pair(h.splice(n,1)[0],s.splice(t,1)[0],{silent:true});v.push(k);if(h.length<=0||s.length<=0){return v}}else{n+=1}}return v},_naiveStartingAndEndingLCS:function(m,k){var n="",o="",l=0,h=0;while(l<m.length&&l<k.length){if(m[l]!==k[l]){break}n+=m[l];l+=1}if(l===m.length){return m}if(l===k.length){return k}l=(m.length-1);h=(k.length-1);while(l>=0&&h>=0){if(m[l]!==k[h]){break}o=[m[l],o].join("");l-=1;h-=1}return n+o},_pair:function(j,h,i){i=i||{};var k=this._createPair(j,h,i.name);this.paired.push(k);this.unpaired=_.without(this.unpaired,j,h);if(!i.silent){this.trigger("pair:new",k)}return k},_createPair:function(j,h,i){if(!(j&&h)||(j===h)){throw new Error("Bad pairing: "+[JSON.stringify(j),JSON.stringify(h)])}i=i||this._guessNameForPair(j,h);return{forward:j,name:i,reverse:h}},_guessNameForPair:function(j,h,k){k=(k!==undefined)?(k):(this.removeExtensions);var i=this._naiveStartingAndEndingLCS(j.name.replace(this.filters[0],""),h.name.replace(this.filters[1],""));if(k){var l=i.lastIndexOf(".");if(l>0){i=i.slice(0,l)}}return i||(j.name+" & "+h.name)},_unpair:function(i,h){h=h||{};if(!i){throw new Error("Bad pair: "+JSON.stringify(i))}this.paired=_.without(this.paired,i);this._addToUnpaired(i.forward);this._addToUnpaired(i.reverse);if(!h.silent){this.trigger("pair:unpair",[i])}return i},unpairAll:function(){var h=[];while(this.paired.length){h.push(this._unpair(this.paired[0],{silent:true}))}this.trigger("pair:unpair",h)},_pairToJSON:function(h){return{collection_type:"paired",src:"new_collection",name:h.name,element_identifiers:[{name:"forward",id:h.forward.id,src:"hda"},{name:"reverse",id:h.reverse.id,src:"hda"}]}},createList:function(){var j=this,i;if(j.historyId){i="/api/histories/"+this.historyId+"/contents/dataset_collections"}var h={type:"dataset_collection",collection_type:"list:paired",name:_.escape(j.$(".collection-name").val()),element_identifiers:j.paired.map(function(k){return j._pairToJSON(k)})};return jQuery.ajax(i,{type:"POST",contentType:"application/json",dataType:"json",data:JSON.stringify(h)}).fail(function(m,k,l){j._ajaxErrHandler(m,k,l)}).done(function(k,l,m){j.trigger("collection:created",k,l,m);if(typeof j.oncreate==="function"){j.oncreate.call(this,k,l,m)}})},_ajaxErrHandler:function(k,h,j){this.error(k,h,j);var i=d("An error occurred while creating this collection");if(k){if(k.readyState===0&&k.status===0){i+=": "+d("Galaxy could not be reached and may be updating.")+d(" Try again in a few minutes.")}else{if(k.responseJSON){i+="<br /><pre>"+JSON.stringify(k.responseJSON)+"</pre>"}else{i+=": "+j}}}creator._showAlert(i,"alert-danger")},render:function(h,i){this.$el.empty().html(e.templates.main());this._renderHeader(h);this._renderMiddle(h);this._renderFooter(h);this._addPluginComponents();this.trigger("rendered",this);return this},_renderHeader:function(i,j){var h=this.$(".header").empty().html(e.templates.header()).find(".help-content").prepend($(e.templates.helpContent()));this._renderFilters();return h},_renderFilters:function(){return this.$(".forward-column .column-header input").val(this.filters[0]).add(this.$(".reverse-column .column-header input").val(this.filters[1]))},_renderMiddle:function(i,j){var h=this.$(".middle").empty().html(e.templates.middle());if(this.unpairedPanelHidden){this.$(".unpaired-columns").hide()}else{if(this.pairedPanelHidden){this.$(".paired-columns").hide()}}this._renderUnpaired();this._renderPaired();return h},_renderUnpaired:function(m,n){var k=this,l,i,h=[],j=this._splitByFilters();this.$(".forward-column .title").text([j[0].length,d("unpaired forward")].join(" "));this.$(".forward-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[0].length));this.$(".reverse-column .title").text([j[1].length,d("unpaired reverse")].join(" "));this.$(".reverse-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[1].length));this.$(".unpaired-columns .column-datasets").empty();this.$(".autopair-link").toggle(this.unpaired.length!==0);if(this.unpaired.length===0){this._renderUnpairedEmpty();return}i=j[1].map(function(p,o){if((j[0][o]!==undefined)&&(j[0][o]!==p)){h.push(k._renderPairButton())}return k._renderUnpairedDataset(p)});l=j[0].map(function(o){return k._renderUnpairedDataset(o)});if(!l.length&&!i.length){this._renderUnpairedNotShown();return}this.$(".unpaired-columns .forward-column .column-datasets").append(l).add(this.$(".unpaired-columns .paired-column .column-datasets").append(h)).add(this.$(".unpaired-columns .reverse-column .column-datasets").append(i));this._adjUnpairedOnScrollbar()},_renderUnpairedDisplayStr:function(h){return["(",h," ",d("filtered out"),")"].join("")},_renderUnpairedDataset:function(h){return $("<li/>").attr("id","dataset-"+h.id).addClass("dataset unpaired").attr("draggable",true).addClass(h.selected?"selected":"").append($("<span/>").addClass("dataset-name").text(h.name)).data("dataset",h)},_renderPairButton:function(){return $("<li/>").addClass("dataset unpaired").append($("<span/>").addClass("dataset-name").text(d("Pair these datasets")))},_renderUnpairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no remaining unpaired datasets")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_renderUnpairedNotShown:function(){var h=$('<div class="empty-message"></div>').text("("+d("no datasets were found matching the current filters")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_adjUnpairedOnScrollbar:function(){var k=this.$(".unpaired-columns").last(),l=this.$(".unpaired-columns .reverse-column .dataset").first();if(!l.size()){return}var h=k.offset().left+k.outerWidth(),j=l.offset().left+l.outerWidth(),i=Math.floor(h)-Math.floor(j);this.$(".unpaired-columns .forward-column").css("margin-left",(i>0)?i:0)},_renderPaired:function(i,j){this.$(".paired-column-title .title").text([this.paired.length,d("paired")].join(" "));this.$(".unpair-all-link").toggle(this.paired.length!==0);if(this.paired.length===0){this._renderPairedEmpty();return}else{this.$(".remove-extensions-link").show()}this.$(".paired-columns .column-datasets").empty();var h=this;this.paired.forEach(function(m,k){var l=new f({pair:m});h.$(".paired-columns .column-datasets").append(l.render().$el).append(['<button class="unpair-btn">','<span class="fa fa-unlink" title="',d("Unpair"),'"></span>',"</button>"].join(""))})},_renderPairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no paired datasets yet")+")");this.$(".paired-columns .column-datasets").empty().prepend(h);return h},_renderFooter:function(i,j){var h=this.$(".footer").empty().html(e.templates.footer());this.$(".remove-extensions").prop("checked",this.removeExtensions);if(typeof this.oncancel==="function"){this.$(".cancel-create.btn").show()}return h},_addPluginComponents:function(){this._chooseFiltersPopover(".choose-filters-link");this.$(".help-content i").hoverhighlight(".collection-creator","rgba( 64, 255, 255, 1.0 )")},_chooseFiltersPopover:function(h){function i(l,k){return['<button class="filter-choice btn" ','data-forward="',l,'" data-reverse="',k,'">',d("Forward"),": ",l,", ",d("Reverse"),": ",k,"</button>"].join("")}var j=$(_.template(['<div class="choose-filters">','<div class="help">',d("Choose from the following filters to change which unpaired reads are shown in the display"),":</div>",i("_1","_2"),i("_R1","_R2"),"</div>"].join(""))({}));return this.$(h).popover({container:".collection-creator",placement:"bottom",html:true,content:j})},_validationWarning:function(i,h){var j="validation-warning";if(i==="name"){i=this.$(".collection-name").add(this.$(".collection-name-prompt"));this.$(".collection-name").focus().select()}if(h){i=i||this.$("."+j);i.removeClass(j)}else{i.addClass(j)}},_setUpBehaviors:function(){this.once("rendered",function(){this.trigger("rendered:initial",this)});this.on("pair:new",function(){this._renderUnpaired();this._renderPaired();this.$(".paired-columns").scrollTop(8000000)});this.on("pair:unpair",function(h){this._renderUnpaired();this._renderPaired();this.splitView()});this.on("filter-change",function(){this.filters=[this.$(".forward-unpaired-filter input").val(),this.$(".reverse-unpaired-filter input").val()];this._renderFilters();this._renderUnpaired()});this.on("autopair",function(){this._renderUnpaired();this._renderPaired();var h,i=null;if(this.paired.length){i="alert-success";h=this.paired.length+" "+d("pairs created");if(!this.unpaired.length){h+=": "+d("all datasets have been successfully paired");this.hideUnpaired();this.$(".collection-name").focus()}}else{h=d("Could not automatically create any pairs from the given dataset names")}this._showAlert(h,i)});return this},events:{"click .more-help":"_clickMoreHelp","click .less-help":"_clickLessHelp","click .header .alert button":"_hideAlert","click .forward-column .column-title":"_clickShowOnlyUnpaired","click .reverse-column .column-title":"_clickShowOnlyUnpaired","click .unpair-all-link":"_clickUnpairAll","change .forward-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .forward-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .autopair-link":"_clickAutopair","click .choose-filters .filter-choice":"_clickFilterChoice","click .clear-filters-link":"_clearFilters","change .reverse-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .reverse-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .forward-column .dataset.unpaired":"_clickUnpairedDataset","click .reverse-column .dataset.unpaired":"_clickUnpairedDataset","click .paired-column .dataset.unpaired":"_clickPairRow","click .unpaired-columns":"clearSelectedUnpaired","mousedown .unpaired-columns .dataset":"_mousedownUnpaired","click .paired-column-title":"_clickShowOnlyPaired","mousedown .flexible-partition-drag":"_startPartitionDrag","click .paired-columns .dataset.paired":"selectPair","click .paired-columns":"clearSelectedPaired","click .paired-columns .pair-name":"_clickPairName","click .unpair-btn":"_clickUnpair","dragover .paired-columns .column-datasets":"_dragoverPairedColumns","drop .paired-columns .column-datasets":"_dropPairedColumns","pair.dragstart .paired-columns .column-datasets":"_pairDragstart","pair.dragend .paired-columns .column-datasets":"_pairDragend","change .remove-extensions":function(h){this.toggleExtensions()},"change .collection-name":"_changeName","keydown .collection-name":"_nameCheckForEnter","click .cancel-create":function(h){if(typeof this.oncancel==="function"){this.oncancel.call(this)}},"click .create-collection":"_clickCreate"},_clickMoreHelp:function(h){this.$(".main-help").addClass("expanded");this.$(".more-help").hide()},_clickLessHelp:function(h){this.$(".main-help").removeClass("expanded");this.$(".more-help").show()},_showAlert:function(i,h){h=h||"alert-danger";this.$(".main-help").hide();this.$(".header .alert").attr("class","alert alert-dismissable").addClass(h).show().find(".alert-message").html(i)},_hideAlert:function(h){this.$(".main-help").show();this.$(".header .alert").hide()},_clickShowOnlyUnpaired:function(h){if(this.$(".paired-columns").is(":visible")){this.hidePaired()}else{this.splitView()}},_clickShowOnlyPaired:function(h){if(this.$(".unpaired-columns").is(":visible")){this.hideUnpaired()}else{this.splitView()}},hideUnpaired:function(h,i){this.unpairedPanelHidden=true;this.pairedPanelHidden=false;this._renderMiddle(h,i)},hidePaired:function(h,i){this.unpairedPanelHidden=false;this.pairedPanelHidden=true;this._renderMiddle(h,i)},splitView:function(h,i){this.unpairedPanelHidden=this.pairedPanelHidden=false;this._renderMiddle(h,i);return this},_clickUnpairAll:function(h){this.unpairAll()},_clickAutopair:function(h){this.autoPair();this.trigger("autopair")},_clickFilterChoice:function(i){var h=$(i.currentTarget);this.$(".forward-unpaired-filter input").val(h.data("forward"));this.$(".reverse-unpaired-filter input").val(h.data("reverse"));this._hideChooseFilters();this.trigger("filter-change")},_hideChooseFilters:function(){this.$(".choose-filters-link").popover("hide");this.$(".popover").css("display","none")},_clearFilters:function(h){this.$(".forward-unpaired-filter input").val("");this.$(".reverse-unpaired-filter input").val("");this.trigger("filter-change")},_clickUnpairedDataset:function(h){h.stopPropagation();return this.toggleSelectUnpaired($(h.currentTarget))},toggleSelectUnpaired:function(j,i){i=i||{};var k=j.data("dataset"),h=i.force!==undefined?i.force:!j.hasClass("selected");if(!j.size()||k===undefined){return j}if(h){j.addClass("selected");if(!i.waitToPair){this.pairAllSelected()}}else{j.removeClass("selected")}return j},pairAllSelected:function(i){i=i||{};var j=this,k=[],h=[],l=[];j.$(".unpaired-columns .forward-column .dataset.selected").each(function(){k.push($(this).data("dataset"))});j.$(".unpaired-columns .reverse-column .dataset.selected").each(function(){h.push($(this).data("dataset"))});k.length=h.length=Math.min(k.length,h.length);k.forEach(function(n,m){try{l.push(j._pair(n,h[m],{silent:true}))}catch(o){j.error(o)}});if(l.length&&!i.silent){this.trigger("pair:new",l)}return l},clearSelectedUnpaired:function(){this.$(".unpaired-columns .dataset.selected").removeClass("selected")},_mousedownUnpaired:function(j){if(j.shiftKey){var i=this,h=$(j.target).addClass("selected"),k=function(l){i.$(l.target).filter(".dataset").addClass("selected")};h.parent().on("mousemove",k);$(document).one("mouseup",function(l){h.parent().off("mousemove",k);i.pairAllSelected()})}},_clickPairRow:function(j){var k=$(j.currentTarget).index(),i=$(".unpaired-columns .forward-column .dataset").eq(k).data("dataset"),h=$(".unpaired-columns .reverse-column .dataset").eq(k).data("dataset");this._pair(i,h)},_startPartitionDrag:function(i){var h=this,l=i.pageY;$("body").css("cursor","ns-resize");h.$(".flexible-partition-drag").css("color","black");function k(m){h.$(".flexible-partition-drag").css("color","");$("body").css("cursor","").unbind("mousemove",j)}function j(m){var n=m.pageY-l;if(!h.adjPartition(n)){$("body").trigger("mouseup")}h._adjUnpairedOnScrollbar();l+=n}$("body").mousemove(j);$("body").one("mouseup",k)},adjPartition:function(i){var h=this.$(".unpaired-columns"),j=this.$(".paired-columns"),k=parseInt(h.css("height"),10),l=parseInt(j.css("height"),10);k=Math.max(10,k+i);l=l-i;var m=i<0;if(m){if(this.unpairedPanelHidden){return false}else{if(k<=10){this.hideUnpaired();return false}}}else{if(this.unpairedPanelHidden){h.show();this.unpairedPanelHidden=false}}if(!m){if(this.pairedPanelHidden){return false}else{if(l<=15){this.hidePaired();return false}}}else{if(this.pairedPanelHidden){j.show();this.pairedPanelHidden=false}}h.css({height:k+"px",flex:"0 0 auto"});return true},selectPair:function(h){h.stopPropagation();$(h.currentTarget).toggleClass("selected")},clearSelectedPaired:function(h){this.$(".paired-columns .dataset.selected").removeClass("selected")},_clickPairName:function(j){j.stopPropagation();var i=$(j.currentTarget),k=this.paired[i.parent().parent().index()/2],h=prompt("Enter a new name for the pair:",k.name);if(h){k.name=h;k.customizedName=true;i.text(k.name)}},_clickUnpair:function(i){var h=Math.floor($(i.currentTarget).index()/2);this._unpair(this.paired[h])},_dragoverPairedColumns:function(k){k.preventDefault();var i=this.$(".paired-columns .column-datasets");this._checkForAutoscroll(i,k.originalEvent.clientY);var j=this._getNearestPairedDatasetLi(k.originalEvent.clientY);$(".paired-drop-placeholder").remove();var h=$('<div class="paired-drop-placeholder"></div>');if(!j.size()){i.append(h)}else{j.before(h)}},_checkForAutoscroll:function(h,n){var l=2;var m=h.offset(),k=h.scrollTop(),i=n-m.top,j=(m.top+h.outerHeight())-n;if(i>=0&&i<this.autoscrollDist){h.scrollTop(k-l)}else{if(j>=0&&j<this.autoscrollDist){h.scrollTop(k+l)}}},_getNearestPairedDatasetLi:function(o){var l=4,j=this.$(".paired-columns .column-datasets li").toArray();for(var k=0;k<j.length;k++){var n=$(j[k]),m=n.offset().top,h=Math.floor(n.outerHeight()/2)+l;if(m+h>o&&m-h<o){return n}}return $()},_dropPairedColumns:function(i){i.preventDefault();i.dataTransfer.dropEffect="move";var h=this._getNearestPairedDatasetLi(i.originalEvent.clientY);if(h.size()){this.$dragging.insertBefore(h)}else{this.$dragging.insertAfter(this.$(".paired-columns .unpair-btn").last())}this._syncPairsToDom();return false},_syncPairsToDom:function(){var h=[];this.$(".paired-columns .dataset.paired").each(function(){h.push($(this).data("pair"))});this.paired=h;this._renderPaired()},_pairDragstart:function(i,j){j.$el.addClass("selected");var h=this.$(".paired-columns .dataset.selected");this.$dragging=h},_pairDragend:function(h,i){$(".paired-drop-placeholder").remove();this.$dragging=null},toggleExtensions:function(i){var h=this;h.removeExtensions=(i!==undefined)?(i):(!h.removeExtensions);_.each(h.paired,function(j){if(j.customizedName){return}j.name=h._guessNameForPair(j.forward,j.reverse)});h._renderPaired();h._renderFooter()},_changeName:function(h){this._validationWarning("name",!!this._getName())},_nameCheckForEnter:function(h){if(h.keyCode===13){this._clickCreate()}},_getName:function(){return _.escape(this.$(".collection-name").val())},_clickCreate:function(i){var h=this._getName();if(!h){this._validationWarning("name")}else{this.createList()}},_printList:function(i){var h=this;_.each(i,function(j){if(i===h.paired){h._printPair(j)}else{}})},_printPair:function(h){this.debug(h.forward.name,h.reverse.name,": ->",h.name)},toString:function(){return"PairedCollectionCreator"}});e.templates=e.templates||{main:_.template(['<div class="header flex-row no-flex"></div>','<div class="middle flex-row flex-row-container"></div>','<div class="footer flex-row no-flex">'].join("")),header:_.template(['<div class="main-help well clear">','<a class="more-help" href="javascript:void(0);">',d("More help"),"</a>",'<div class="help-content">','<a class="less-help" href="javascript:void(0);">',d("Less"),"</a>","</div>","</div>",'<div class="alert alert-dismissable">','<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>','<span class="alert-message"></span>',"</div>",'<div class="column-headers vertically-spaced flex-column-container">','<div class="forward-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired forward"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter forward-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>",'<div class="paired-column flex-column no-flex column">','<div class="column-header">','<a class="choose-filters-link" href="javascript:void(0)">',d("Choose filters"),"</a>",'<a class="clear-filters-link" href="javascript:void(0);">',d("Clear filters"),"</a><br />",'<a class="autopair-link" href="javascript:void(0);">',d("Auto-pair"),"</a>","</div>","</div>",'<div class="reverse-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired reverse"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter reverse-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>","</div>"].join("")),middle:_.template(['<div class="unpaired-columns flex-column-container scroll-container flex-row">','<div class="forward-column flex-column column">','<ol class="column-datasets"></ol>',"</div>",'<div class="paired-column flex-column no-flex column">','<ol class="column-datasets"></ol>',"</div>",'<div class="reverse-column flex-column column">','<ol class="column-datasets"></ol>',"</div>","</div>",'<div class="flexible-partition">','<div class="flexible-partition-drag" title="',d("Drag to change"),'"></div>','<div class="column-header">','<div class="column-title paired-column-title">','<span class="title"></span>',"</div>",'<a class="unpair-all-link" href="javascript:void(0);">',d("Unpair all"),"</a>","</div>","</div>",'<div class="paired-columns flex-column-container scroll-container flex-row">','<ol class="column-datasets"></ol>',"</div>"].join("")),footer:_.template(['<div class="attributes clear">','<div class="clear">','<label class="remove-extensions-prompt pull-right">',d("Remove file extensions from pair names"),"?",'<input class="remove-extensions pull-right" type="checkbox" />',"</label>","</div>",'<div class="clear">','<input class="collection-name form-control pull-right" ','placeholder="',d("Enter a name for your new list"),'" />','<div class="collection-name-prompt pull-right">',d("Name"),":</div>","</div>","</div>",'<div class="actions clear vertically-spaced">','<div class="other-options pull-left">','<button class="cancel-create btn" tabindex="-1">',d("Cancel"),"</button>",'<div class="create-other btn-group dropup">','<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">',d("Create a different kind of collection"),' <span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">','<li><a href="#">',d("Create a <i>single</i> pair"),"</a></li>",'<li><a href="#">',d("Create a list of <i>unpaired</i> datasets"),"</a></li>","</ul>","</div>","</div>",'<div class="main-options pull-right">','<button class="create-collection btn btn-primary">',d("Create list"),"</button>","</div>","</div>"].join("")),helpContent:_.template(["<p>",d(["Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). ","These collections can be passed to tools and workflows in order to have analyses done on each member of ","the entire group. This interface allows you to create a collection, choose which datasets are paired, ","and re-order the final collection."].join("")),"</p>","<p>",d(['Unpaired datasets are shown in the <i data-target=".unpaired-columns">unpaired section</i> ',"(hover over the underlined words to highlight below). ",'Paired datasets are shown in the <i data-target=".paired-columns">paired section</i>.',"<ul>To pair datasets, you can:","<li>Click a dataset in the ",'<i data-target=".unpaired-columns .forward-column .column-datasets,','.unpaired-columns .forward-column">forward column</i> ',"to select it then click a dataset in the ",'<i data-target=".unpaired-columns .reverse-column .column-datasets,','.unpaired-columns .reverse-column">reverse column</i>.',"</li>",'<li>Click one of the "Pair these datasets" buttons in the ','<i data-target=".unpaired-columns .paired-column .column-datasets,','.unpaired-columns .paired-column">middle column</i> ',"to pair the datasets in a particular row.","</li>",'<li>Click <i data-target=".autopair-link">"Auto-pair"</i> ',"to have your datasets automatically paired based on name.","</li>","</ul>"].join("")),"</p>","<p>",d(["<ul>You can filter what is shown in the unpaired sections by:","<li>Entering partial dataset names in either the ",'<i data-target=".forward-unpaired-filter input">forward filter</i> or ','<i data-target=".reverse-unpaired-filter input">reverse filter</i>.',"</li>","<li>Choosing from a list of preset filters by clicking the ",'<i data-target=".choose-filters-link">"Choose filters" link</i>.',"</li>","<li>Entering regular expressions to match dataset names. See: ",'<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expre…"',' target="_blank">MDN\'s JavaScript Regular Expression Tutorial</a>. ',"Note: forward slashes (\\) are not needed.","</li>","<li>Clearing the filters by clicking the ",'<i data-target=".clear-filters-link">"Clear filters" link</i>.',"</li>","</ul>"].join("")),"</p>","<p>",d(["To unpair individual dataset pairs, click the ",'<i data-target=".unpair-btn">unpair buttons ( <span class="fa fa-unlink"></span> )</i>. ','Click the <i data-target=".unpair-all-link">"Unpair all" link</i> to unpair all pairs.'].join("")),"</p>","<p>",d(['You can include or remove the file extensions (e.g. ".fastq") from your pair names by toggling the ','<i data-target=".remove-extensions-prompt">"Remove file extensions from pair names?"</i> control.'].join("")),"</p>","<p>",d(['Once your collection is complete, enter a <i data-target=".collection-name">name</i> and ','click <i data-target=".create-collection">"Create list"</i>. ',"(Note: you do not have to pair all unpaired datasets to finish.)"].join("")),"</p>"].join(""))};(function(){jQuery.fn.extend({hoverhighlight:function h(j,i){j=j||"body";if(!this.size()){return this}$(this).each(function(){var l=$(this),k=l.data("target");if(k){l.mouseover(function(m){$(k,j).css({background:i})}).mouseout(function(m){$(k).css({background:""})})}});return this}})}());var b=function c(j,h){h=_.defaults(h||{},{datasets:j,oncancel:function(){Galaxy.modal.hide()},oncreate:function(){Galaxy.modal.hide();Galaxy.currHistoryPanel.refreshContents()}});if(!window.Galaxy||!Galaxy.modal){throw new Error("Galaxy or Galaxy.modal not found")}var i=new e(h).render();Galaxy.modal.show({title:"Create a collection of paired datasets",body:i.$el,width:"80%",height:"800px",closing_events:true});window.PCC=i;return i};return{PairedCollectionCreator:e,pairedCollectionCreatorModal:b}});
\ No newline at end of file
+define(["utils/levenshtein","mvc/base-mvc","utils/localization"],function(g,a,d){var f=Backbone.View.extend(a.LoggableMixin).extend({tagName:"li",className:"dataset paired",initialize:function(h){this.pair=h.pair||{}},template:_.template(['<span class="forward-dataset-name flex-column"><%= pair.forward.name %></span>','<span class="pair-name-column flex-column">','<span class="pair-name"><%= pair.name %></span>',"</span>",'<span class="reverse-dataset-name flex-column"><%= pair.reverse.name %></span>'].join("")),render:function(){this.$el.attr("draggable",true).data("pair",this.pair).html(this.template({pair:this.pair})).addClass("flex-column-container");return this},events:{dragstart:"_dragstart",dragend:"_dragend",dragover:"_sendToParent",drop:"_sendToParent"},_dragstart:function(h){h.currentTarget.style.opacity="0.4";if(h.originalEvent){h=h.originalEvent}h.dataTransfer.effectAllowed="move";h.dataTransfer.setData("text/plain",JSON.stringify(this.pair));this.$el.parent().trigger("pair.dragstart",[this])},_dragend:function(h){h.currentTarget.style.opacity="1.0";this.$el.parent().trigger("pair.dragend",[this])},_sendToParent:function(h){this.$el.parent().trigger(h)},toString:function(){return"PairView("+this.pair.name+")"}});var e=Backbone.View.extend(a.LoggableMixin).extend({className:"collection-creator flex-row-container",initialize:function(h){h=_.defaults(h,{datasets:[],filters:this.DEFAULT_FILTERS,automaticallyPair:true,matchPercentage:1,strategy:"lcs"});this.initialList=h.datasets;this.historyId=h.historyId;this.filters=this.commonFilters[h.filters]||this.commonFilters[this.DEFAULT_FILTERS];if(_.isArray(h.filters)){this.filters=h.filters}this.automaticallyPair=h.automaticallyPair;this.matchPercentage=h.matchPercentage;this.strategy=this.strategies[h.strategy]||this.strategies[this.DEFAULT_STRATEGY];if(_.isFunction(h.strategy)){this.strategy=h.strategy}this.removeExtensions=true;this.oncancel=h.oncancel;this.oncreate=h.oncreate;this.autoscrollDist=h.autoscrollDist||24;this.unpairedPanelHidden=false;this.pairedPanelHidden=false;this.$dragging=null;this._setUpBehaviors();this._dataSetUp()},commonFilters:{none:["",""],illumina:["_1","_2"]},DEFAULT_FILTERS:"illumina",strategies:{lcs:"autoPairLCSs",levenshtein:"autoPairLevenshtein"},DEFAULT_STRATEGY:"lcs",_dataSetUp:function(){this.paired=[];this.unpaired=[];this.selectedIds=[];this._sortInitialList();this._ensureIds();this.unpaired=this.initialList.slice(0);if(this.automaticallyPair){this.autoPair();this.once("rendered:initial",function(){this.trigger("autopair")})}},_sortInitialList:function(){this._sortDatasetList(this.initialList)},_sortDatasetList:function(h){h.sort(function(j,i){return naturalSort(j.name,i.name)});return h},_ensureIds:function(){this.initialList.forEach(function(h){if(!h.hasOwnProperty("id")){h.id=_.uniqueId()}});return this.initialList},_splitByFilters:function(j){var i=[],h=[];this.unpaired.forEach(function(k){if(this._filterFwdFn(k)){i.push(k)}if(this._filterRevFn(k)){h.push(k)}}.bind(this));return[i,h]},_filterFwdFn:function(i){var h=new RegExp(this.filters[0]);return h.test(i.name)},_filterRevFn:function(i){var h=new RegExp(this.filters[1]);return h.test(i.name)},_addToUnpaired:function(i){var h=function(j,l){if(j===l){return j}var k=Math.floor((l-j)/2)+j,m=naturalSort(i.name,this.unpaired[k].name);if(m<0){return h(j,k)}else{if(m>0){return h(k+1,l)}}while(this.unpaired[k]&&this.unpaired[k].name===i.name){k++}return k}.bind(this);this.unpaired.splice(h(0,this.unpaired.length),0,i)},autoPair:function(i){i=i||this.strategy;var h=this.simpleAutoPair();h=h.concat(this[i].call(this));return h},simpleAutoPair:function(){var o=0,m,s=this._splitByFilters(),h=s[0],r=s[1],q,u,k=false,t=[];while(o<h.length){var n=h[o];q=n.name.replace(this.filters[0],"");k=false;for(m=0;m<r.length;m++){var p=r[m];u=p.name.replace(this.filters[1],"");if(n!==p&&q===u){k=true;var l=this._pair(h.splice(o,1)[0],r.splice(m,1)[0],{silent:true});t.push(l);break}}if(!k){o+=1}}return t},autoPairLevenshtein:function(){var p=0,n,u=this._splitByFilters(),h=u[0],s=u[1],r,x,k,t,l,v=[];while(p<h.length){var o=h[p];r=o.name.replace(this.filters[0],"");l=Number.MAX_VALUE;for(n=0;n<s.length;n++){var q=s[n];x=q.name.replace(this.filters[1],"");if(o!==q){if(r===x){t=n;l=0;break}k=levenshteinDistance(r,x);if(k<l){t=n;l=k}}}var w=1-(l/(Math.max(r.length,x.length)));if(w>=this.matchPercentage){var m=this._pair(h.splice(p,1)[0],s.splice(t,1)[0],{silent:true});v.push(m);if(h.length<=0||s.length<=0){return v}}else{p+=1}}return v},autoPairLCSs:function(){var n=0,l,u=this._splitByFilters(),h=u[0],s=u[1],r,y,x,t,p,v=[];if(!h.length||!s.length){return v}while(n<h.length){var m=h[n];r=m.name.replace(this.filters[0],"");p=0;for(l=0;l<s.length;l++){var q=s[l];y=q.name.replace(this.filters[1],"");if(m!==q){if(r===y){t=l;p=r.length;break}var o=this._naiveStartingAndEndingLCS(r,y);x=o.length;if(x>p){t=l;p=x}}}var w=p/(Math.min(r.length,y.length));if(w>=this.matchPercentage){var k=this._pair(h.splice(n,1)[0],s.splice(t,1)[0],{silent:true});v.push(k);if(h.length<=0||s.length<=0){return v}}else{n+=1}}return v},_naiveStartingAndEndingLCS:function(m,k){var n="",o="",l=0,h=0;while(l<m.length&&l<k.length){if(m[l]!==k[l]){break}n+=m[l];l+=1}if(l===m.length){return m}if(l===k.length){return k}l=(m.length-1);h=(k.length-1);while(l>=0&&h>=0){if(m[l]!==k[h]){break}o=[m[l],o].join("");l-=1;h-=1}return n+o},_pair:function(j,h,i){i=i||{};var k=this._createPair(j,h,i.name);this.paired.push(k);this.unpaired=_.without(this.unpaired,j,h);if(!i.silent){this.trigger("pair:new",k)}return k},_createPair:function(j,h,i){if(!(j&&h)||(j===h)){throw new Error("Bad pairing: "+[JSON.stringify(j),JSON.stringify(h)])}i=i||this._guessNameForPair(j,h);return{forward:j,name:i,reverse:h}},_guessNameForPair:function(j,h,k){k=(k!==undefined)?(k):(this.removeExtensions);var i=this._naiveStartingAndEndingLCS(j.name.replace(this.filters[0],""),h.name.replace(this.filters[1],""));if(k){var l=i.lastIndexOf(".");if(l>0){i=i.slice(0,l)}}return i||(j.name+" & "+h.name)},_unpair:function(i,h){h=h||{};if(!i){throw new Error("Bad pair: "+JSON.stringify(i))}this.paired=_.without(this.paired,i);this._addToUnpaired(i.forward);this._addToUnpaired(i.reverse);if(!h.silent){this.trigger("pair:unpair",[i])}return i},unpairAll:function(){var h=[];while(this.paired.length){h.push(this._unpair(this.paired[0],{silent:true}))}this.trigger("pair:unpair",h)},_pairToJSON:function(h){return{collection_type:"paired",src:"new_collection",name:h.name,element_identifiers:[{name:"forward",id:h.forward.id,src:"hda"},{name:"reverse",id:h.reverse.id,src:"hda"}]}},createList:function(){var j=this,i;if(j.historyId){i="/api/histories/"+this.historyId+"/contents/dataset_collections"}var h={type:"dataset_collection",collection_type:"list:paired",name:_.escape(j.$(".collection-name").val()),element_identifiers:j.paired.map(function(k){return j._pairToJSON(k)})};return jQuery.ajax(i,{type:"POST",contentType:"application/json",dataType:"json",data:JSON.stringify(h)}).fail(function(m,k,l){j._ajaxErrHandler(m,k,l)}).done(function(k,l,m){j.trigger("collection:created",k,l,m);if(typeof j.oncreate==="function"){j.oncreate.call(this,k,l,m)}})},_ajaxErrHandler:function(k,h,j){this.error(k,h,j);var i=d("An error occurred while creating this collection");if(k){if(k.readyState===0&&k.status===0){i+=": "+d("Galaxy could not be reached and may be updating.")+d(" Try again in a few minutes.")}else{if(k.responseJSON){i+="<br /><pre>"+JSON.stringify(k.responseJSON)+"</pre>"}else{i+=": "+j}}}creator._showAlert(i,"alert-danger")},render:function(h,i){this.$el.empty().html(e.templates.main());this._renderHeader(h);this._renderMiddle(h);this._renderFooter(h);this._addPluginComponents();this.trigger("rendered",this);return this},_renderHeader:function(i,j){var h=this.$(".header").empty().html(e.templates.header()).find(".help-content").prepend($(e.templates.helpContent()));this._renderFilters();return h},_renderFilters:function(){return this.$(".forward-column .column-header input").val(this.filters[0]).add(this.$(".reverse-column .column-header input").val(this.filters[1]))},_renderMiddle:function(i,j){var h=this.$(".middle").empty().html(e.templates.middle());if(this.unpairedPanelHidden){this.$(".unpaired-columns").hide()}else{if(this.pairedPanelHidden){this.$(".paired-columns").hide()}}this._renderUnpaired();this._renderPaired();return h},_renderUnpaired:function(m,n){var k=this,l,i,h=[],j=this._splitByFilters();this.$(".forward-column .title").text([j[0].length,d("unpaired forward")].join(" "));this.$(".forward-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[0].length));this.$(".reverse-column .title").text([j[1].length,d("unpaired reverse")].join(" "));this.$(".reverse-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[1].length));this.$(".unpaired-columns .column-datasets").empty();this.$(".autopair-link").toggle(this.unpaired.length!==0);if(this.unpaired.length===0){this._renderUnpairedEmpty();return}i=j[1].map(function(p,o){if((j[0][o]!==undefined)&&(j[0][o]!==p)){h.push(k._renderPairButton())}return k._renderUnpairedDataset(p)});l=j[0].map(function(o){return k._renderUnpairedDataset(o)});if(!l.length&&!i.length){this._renderUnpairedNotShown();return}this.$(".unpaired-columns .forward-column .column-datasets").append(l).add(this.$(".unpaired-columns .paired-column .column-datasets").append(h)).add(this.$(".unpaired-columns .reverse-column .column-datasets").append(i));this._adjUnpairedOnScrollbar()},_renderUnpairedDisplayStr:function(h){return["(",h," ",d("filtered out"),")"].join("")},_renderUnpairedDataset:function(h){return $("<li/>").attr("id","dataset-"+h.id).addClass("dataset unpaired").attr("draggable",true).addClass(h.selected?"selected":"").append($("<span/>").addClass("dataset-name").text(h.name)).data("dataset",h)},_renderPairButton:function(){return $("<li/>").addClass("dataset unpaired").append($("<span/>").addClass("dataset-name").text(d("Pair these datasets")))},_renderUnpairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no remaining unpaired datasets")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_renderUnpairedNotShown:function(){var h=$('<div class="empty-message"></div>').text("("+d("no datasets were found matching the current filters")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_adjUnpairedOnScrollbar:function(){var k=this.$(".unpaired-columns").last(),l=this.$(".unpaired-columns .reverse-column .dataset").first();if(!l.size()){return}var h=k.offset().left+k.outerWidth(),j=l.offset().left+l.outerWidth(),i=Math.floor(h)-Math.floor(j);this.$(".unpaired-columns .forward-column").css("margin-left",(i>0)?i:0)},_renderPaired:function(i,j){this.$(".paired-column-title .title").text([this.paired.length,d("paired")].join(" "));this.$(".unpair-all-link").toggle(this.paired.length!==0);if(this.paired.length===0){this._renderPairedEmpty();return}else{this.$(".remove-extensions-link").show()}this.$(".paired-columns .column-datasets").empty();var h=this;this.paired.forEach(function(m,k){var l=new f({pair:m});h.$(".paired-columns .column-datasets").append(l.render().$el).append(['<button class="unpair-btn">','<span class="fa fa-unlink" title="',d("Unpair"),'"></span>',"</button>"].join(""))})},_renderPairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no paired datasets yet")+")");this.$(".paired-columns .column-datasets").empty().prepend(h);return h},_renderFooter:function(i,j){var h=this.$(".footer").empty().html(e.templates.footer());this.$(".remove-extensions").prop("checked",this.removeExtensions);if(typeof this.oncancel==="function"){this.$(".cancel-create.btn").show()}return h},_addPluginComponents:function(){this._chooseFiltersPopover(".choose-filters-link");this.$(".help-content i").hoverhighlight(".collection-creator","rgba( 64, 255, 255, 1.0 )")},_chooseFiltersPopover:function(h){function i(l,k){return['<button class="filter-choice btn" ','data-forward="',l,'" data-reverse="',k,'">',d("Forward"),": ",l,", ",d("Reverse"),": ",k,"</button>"].join("")}var j=$(_.template(['<div class="choose-filters">','<div class="help">',d("Choose from the following filters to change which unpaired reads are shown in the display"),":</div>",i("_1","_2"),i("_R1","_R2"),"</div>"].join(""))({}));return this.$(h).popover({container:".collection-creator",placement:"bottom",html:true,content:j})},_validationWarning:function(i,h){var j="validation-warning";if(i==="name"){i=this.$(".collection-name").add(this.$(".collection-name-prompt"));this.$(".collection-name").focus().select()}if(h){i=i||this.$("."+j);i.removeClass(j)}else{i.addClass(j)}},_setUpBehaviors:function(){this.once("rendered",function(){this.trigger("rendered:initial",this)});this.on("pair:new",function(){this._renderUnpaired();this._renderPaired();this.$(".paired-columns").scrollTop(8000000)});this.on("pair:unpair",function(h){this._renderUnpaired();this._renderPaired();this.splitView()});this.on("filter-change",function(){this.filters=[this.$(".forward-unpaired-filter input").val(),this.$(".reverse-unpaired-filter input").val()];this._renderFilters();this._renderUnpaired()});this.on("autopair",function(){this._renderUnpaired();this._renderPaired();var h,i=null;if(this.paired.length){i="alert-success";h=this.paired.length+" "+d("pairs created");if(!this.unpaired.length){h+=": "+d("all datasets have been successfully paired");this.hideUnpaired();this.$(".collection-name").focus()}}else{h=d("Could not automatically create any pairs from the given dataset names")}this._showAlert(h,i)});return this},events:{"click .more-help":"_clickMoreHelp","click .less-help":"_clickLessHelp","click .header .alert button":"_hideAlert","click .forward-column .column-title":"_clickShowOnlyUnpaired","click .reverse-column .column-title":"_clickShowOnlyUnpaired","click .unpair-all-link":"_clickUnpairAll","change .forward-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .forward-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .autopair-link":"_clickAutopair","click .choose-filters .filter-choice":"_clickFilterChoice","click .clear-filters-link":"_clearFilters","change .reverse-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .reverse-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .forward-column .dataset.unpaired":"_clickUnpairedDataset","click .reverse-column .dataset.unpaired":"_clickUnpairedDataset","click .paired-column .dataset.unpaired":"_clickPairRow","click .unpaired-columns":"clearSelectedUnpaired","mousedown .unpaired-columns .dataset":"_mousedownUnpaired","click .paired-column-title":"_clickShowOnlyPaired","mousedown .flexible-partition-drag":"_startPartitionDrag","click .paired-columns .dataset.paired":"selectPair","click .paired-columns":"clearSelectedPaired","click .paired-columns .pair-name":"_clickPairName","click .unpair-btn":"_clickUnpair","dragover .paired-columns .column-datasets":"_dragoverPairedColumns","drop .paired-columns .column-datasets":"_dropPairedColumns","pair.dragstart .paired-columns .column-datasets":"_pairDragstart","pair.dragend .paired-columns .column-datasets":"_pairDragend","change .remove-extensions":function(h){this.toggleExtensions()},"change .collection-name":"_changeName","keydown .collection-name":"_nameCheckForEnter","click .cancel-create":function(h){if(typeof this.oncancel==="function"){this.oncancel.call(this)}},"click .create-collection":"_clickCreate"},_clickMoreHelp:function(h){this.$(".main-help").addClass("expanded");this.$(".more-help").hide()},_clickLessHelp:function(h){this.$(".main-help").removeClass("expanded");this.$(".more-help").show()},_showAlert:function(i,h){h=h||"alert-danger";this.$(".main-help").hide();this.$(".header .alert").attr("class","alert alert-dismissable").addClass(h).show().find(".alert-message").html(i)},_hideAlert:function(h){this.$(".main-help").show();this.$(".header .alert").hide()},_clickShowOnlyUnpaired:function(h){if(this.$(".paired-columns").is(":visible")){this.hidePaired()}else{this.splitView()}},_clickShowOnlyPaired:function(h){if(this.$(".unpaired-columns").is(":visible")){this.hideUnpaired()}else{this.splitView()}},hideUnpaired:function(h,i){this.unpairedPanelHidden=true;this.pairedPanelHidden=false;this._renderMiddle(h,i)},hidePaired:function(h,i){this.unpairedPanelHidden=false;this.pairedPanelHidden=true;this._renderMiddle(h,i)},splitView:function(h,i){this.unpairedPanelHidden=this.pairedPanelHidden=false;this._renderMiddle(h,i);return this},_clickUnpairAll:function(h){this.unpairAll()},_clickAutopair:function(h){this.autoPair();this.trigger("autopair")},_clickFilterChoice:function(i){var h=$(i.currentTarget);this.$(".forward-unpaired-filter input").val(h.data("forward"));this.$(".reverse-unpaired-filter input").val(h.data("reverse"));this._hideChooseFilters();this.trigger("filter-change")},_hideChooseFilters:function(){this.$(".choose-filters-link").popover("hide");this.$(".popover").css("display","none")},_clearFilters:function(h){this.$(".forward-unpaired-filter input").val("");this.$(".reverse-unpaired-filter input").val("");this.trigger("filter-change")},_clickUnpairedDataset:function(h){h.stopPropagation();return this.toggleSelectUnpaired($(h.currentTarget))},toggleSelectUnpaired:function(j,i){i=i||{};var k=j.data("dataset"),h=i.force!==undefined?i.force:!j.hasClass("selected");if(!j.size()||k===undefined){return j}if(h){j.addClass("selected");if(!i.waitToPair){this.pairAllSelected()}}else{j.removeClass("selected")}return j},pairAllSelected:function(i){i=i||{};var j=this,k=[],h=[],l=[];j.$(".unpaired-columns .forward-column .dataset.selected").each(function(){k.push($(this).data("dataset"))});j.$(".unpaired-columns .reverse-column .dataset.selected").each(function(){h.push($(this).data("dataset"))});k.length=h.length=Math.min(k.length,h.length);k.forEach(function(n,m){try{l.push(j._pair(n,h[m],{silent:true}))}catch(o){j.error(o)}});if(l.length&&!i.silent){this.trigger("pair:new",l)}return l},clearSelectedUnpaired:function(){this.$(".unpaired-columns .dataset.selected").removeClass("selected")},_mousedownUnpaired:function(j){if(j.shiftKey){var i=this,h=$(j.target).addClass("selected"),k=function(l){i.$(l.target).filter(".dataset").addClass("selected")};h.parent().on("mousemove",k);$(document).one("mouseup",function(l){h.parent().off("mousemove",k);i.pairAllSelected()})}},_clickPairRow:function(j){var k=$(j.currentTarget).index(),i=$(".unpaired-columns .forward-column .dataset").eq(k).data("dataset"),h=$(".unpaired-columns .reverse-column .dataset").eq(k).data("dataset");this._pair(i,h)},_startPartitionDrag:function(i){var h=this,l=i.pageY;$("body").css("cursor","ns-resize");h.$(".flexible-partition-drag").css("color","black");function k(m){h.$(".flexible-partition-drag").css("color","");$("body").css("cursor","").unbind("mousemove",j)}function j(m){var n=m.pageY-l;if(!h.adjPartition(n)){$("body").trigger("mouseup")}h._adjUnpairedOnScrollbar();l+=n}$("body").mousemove(j);$("body").one("mouseup",k)},adjPartition:function(i){var h=this.$(".unpaired-columns"),j=this.$(".paired-columns"),k=parseInt(h.css("height"),10),l=parseInt(j.css("height"),10);k=Math.max(10,k+i);l=l-i;var m=i<0;if(m){if(this.unpairedPanelHidden){return false}else{if(k<=10){this.hideUnpaired();return false}}}else{if(this.unpairedPanelHidden){h.show();this.unpairedPanelHidden=false}}if(!m){if(this.pairedPanelHidden){return false}else{if(l<=15){this.hidePaired();return false}}}else{if(this.pairedPanelHidden){j.show();this.pairedPanelHidden=false}}h.css({height:k+"px",flex:"0 0 auto"});return true},selectPair:function(h){h.stopPropagation();$(h.currentTarget).toggleClass("selected")},clearSelectedPaired:function(h){this.$(".paired-columns .dataset.selected").removeClass("selected")},_clickPairName:function(k){k.stopPropagation();var m=$(k.currentTarget),j=m.parent().parent(),i=j.index(".dataset.paired"),l=this.paired[i],h=prompt("Enter a new name for the pair:",l.name);if(h){l.name=h;l.customizedName=true;m.text(l.name)}},_clickUnpair:function(i){var h=Math.floor($(i.currentTarget).index(".unpair-btn"));this._unpair(this.paired[h])},_dragoverPairedColumns:function(k){k.preventDefault();var i=this.$(".paired-columns .column-datasets");this._checkForAutoscroll(i,k.originalEvent.clientY);var j=this._getNearestPairedDatasetLi(k.originalEvent.clientY);$(".paired-drop-placeholder").remove();var h=$('<div class="paired-drop-placeholder"></div>');if(!j.size()){i.append(h)}else{j.before(h)}},_checkForAutoscroll:function(h,n){var l=2;var m=h.offset(),k=h.scrollTop(),i=n-m.top,j=(m.top+h.outerHeight())-n;if(i>=0&&i<this.autoscrollDist){h.scrollTop(k-l)}else{if(j>=0&&j<this.autoscrollDist){h.scrollTop(k+l)}}},_getNearestPairedDatasetLi:function(o){var l=4,j=this.$(".paired-columns .column-datasets li").toArray();for(var k=0;k<j.length;k++){var n=$(j[k]),m=n.offset().top,h=Math.floor(n.outerHeight()/2)+l;if(m+h>o&&m-h<o){return n}}return $()},_dropPairedColumns:function(i){i.preventDefault();i.dataTransfer.dropEffect="move";var h=this._getNearestPairedDatasetLi(i.originalEvent.clientY);if(h.size()){this.$dragging.insertBefore(h)}else{this.$dragging.insertAfter(this.$(".paired-columns .unpair-btn").last())}this._syncPairsToDom();return false},_syncPairsToDom:function(){var h=[];this.$(".paired-columns .dataset.paired").each(function(){h.push($(this).data("pair"))});this.paired=h;this._renderPaired()},_pairDragstart:function(i,j){j.$el.addClass("selected");var h=this.$(".paired-columns .dataset.selected");this.$dragging=h},_pairDragend:function(h,i){$(".paired-drop-placeholder").remove();this.$dragging=null},toggleExtensions:function(i){var h=this;h.removeExtensions=(i!==undefined)?(i):(!h.removeExtensions);_.each(h.paired,function(j){if(j.customizedName){return}j.name=h._guessNameForPair(j.forward,j.reverse)});h._renderPaired();h._renderFooter()},_changeName:function(h){this._validationWarning("name",!!this._getName())},_nameCheckForEnter:function(h){if(h.keyCode===13){this._clickCreate()}},_getName:function(){return _.escape(this.$(".collection-name").val())},_clickCreate:function(i){var h=this._getName();if(!h){this._validationWarning("name")}else{this.createList()}},_printList:function(i){var h=this;_.each(i,function(j){if(i===h.paired){h._printPair(j)}else{}})},_printPair:function(h){this.debug(h.forward.name,h.reverse.name,": ->",h.name)},toString:function(){return"PairedCollectionCreator"}});e.templates=e.templates||{main:_.template(['<div class="header flex-row no-flex"></div>','<div class="middle flex-row flex-row-container"></div>','<div class="footer flex-row no-flex">'].join("")),header:_.template(['<div class="main-help well clear">','<a class="more-help" href="javascript:void(0);">',d("More help"),"</a>",'<div class="help-content">','<a class="less-help" href="javascript:void(0);">',d("Less"),"</a>","</div>","</div>",'<div class="alert alert-dismissable">','<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>','<span class="alert-message"></span>',"</div>",'<div class="column-headers vertically-spaced flex-column-container">','<div class="forward-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired forward"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter forward-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>",'<div class="paired-column flex-column no-flex column">','<div class="column-header">','<a class="choose-filters-link" href="javascript:void(0)">',d("Choose filters"),"</a>",'<a class="clear-filters-link" href="javascript:void(0);">',d("Clear filters"),"</a><br />",'<a class="autopair-link" href="javascript:void(0);">',d("Auto-pair"),"</a>","</div>","</div>",'<div class="reverse-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired reverse"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter reverse-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>","</div>"].join("")),middle:_.template(['<div class="unpaired-columns flex-column-container scroll-container flex-row">','<div class="forward-column flex-column column">','<ol class="column-datasets"></ol>',"</div>",'<div class="paired-column flex-column no-flex column">','<ol class="column-datasets"></ol>',"</div>",'<div class="reverse-column flex-column column">','<ol class="column-datasets"></ol>',"</div>","</div>",'<div class="flexible-partition">','<div class="flexible-partition-drag" title="',d("Drag to change"),'"></div>','<div class="column-header">','<div class="column-title paired-column-title">','<span class="title"></span>',"</div>",'<a class="unpair-all-link" href="javascript:void(0);">',d("Unpair all"),"</a>","</div>","</div>",'<div class="paired-columns flex-column-container scroll-container flex-row">','<ol class="column-datasets"></ol>',"</div>"].join("")),footer:_.template(['<div class="attributes clear">','<div class="clear">','<label class="remove-extensions-prompt pull-right">',d("Remove file extensions from pair names"),"?",'<input class="remove-extensions pull-right" type="checkbox" />',"</label>","</div>",'<div class="clear">','<input class="collection-name form-control pull-right" ','placeholder="',d("Enter a name for your new list"),'" />','<div class="collection-name-prompt pull-right">',d("Name"),":</div>","</div>","</div>",'<div class="actions clear vertically-spaced">','<div class="other-options pull-left">','<button class="cancel-create btn" tabindex="-1">',d("Cancel"),"</button>",'<div class="create-other btn-group dropup">','<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">',d("Create a different kind of collection"),' <span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">','<li><a href="#">',d("Create a <i>single</i> pair"),"</a></li>",'<li><a href="#">',d("Create a list of <i>unpaired</i> datasets"),"</a></li>","</ul>","</div>","</div>",'<div class="main-options pull-right">','<button class="create-collection btn btn-primary">',d("Create list"),"</button>","</div>","</div>"].join("")),helpContent:_.template(["<p>",d(["Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). ","These collections can be passed to tools and workflows in order to have analyses done on each member of ","the entire group. This interface allows you to create a collection, choose which datasets are paired, ","and re-order the final collection."].join("")),"</p>","<p>",d(['Unpaired datasets are shown in the <i data-target=".unpaired-columns">unpaired section</i> ',"(hover over the underlined words to highlight below). ",'Paired datasets are shown in the <i data-target=".paired-columns">paired section</i>.',"<ul>To pair datasets, you can:","<li>Click a dataset in the ",'<i data-target=".unpaired-columns .forward-column .column-datasets,','.unpaired-columns .forward-column">forward column</i> ',"to select it then click a dataset in the ",'<i data-target=".unpaired-columns .reverse-column .column-datasets,','.unpaired-columns .reverse-column">reverse column</i>.',"</li>",'<li>Click one of the "Pair these datasets" buttons in the ','<i data-target=".unpaired-columns .paired-column .column-datasets,','.unpaired-columns .paired-column">middle column</i> ',"to pair the datasets in a particular row.","</li>",'<li>Click <i data-target=".autopair-link">"Auto-pair"</i> ',"to have your datasets automatically paired based on name.","</li>","</ul>"].join("")),"</p>","<p>",d(["<ul>You can filter what is shown in the unpaired sections by:","<li>Entering partial dataset names in either the ",'<i data-target=".forward-unpaired-filter input">forward filter</i> or ','<i data-target=".reverse-unpaired-filter input">reverse filter</i>.',"</li>","<li>Choosing from a list of preset filters by clicking the ",'<i data-target=".choose-filters-link">"Choose filters" link</i>.',"</li>","<li>Entering regular expressions to match dataset names. See: ",'<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expre…"',' target="_blank">MDN\'s JavaScript Regular Expression Tutorial</a>. ',"Note: forward slashes (\\) are not needed.","</li>","<li>Clearing the filters by clicking the ",'<i data-target=".clear-filters-link">"Clear filters" link</i>.',"</li>","</ul>"].join("")),"</p>","<p>",d(["To unpair individual dataset pairs, click the ",'<i data-target=".unpair-btn">unpair buttons ( <span class="fa fa-unlink"></span> )</i>. ','Click the <i data-target=".unpair-all-link">"Unpair all" link</i> to unpair all pairs.'].join("")),"</p>","<p>",d(['You can include or remove the file extensions (e.g. ".fastq") from your pair names by toggling the ','<i data-target=".remove-extensions-prompt">"Remove file extensions from pair names?"</i> control.'].join("")),"</p>","<p>",d(['Once your collection is complete, enter a <i data-target=".collection-name">name</i> and ','click <i data-target=".create-collection">"Create list"</i>. ',"(Note: you do not have to pair all unpaired datasets to finish.)"].join("")),"</p>"].join(""))};(function(){jQuery.fn.extend({hoverhighlight:function h(j,i){j=j||"body";if(!this.size()){return this}$(this).each(function(){var l=$(this),k=l.data("target");if(k){l.mouseover(function(m){$(k,j).css({background:i})}).mouseout(function(m){$(k).css({background:""})})}});return this}})}());var b=function c(j,h){h=_.defaults(h||{},{datasets:j,oncancel:function(){Galaxy.modal.hide()},oncreate:function(){Galaxy.modal.hide();Galaxy.currHistoryPanel.refreshContents()}});if(!window.Galaxy||!Galaxy.modal){throw new Error("Galaxy or Galaxy.modal not found")}var i=new e(h).render();Galaxy.modal.show({title:"Create a collection of paired datasets",body:i.$el,width:"80%",height:"800px",closing_events:true});window.PCC=i;return i};return{PairedCollectionCreator:e,pairedCollectionCreatorModal:b}});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: UI, Paired collection creator: fix template function for 'Choose Filters'
by commits-noreply@bitbucket.org 09 Feb '15
by commits-noreply@bitbucket.org 09 Feb '15
09 Feb '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/3764ca243a93/
Changeset: 3764ca243a93
User: carlfeberhard
Date: 2015-02-09 22:54:17+00:00
Summary: UI, Paired collection creator: fix template function for 'Choose Filters'
Affected #: 3 files
diff -r 27bc860232d7e531133f0413d6200fe5c171695d -r 3764ca243a9366a8f7ccd9403ef7bc7df45cc4ae client/galaxy/scripts/mvc/collection/paired-collection-creator.js
--- a/client/galaxy/scripts/mvc/collection/paired-collection-creator.js
+++ b/client/galaxy/scripts/mvc/collection/paired-collection-creator.js
@@ -876,7 +876,7 @@
filterChoice( '_1', '_2' ),
filterChoice( '_R1', '_R2' ),
'</div>'
- ].join(''), {}));
+ ].join(''))({}));
return this.$( selector ).popover({
container : '.collection-creator',
diff -r 27bc860232d7e531133f0413d6200fe5c171695d -r 3764ca243a9366a8f7ccd9403ef7bc7df45cc4ae static/scripts/mvc/collection/paired-collection-creator.js
--- a/static/scripts/mvc/collection/paired-collection-creator.js
+++ b/static/scripts/mvc/collection/paired-collection-creator.js
@@ -876,7 +876,7 @@
filterChoice( '_1', '_2' ),
filterChoice( '_R1', '_R2' ),
'</div>'
- ].join(''), {}));
+ ].join(''))({}));
return this.$( selector ).popover({
container : '.collection-creator',
diff -r 27bc860232d7e531133f0413d6200fe5c171695d -r 3764ca243a9366a8f7ccd9403ef7bc7df45cc4ae static/scripts/packed/mvc/collection/paired-collection-creator.js
--- a/static/scripts/packed/mvc/collection/paired-collection-creator.js
+++ b/static/scripts/packed/mvc/collection/paired-collection-creator.js
@@ -1,1 +1,1 @@
-define(["utils/levenshtein","mvc/base-mvc","utils/localization"],function(g,a,d){var f=Backbone.View.extend(a.LoggableMixin).extend({tagName:"li",className:"dataset paired",initialize:function(h){this.pair=h.pair||{}},template:_.template(['<span class="forward-dataset-name flex-column"><%= pair.forward.name %></span>','<span class="pair-name-column flex-column">','<span class="pair-name"><%= pair.name %></span>',"</span>",'<span class="reverse-dataset-name flex-column"><%= pair.reverse.name %></span>'].join("")),render:function(){this.$el.attr("draggable",true).data("pair",this.pair).html(this.template({pair:this.pair})).addClass("flex-column-container");return this},events:{dragstart:"_dragstart",dragend:"_dragend",dragover:"_sendToParent",drop:"_sendToParent"},_dragstart:function(h){h.currentTarget.style.opacity="0.4";if(h.originalEvent){h=h.originalEvent}h.dataTransfer.effectAllowed="move";h.dataTransfer.setData("text/plain",JSON.stringify(this.pair));this.$el.parent().trigger("pair.dragstart",[this])},_dragend:function(h){h.currentTarget.style.opacity="1.0";this.$el.parent().trigger("pair.dragend",[this])},_sendToParent:function(h){this.$el.parent().trigger(h)},toString:function(){return"PairView("+this.pair.name+")"}});var e=Backbone.View.extend(a.LoggableMixin).extend({className:"collection-creator flex-row-container",initialize:function(h){h=_.defaults(h,{datasets:[],filters:this.DEFAULT_FILTERS,automaticallyPair:true,matchPercentage:1,strategy:"lcs"});this.initialList=h.datasets;this.historyId=h.historyId;this.filters=this.commonFilters[h.filters]||this.commonFilters[this.DEFAULT_FILTERS];if(_.isArray(h.filters)){this.filters=h.filters}this.automaticallyPair=h.automaticallyPair;this.matchPercentage=h.matchPercentage;this.strategy=this.strategies[h.strategy]||this.strategies[this.DEFAULT_STRATEGY];if(_.isFunction(h.strategy)){this.strategy=h.strategy}this.removeExtensions=true;this.oncancel=h.oncancel;this.oncreate=h.oncreate;this.autoscrollDist=h.autoscrollDist||24;this.unpairedPanelHidden=false;this.pairedPanelHidden=false;this.$dragging=null;this._setUpBehaviors();this._dataSetUp()},commonFilters:{none:["",""],illumina:["_1","_2"]},DEFAULT_FILTERS:"illumina",strategies:{lcs:"autoPairLCSs",levenshtein:"autoPairLevenshtein"},DEFAULT_STRATEGY:"lcs",_dataSetUp:function(){this.paired=[];this.unpaired=[];this.selectedIds=[];this._sortInitialList();this._ensureIds();this.unpaired=this.initialList.slice(0);if(this.automaticallyPair){this.autoPair();this.once("rendered:initial",function(){this.trigger("autopair")})}},_sortInitialList:function(){this._sortDatasetList(this.initialList)},_sortDatasetList:function(h){h.sort(function(j,i){return naturalSort(j.name,i.name)});return h},_ensureIds:function(){this.initialList.forEach(function(h){if(!h.hasOwnProperty("id")){h.id=_.uniqueId()}});return this.initialList},_splitByFilters:function(j){var i=[],h=[];this.unpaired.forEach(function(k){if(this._filterFwdFn(k)){i.push(k)}if(this._filterRevFn(k)){h.push(k)}}.bind(this));return[i,h]},_filterFwdFn:function(i){var h=new RegExp(this.filters[0]);return h.test(i.name)},_filterRevFn:function(i){var h=new RegExp(this.filters[1]);return h.test(i.name)},_addToUnpaired:function(i){var h=function(j,l){if(j===l){return j}var k=Math.floor((l-j)/2)+j,m=naturalSort(i.name,this.unpaired[k].name);if(m<0){return h(j,k)}else{if(m>0){return h(k+1,l)}}while(this.unpaired[k]&&this.unpaired[k].name===i.name){k++}return k}.bind(this);this.unpaired.splice(h(0,this.unpaired.length),0,i)},autoPair:function(i){i=i||this.strategy;var h=this.simpleAutoPair();h=h.concat(this[i].call(this));return h},simpleAutoPair:function(){var o=0,m,s=this._splitByFilters(),h=s[0],r=s[1],q,u,k=false,t=[];while(o<h.length){var n=h[o];q=n.name.replace(this.filters[0],"");k=false;for(m=0;m<r.length;m++){var p=r[m];u=p.name.replace(this.filters[1],"");if(n!==p&&q===u){k=true;var l=this._pair(h.splice(o,1)[0],r.splice(m,1)[0],{silent:true});t.push(l);break}}if(!k){o+=1}}return t},autoPairLevenshtein:function(){var p=0,n,u=this._splitByFilters(),h=u[0],s=u[1],r,x,k,t,l,v=[];while(p<h.length){var o=h[p];r=o.name.replace(this.filters[0],"");l=Number.MAX_VALUE;for(n=0;n<s.length;n++){var q=s[n];x=q.name.replace(this.filters[1],"");if(o!==q){if(r===x){t=n;l=0;break}k=levenshteinDistance(r,x);if(k<l){t=n;l=k}}}var w=1-(l/(Math.max(r.length,x.length)));if(w>=this.matchPercentage){var m=this._pair(h.splice(p,1)[0],s.splice(t,1)[0],{silent:true});v.push(m);if(h.length<=0||s.length<=0){return v}}else{p+=1}}return v},autoPairLCSs:function(){var n=0,l,u=this._splitByFilters(),h=u[0],s=u[1],r,y,x,t,p,v=[];if(!h.length||!s.length){return v}while(n<h.length){var m=h[n];r=m.name.replace(this.filters[0],"");p=0;for(l=0;l<s.length;l++){var q=s[l];y=q.name.replace(this.filters[1],"");if(m!==q){if(r===y){t=l;p=r.length;break}var o=this._naiveStartingAndEndingLCS(r,y);x=o.length;if(x>p){t=l;p=x}}}var w=p/(Math.min(r.length,y.length));if(w>=this.matchPercentage){var k=this._pair(h.splice(n,1)[0],s.splice(t,1)[0],{silent:true});v.push(k);if(h.length<=0||s.length<=0){return v}}else{n+=1}}return v},_naiveStartingAndEndingLCS:function(m,k){var n="",o="",l=0,h=0;while(l<m.length&&l<k.length){if(m[l]!==k[l]){break}n+=m[l];l+=1}if(l===m.length){return m}if(l===k.length){return k}l=(m.length-1);h=(k.length-1);while(l>=0&&h>=0){if(m[l]!==k[h]){break}o=[m[l],o].join("");l-=1;h-=1}return n+o},_pair:function(j,h,i){i=i||{};var k=this._createPair(j,h,i.name);this.paired.push(k);this.unpaired=_.without(this.unpaired,j,h);if(!i.silent){this.trigger("pair:new",k)}return k},_createPair:function(j,h,i){if(!(j&&h)||(j===h)){throw new Error("Bad pairing: "+[JSON.stringify(j),JSON.stringify(h)])}i=i||this._guessNameForPair(j,h);return{forward:j,name:i,reverse:h}},_guessNameForPair:function(j,h,k){k=(k!==undefined)?(k):(this.removeExtensions);var i=this._naiveStartingAndEndingLCS(j.name.replace(this.filters[0],""),h.name.replace(this.filters[1],""));if(k){var l=i.lastIndexOf(".");if(l>0){i=i.slice(0,l)}}return i||(j.name+" & "+h.name)},_unpair:function(i,h){h=h||{};if(!i){throw new Error("Bad pair: "+JSON.stringify(i))}this.paired=_.without(this.paired,i);this._addToUnpaired(i.forward);this._addToUnpaired(i.reverse);if(!h.silent){this.trigger("pair:unpair",[i])}return i},unpairAll:function(){var h=[];while(this.paired.length){h.push(this._unpair(this.paired[0],{silent:true}))}this.trigger("pair:unpair",h)},_pairToJSON:function(h){return{collection_type:"paired",src:"new_collection",name:h.name,element_identifiers:[{name:"forward",id:h.forward.id,src:"hda"},{name:"reverse",id:h.reverse.id,src:"hda"}]}},createList:function(){var j=this,i;if(j.historyId){i="/api/histories/"+this.historyId+"/contents/dataset_collections"}var h={type:"dataset_collection",collection_type:"list:paired",name:_.escape(j.$(".collection-name").val()),element_identifiers:j.paired.map(function(k){return j._pairToJSON(k)})};return jQuery.ajax(i,{type:"POST",contentType:"application/json",dataType:"json",data:JSON.stringify(h)}).fail(function(m,k,l){j._ajaxErrHandler(m,k,l)}).done(function(k,l,m){j.trigger("collection:created",k,l,m);if(typeof j.oncreate==="function"){j.oncreate.call(this,k,l,m)}})},_ajaxErrHandler:function(k,h,j){this.error(k,h,j);var i=d("An error occurred while creating this collection");if(k){if(k.readyState===0&&k.status===0){i+=": "+d("Galaxy could not be reached and may be updating.")+d(" Try again in a few minutes.")}else{if(k.responseJSON){i+="<br /><pre>"+JSON.stringify(k.responseJSON)+"</pre>"}else{i+=": "+j}}}creator._showAlert(i,"alert-danger")},render:function(h,i){this.$el.empty().html(e.templates.main());this._renderHeader(h);this._renderMiddle(h);this._renderFooter(h);this._addPluginComponents();this.trigger("rendered",this);return this},_renderHeader:function(i,j){var h=this.$(".header").empty().html(e.templates.header()).find(".help-content").prepend($(e.templates.helpContent()));this._renderFilters();return h},_renderFilters:function(){return this.$(".forward-column .column-header input").val(this.filters[0]).add(this.$(".reverse-column .column-header input").val(this.filters[1]))},_renderMiddle:function(i,j){var h=this.$(".middle").empty().html(e.templates.middle());if(this.unpairedPanelHidden){this.$(".unpaired-columns").hide()}else{if(this.pairedPanelHidden){this.$(".paired-columns").hide()}}this._renderUnpaired();this._renderPaired();return h},_renderUnpaired:function(m,n){var k=this,l,i,h=[],j=this._splitByFilters();this.$(".forward-column .title").text([j[0].length,d("unpaired forward")].join(" "));this.$(".forward-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[0].length));this.$(".reverse-column .title").text([j[1].length,d("unpaired reverse")].join(" "));this.$(".reverse-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[1].length));this.$(".unpaired-columns .column-datasets").empty();this.$(".autopair-link").toggle(this.unpaired.length!==0);if(this.unpaired.length===0){this._renderUnpairedEmpty();return}i=j[1].map(function(p,o){if((j[0][o]!==undefined)&&(j[0][o]!==p)){h.push(k._renderPairButton())}return k._renderUnpairedDataset(p)});l=j[0].map(function(o){return k._renderUnpairedDataset(o)});if(!l.length&&!i.length){this._renderUnpairedNotShown();return}this.$(".unpaired-columns .forward-column .column-datasets").append(l).add(this.$(".unpaired-columns .paired-column .column-datasets").append(h)).add(this.$(".unpaired-columns .reverse-column .column-datasets").append(i));this._adjUnpairedOnScrollbar()},_renderUnpairedDisplayStr:function(h){return["(",h," ",d("filtered out"),")"].join("")},_renderUnpairedDataset:function(h){return $("<li/>").attr("id","dataset-"+h.id).addClass("dataset unpaired").attr("draggable",true).addClass(h.selected?"selected":"").append($("<span/>").addClass("dataset-name").text(h.name)).data("dataset",h)},_renderPairButton:function(){return $("<li/>").addClass("dataset unpaired").append($("<span/>").addClass("dataset-name").text(d("Pair these datasets")))},_renderUnpairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no remaining unpaired datasets")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_renderUnpairedNotShown:function(){var h=$('<div class="empty-message"></div>').text("("+d("no datasets were found matching the current filters")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_adjUnpairedOnScrollbar:function(){var k=this.$(".unpaired-columns").last(),l=this.$(".unpaired-columns .reverse-column .dataset").first();if(!l.size()){return}var h=k.offset().left+k.outerWidth(),j=l.offset().left+l.outerWidth(),i=Math.floor(h)-Math.floor(j);this.$(".unpaired-columns .forward-column").css("margin-left",(i>0)?i:0)},_renderPaired:function(i,j){this.$(".paired-column-title .title").text([this.paired.length,d("paired")].join(" "));this.$(".unpair-all-link").toggle(this.paired.length!==0);if(this.paired.length===0){this._renderPairedEmpty();return}else{this.$(".remove-extensions-link").show()}this.$(".paired-columns .column-datasets").empty();var h=this;this.paired.forEach(function(m,k){var l=new f({pair:m});h.$(".paired-columns .column-datasets").append(l.render().$el).append(['<button class="unpair-btn">','<span class="fa fa-unlink" title="',d("Unpair"),'"></span>',"</button>"].join(""))})},_renderPairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no paired datasets yet")+")");this.$(".paired-columns .column-datasets").empty().prepend(h);return h},_renderFooter:function(i,j){var h=this.$(".footer").empty().html(e.templates.footer());this.$(".remove-extensions").prop("checked",this.removeExtensions);if(typeof this.oncancel==="function"){this.$(".cancel-create.btn").show()}return h},_addPluginComponents:function(){this._chooseFiltersPopover(".choose-filters-link");this.$(".help-content i").hoverhighlight(".collection-creator","rgba( 64, 255, 255, 1.0 )")},_chooseFiltersPopover:function(h){function i(l,k){return['<button class="filter-choice btn" ','data-forward="',l,'" data-reverse="',k,'">',d("Forward"),": ",l,", ",d("Reverse"),": ",k,"</button>"].join("")}var j=$(_.template(['<div class="choose-filters">','<div class="help">',d("Choose from the following filters to change which unpaired reads are shown in the display"),":</div>",i("_1","_2"),i("_R1","_R2"),"</div>"].join(""),{}));return this.$(h).popover({container:".collection-creator",placement:"bottom",html:true,content:j})},_validationWarning:function(i,h){var j="validation-warning";if(i==="name"){i=this.$(".collection-name").add(this.$(".collection-name-prompt"));this.$(".collection-name").focus().select()}if(h){i=i||this.$("."+j);i.removeClass(j)}else{i.addClass(j)}},_setUpBehaviors:function(){this.once("rendered",function(){this.trigger("rendered:initial",this)});this.on("pair:new",function(){this._renderUnpaired();this._renderPaired();this.$(".paired-columns").scrollTop(8000000)});this.on("pair:unpair",function(h){this._renderUnpaired();this._renderPaired();this.splitView()});this.on("filter-change",function(){this.filters=[this.$(".forward-unpaired-filter input").val(),this.$(".reverse-unpaired-filter input").val()];this._renderFilters();this._renderUnpaired()});this.on("autopair",function(){this._renderUnpaired();this._renderPaired();var h,i=null;if(this.paired.length){i="alert-success";h=this.paired.length+" "+d("pairs created");if(!this.unpaired.length){h+=": "+d("all datasets have been successfully paired");this.hideUnpaired();this.$(".collection-name").focus()}}else{h=d("Could not automatically create any pairs from the given dataset names")}this._showAlert(h,i)});return this},events:{"click .more-help":"_clickMoreHelp","click .less-help":"_clickLessHelp","click .header .alert button":"_hideAlert","click .forward-column .column-title":"_clickShowOnlyUnpaired","click .reverse-column .column-title":"_clickShowOnlyUnpaired","click .unpair-all-link":"_clickUnpairAll","change .forward-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .forward-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .autopair-link":"_clickAutopair","click .choose-filters .filter-choice":"_clickFilterChoice","click .clear-filters-link":"_clearFilters","change .reverse-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .reverse-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .forward-column .dataset.unpaired":"_clickUnpairedDataset","click .reverse-column .dataset.unpaired":"_clickUnpairedDataset","click .paired-column .dataset.unpaired":"_clickPairRow","click .unpaired-columns":"clearSelectedUnpaired","mousedown .unpaired-columns .dataset":"_mousedownUnpaired","click .paired-column-title":"_clickShowOnlyPaired","mousedown .flexible-partition-drag":"_startPartitionDrag","click .paired-columns .dataset.paired":"selectPair","click .paired-columns":"clearSelectedPaired","click .paired-columns .pair-name":"_clickPairName","click .unpair-btn":"_clickUnpair","dragover .paired-columns .column-datasets":"_dragoverPairedColumns","drop .paired-columns .column-datasets":"_dropPairedColumns","pair.dragstart .paired-columns .column-datasets":"_pairDragstart","pair.dragend .paired-columns .column-datasets":"_pairDragend","change .remove-extensions":function(h){this.toggleExtensions()},"change .collection-name":"_changeName","keydown .collection-name":"_nameCheckForEnter","click .cancel-create":function(h){if(typeof this.oncancel==="function"){this.oncancel.call(this)}},"click .create-collection":"_clickCreate"},_clickMoreHelp:function(h){this.$(".main-help").addClass("expanded");this.$(".more-help").hide()},_clickLessHelp:function(h){this.$(".main-help").removeClass("expanded");this.$(".more-help").show()},_showAlert:function(i,h){h=h||"alert-danger";this.$(".main-help").hide();this.$(".header .alert").attr("class","alert alert-dismissable").addClass(h).show().find(".alert-message").html(i)},_hideAlert:function(h){this.$(".main-help").show();this.$(".header .alert").hide()},_clickShowOnlyUnpaired:function(h){if(this.$(".paired-columns").is(":visible")){this.hidePaired()}else{this.splitView()}},_clickShowOnlyPaired:function(h){if(this.$(".unpaired-columns").is(":visible")){this.hideUnpaired()}else{this.splitView()}},hideUnpaired:function(h,i){this.unpairedPanelHidden=true;this.pairedPanelHidden=false;this._renderMiddle(h,i)},hidePaired:function(h,i){this.unpairedPanelHidden=false;this.pairedPanelHidden=true;this._renderMiddle(h,i)},splitView:function(h,i){this.unpairedPanelHidden=this.pairedPanelHidden=false;this._renderMiddle(h,i);return this},_clickUnpairAll:function(h){this.unpairAll()},_clickAutopair:function(h){this.autoPair();this.trigger("autopair")},_clickFilterChoice:function(i){var h=$(i.currentTarget);this.$(".forward-unpaired-filter input").val(h.data("forward"));this.$(".reverse-unpaired-filter input").val(h.data("reverse"));this._hideChooseFilters();this.trigger("filter-change")},_hideChooseFilters:function(){this.$(".choose-filters-link").popover("hide");this.$(".popover").css("display","none")},_clearFilters:function(h){this.$(".forward-unpaired-filter input").val("");this.$(".reverse-unpaired-filter input").val("");this.trigger("filter-change")},_clickUnpairedDataset:function(h){h.stopPropagation();return this.toggleSelectUnpaired($(h.currentTarget))},toggleSelectUnpaired:function(j,i){i=i||{};var k=j.data("dataset"),h=i.force!==undefined?i.force:!j.hasClass("selected");if(!j.size()||k===undefined){return j}if(h){j.addClass("selected");if(!i.waitToPair){this.pairAllSelected()}}else{j.removeClass("selected")}return j},pairAllSelected:function(i){i=i||{};var j=this,k=[],h=[],l=[];j.$(".unpaired-columns .forward-column .dataset.selected").each(function(){k.push($(this).data("dataset"))});j.$(".unpaired-columns .reverse-column .dataset.selected").each(function(){h.push($(this).data("dataset"))});k.length=h.length=Math.min(k.length,h.length);k.forEach(function(n,m){try{l.push(j._pair(n,h[m],{silent:true}))}catch(o){j.error(o)}});if(l.length&&!i.silent){this.trigger("pair:new",l)}return l},clearSelectedUnpaired:function(){this.$(".unpaired-columns .dataset.selected").removeClass("selected")},_mousedownUnpaired:function(j){if(j.shiftKey){var i=this,h=$(j.target).addClass("selected"),k=function(l){i.$(l.target).filter(".dataset").addClass("selected")};h.parent().on("mousemove",k);$(document).one("mouseup",function(l){h.parent().off("mousemove",k);i.pairAllSelected()})}},_clickPairRow:function(j){var k=$(j.currentTarget).index(),i=$(".unpaired-columns .forward-column .dataset").eq(k).data("dataset"),h=$(".unpaired-columns .reverse-column .dataset").eq(k).data("dataset");this._pair(i,h)},_startPartitionDrag:function(i){var h=this,l=i.pageY;$("body").css("cursor","ns-resize");h.$(".flexible-partition-drag").css("color","black");function k(m){h.$(".flexible-partition-drag").css("color","");$("body").css("cursor","").unbind("mousemove",j)}function j(m){var n=m.pageY-l;if(!h.adjPartition(n)){$("body").trigger("mouseup")}h._adjUnpairedOnScrollbar();l+=n}$("body").mousemove(j);$("body").one("mouseup",k)},adjPartition:function(i){var h=this.$(".unpaired-columns"),j=this.$(".paired-columns"),k=parseInt(h.css("height"),10),l=parseInt(j.css("height"),10);k=Math.max(10,k+i);l=l-i;var m=i<0;if(m){if(this.unpairedPanelHidden){return false}else{if(k<=10){this.hideUnpaired();return false}}}else{if(this.unpairedPanelHidden){h.show();this.unpairedPanelHidden=false}}if(!m){if(this.pairedPanelHidden){return false}else{if(l<=15){this.hidePaired();return false}}}else{if(this.pairedPanelHidden){j.show();this.pairedPanelHidden=false}}h.css({height:k+"px",flex:"0 0 auto"});return true},selectPair:function(h){h.stopPropagation();$(h.currentTarget).toggleClass("selected")},clearSelectedPaired:function(h){this.$(".paired-columns .dataset.selected").removeClass("selected")},_clickPairName:function(j){j.stopPropagation();var i=$(j.currentTarget),k=this.paired[i.parent().parent().index()/2],h=prompt("Enter a new name for the pair:",k.name);if(h){k.name=h;k.customizedName=true;i.text(k.name)}},_clickUnpair:function(i){var h=Math.floor($(i.currentTarget).index()/2);this._unpair(this.paired[h])},_dragoverPairedColumns:function(k){k.preventDefault();var i=this.$(".paired-columns .column-datasets");this._checkForAutoscroll(i,k.originalEvent.clientY);var j=this._getNearestPairedDatasetLi(k.originalEvent.clientY);$(".paired-drop-placeholder").remove();var h=$('<div class="paired-drop-placeholder"></div>');if(!j.size()){i.append(h)}else{j.before(h)}},_checkForAutoscroll:function(h,n){var l=2;var m=h.offset(),k=h.scrollTop(),i=n-m.top,j=(m.top+h.outerHeight())-n;if(i>=0&&i<this.autoscrollDist){h.scrollTop(k-l)}else{if(j>=0&&j<this.autoscrollDist){h.scrollTop(k+l)}}},_getNearestPairedDatasetLi:function(o){var l=4,j=this.$(".paired-columns .column-datasets li").toArray();for(var k=0;k<j.length;k++){var n=$(j[k]),m=n.offset().top,h=Math.floor(n.outerHeight()/2)+l;if(m+h>o&&m-h<o){return n}}return $()},_dropPairedColumns:function(i){i.preventDefault();i.dataTransfer.dropEffect="move";var h=this._getNearestPairedDatasetLi(i.originalEvent.clientY);if(h.size()){this.$dragging.insertBefore(h)}else{this.$dragging.insertAfter(this.$(".paired-columns .unpair-btn").last())}this._syncPairsToDom();return false},_syncPairsToDom:function(){var h=[];this.$(".paired-columns .dataset.paired").each(function(){h.push($(this).data("pair"))});this.paired=h;this._renderPaired()},_pairDragstart:function(i,j){j.$el.addClass("selected");var h=this.$(".paired-columns .dataset.selected");this.$dragging=h},_pairDragend:function(h,i){$(".paired-drop-placeholder").remove();this.$dragging=null},toggleExtensions:function(i){var h=this;h.removeExtensions=(i!==undefined)?(i):(!h.removeExtensions);_.each(h.paired,function(j){if(j.customizedName){return}j.name=h._guessNameForPair(j.forward,j.reverse)});h._renderPaired();h._renderFooter()},_changeName:function(h){this._validationWarning("name",!!this._getName())},_nameCheckForEnter:function(h){if(h.keyCode===13){this._clickCreate()}},_getName:function(){return _.escape(this.$(".collection-name").val())},_clickCreate:function(i){var h=this._getName();if(!h){this._validationWarning("name")}else{this.createList()}},_printList:function(i){var h=this;_.each(i,function(j){if(i===h.paired){h._printPair(j)}else{}})},_printPair:function(h){this.debug(h.forward.name,h.reverse.name,": ->",h.name)},toString:function(){return"PairedCollectionCreator"}});e.templates=e.templates||{main:_.template(['<div class="header flex-row no-flex"></div>','<div class="middle flex-row flex-row-container"></div>','<div class="footer flex-row no-flex">'].join("")),header:_.template(['<div class="main-help well clear">','<a class="more-help" href="javascript:void(0);">',d("More help"),"</a>",'<div class="help-content">','<a class="less-help" href="javascript:void(0);">',d("Less"),"</a>","</div>","</div>",'<div class="alert alert-dismissable">','<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>','<span class="alert-message"></span>',"</div>",'<div class="column-headers vertically-spaced flex-column-container">','<div class="forward-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired forward"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter forward-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>",'<div class="paired-column flex-column no-flex column">','<div class="column-header">','<a class="choose-filters-link" href="javascript:void(0)">',d("Choose filters"),"</a>",'<a class="clear-filters-link" href="javascript:void(0);">',d("Clear filters"),"</a><br />",'<a class="autopair-link" href="javascript:void(0);">',d("Auto-pair"),"</a>","</div>","</div>",'<div class="reverse-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired reverse"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter reverse-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>","</div>"].join("")),middle:_.template(['<div class="unpaired-columns flex-column-container scroll-container flex-row">','<div class="forward-column flex-column column">','<ol class="column-datasets"></ol>',"</div>",'<div class="paired-column flex-column no-flex column">','<ol class="column-datasets"></ol>',"</div>",'<div class="reverse-column flex-column column">','<ol class="column-datasets"></ol>',"</div>","</div>",'<div class="flexible-partition">','<div class="flexible-partition-drag" title="',d("Drag to change"),'"></div>','<div class="column-header">','<div class="column-title paired-column-title">','<span class="title"></span>',"</div>",'<a class="unpair-all-link" href="javascript:void(0);">',d("Unpair all"),"</a>","</div>","</div>",'<div class="paired-columns flex-column-container scroll-container flex-row">','<ol class="column-datasets"></ol>',"</div>"].join("")),footer:_.template(['<div class="attributes clear">','<div class="clear">','<label class="remove-extensions-prompt pull-right">',d("Remove file extensions from pair names"),"?",'<input class="remove-extensions pull-right" type="checkbox" />',"</label>","</div>",'<div class="clear">','<input class="collection-name form-control pull-right" ','placeholder="',d("Enter a name for your new list"),'" />','<div class="collection-name-prompt pull-right">',d("Name"),":</div>","</div>","</div>",'<div class="actions clear vertically-spaced">','<div class="other-options pull-left">','<button class="cancel-create btn" tabindex="-1">',d("Cancel"),"</button>",'<div class="create-other btn-group dropup">','<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">',d("Create a different kind of collection"),' <span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">','<li><a href="#">',d("Create a <i>single</i> pair"),"</a></li>",'<li><a href="#">',d("Create a list of <i>unpaired</i> datasets"),"</a></li>","</ul>","</div>","</div>",'<div class="main-options pull-right">','<button class="create-collection btn btn-primary">',d("Create list"),"</button>","</div>","</div>"].join("")),helpContent:_.template(["<p>",d(["Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). ","These collections can be passed to tools and workflows in order to have analyses done on each member of ","the entire group. This interface allows you to create a collection, choose which datasets are paired, ","and re-order the final collection."].join("")),"</p>","<p>",d(['Unpaired datasets are shown in the <i data-target=".unpaired-columns">unpaired section</i> ',"(hover over the underlined words to highlight below). ",'Paired datasets are shown in the <i data-target=".paired-columns">paired section</i>.',"<ul>To pair datasets, you can:","<li>Click a dataset in the ",'<i data-target=".unpaired-columns .forward-column .column-datasets,','.unpaired-columns .forward-column">forward column</i> ',"to select it then click a dataset in the ",'<i data-target=".unpaired-columns .reverse-column .column-datasets,','.unpaired-columns .reverse-column">reverse column</i>.',"</li>",'<li>Click one of the "Pair these datasets" buttons in the ','<i data-target=".unpaired-columns .paired-column .column-datasets,','.unpaired-columns .paired-column">middle column</i> ',"to pair the datasets in a particular row.","</li>",'<li>Click <i data-target=".autopair-link">"Auto-pair"</i> ',"to have your datasets automatically paired based on name.","</li>","</ul>"].join("")),"</p>","<p>",d(["<ul>You can filter what is shown in the unpaired sections by:","<li>Entering partial dataset names in either the ",'<i data-target=".forward-unpaired-filter input">forward filter</i> or ','<i data-target=".reverse-unpaired-filter input">reverse filter</i>.',"</li>","<li>Choosing from a list of preset filters by clicking the ",'<i data-target=".choose-filters-link">"Choose filters" link</i>.',"</li>","<li>Entering regular expressions to match dataset names. See: ",'<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expre…"',' target="_blank">MDN\'s JavaScript Regular Expression Tutorial</a>. ',"Note: forward slashes (\\) are not needed.","</li>","<li>Clearing the filters by clicking the ",'<i data-target=".clear-filters-link">"Clear filters" link</i>.',"</li>","</ul>"].join("")),"</p>","<p>",d(["To unpair individual dataset pairs, click the ",'<i data-target=".unpair-btn">unpair buttons ( <span class="fa fa-unlink"></span> )</i>. ','Click the <i data-target=".unpair-all-link">"Unpair all" link</i> to unpair all pairs.'].join("")),"</p>","<p>",d(['You can include or remove the file extensions (e.g. ".fastq") from your pair names by toggling the ','<i data-target=".remove-extensions-prompt">"Remove file extensions from pair names?"</i> control.'].join("")),"</p>","<p>",d(['Once your collection is complete, enter a <i data-target=".collection-name">name</i> and ','click <i data-target=".create-collection">"Create list"</i>. ',"(Note: you do not have to pair all unpaired datasets to finish.)"].join("")),"</p>"].join(""))};(function(){jQuery.fn.extend({hoverhighlight:function h(j,i){j=j||"body";if(!this.size()){return this}$(this).each(function(){var l=$(this),k=l.data("target");if(k){l.mouseover(function(m){$(k,j).css({background:i})}).mouseout(function(m){$(k).css({background:""})})}});return this}})}());var b=function c(j,h){h=_.defaults(h||{},{datasets:j,oncancel:function(){Galaxy.modal.hide()},oncreate:function(){Galaxy.modal.hide();Galaxy.currHistoryPanel.refreshContents()}});if(!window.Galaxy||!Galaxy.modal){throw new Error("Galaxy or Galaxy.modal not found")}var i=new e(h).render();Galaxy.modal.show({title:"Create a collection of paired datasets",body:i.$el,width:"80%",height:"800px",closing_events:true});window.PCC=i;return i};return{PairedCollectionCreator:e,pairedCollectionCreatorModal:b}});
\ No newline at end of file
+define(["utils/levenshtein","mvc/base-mvc","utils/localization"],function(g,a,d){var f=Backbone.View.extend(a.LoggableMixin).extend({tagName:"li",className:"dataset paired",initialize:function(h){this.pair=h.pair||{}},template:_.template(['<span class="forward-dataset-name flex-column"><%= pair.forward.name %></span>','<span class="pair-name-column flex-column">','<span class="pair-name"><%= pair.name %></span>',"</span>",'<span class="reverse-dataset-name flex-column"><%= pair.reverse.name %></span>'].join("")),render:function(){this.$el.attr("draggable",true).data("pair",this.pair).html(this.template({pair:this.pair})).addClass("flex-column-container");return this},events:{dragstart:"_dragstart",dragend:"_dragend",dragover:"_sendToParent",drop:"_sendToParent"},_dragstart:function(h){h.currentTarget.style.opacity="0.4";if(h.originalEvent){h=h.originalEvent}h.dataTransfer.effectAllowed="move";h.dataTransfer.setData("text/plain",JSON.stringify(this.pair));this.$el.parent().trigger("pair.dragstart",[this])},_dragend:function(h){h.currentTarget.style.opacity="1.0";this.$el.parent().trigger("pair.dragend",[this])},_sendToParent:function(h){this.$el.parent().trigger(h)},toString:function(){return"PairView("+this.pair.name+")"}});var e=Backbone.View.extend(a.LoggableMixin).extend({className:"collection-creator flex-row-container",initialize:function(h){h=_.defaults(h,{datasets:[],filters:this.DEFAULT_FILTERS,automaticallyPair:true,matchPercentage:1,strategy:"lcs"});this.initialList=h.datasets;this.historyId=h.historyId;this.filters=this.commonFilters[h.filters]||this.commonFilters[this.DEFAULT_FILTERS];if(_.isArray(h.filters)){this.filters=h.filters}this.automaticallyPair=h.automaticallyPair;this.matchPercentage=h.matchPercentage;this.strategy=this.strategies[h.strategy]||this.strategies[this.DEFAULT_STRATEGY];if(_.isFunction(h.strategy)){this.strategy=h.strategy}this.removeExtensions=true;this.oncancel=h.oncancel;this.oncreate=h.oncreate;this.autoscrollDist=h.autoscrollDist||24;this.unpairedPanelHidden=false;this.pairedPanelHidden=false;this.$dragging=null;this._setUpBehaviors();this._dataSetUp()},commonFilters:{none:["",""],illumina:["_1","_2"]},DEFAULT_FILTERS:"illumina",strategies:{lcs:"autoPairLCSs",levenshtein:"autoPairLevenshtein"},DEFAULT_STRATEGY:"lcs",_dataSetUp:function(){this.paired=[];this.unpaired=[];this.selectedIds=[];this._sortInitialList();this._ensureIds();this.unpaired=this.initialList.slice(0);if(this.automaticallyPair){this.autoPair();this.once("rendered:initial",function(){this.trigger("autopair")})}},_sortInitialList:function(){this._sortDatasetList(this.initialList)},_sortDatasetList:function(h){h.sort(function(j,i){return naturalSort(j.name,i.name)});return h},_ensureIds:function(){this.initialList.forEach(function(h){if(!h.hasOwnProperty("id")){h.id=_.uniqueId()}});return this.initialList},_splitByFilters:function(j){var i=[],h=[];this.unpaired.forEach(function(k){if(this._filterFwdFn(k)){i.push(k)}if(this._filterRevFn(k)){h.push(k)}}.bind(this));return[i,h]},_filterFwdFn:function(i){var h=new RegExp(this.filters[0]);return h.test(i.name)},_filterRevFn:function(i){var h=new RegExp(this.filters[1]);return h.test(i.name)},_addToUnpaired:function(i){var h=function(j,l){if(j===l){return j}var k=Math.floor((l-j)/2)+j,m=naturalSort(i.name,this.unpaired[k].name);if(m<0){return h(j,k)}else{if(m>0){return h(k+1,l)}}while(this.unpaired[k]&&this.unpaired[k].name===i.name){k++}return k}.bind(this);this.unpaired.splice(h(0,this.unpaired.length),0,i)},autoPair:function(i){i=i||this.strategy;var h=this.simpleAutoPair();h=h.concat(this[i].call(this));return h},simpleAutoPair:function(){var o=0,m,s=this._splitByFilters(),h=s[0],r=s[1],q,u,k=false,t=[];while(o<h.length){var n=h[o];q=n.name.replace(this.filters[0],"");k=false;for(m=0;m<r.length;m++){var p=r[m];u=p.name.replace(this.filters[1],"");if(n!==p&&q===u){k=true;var l=this._pair(h.splice(o,1)[0],r.splice(m,1)[0],{silent:true});t.push(l);break}}if(!k){o+=1}}return t},autoPairLevenshtein:function(){var p=0,n,u=this._splitByFilters(),h=u[0],s=u[1],r,x,k,t,l,v=[];while(p<h.length){var o=h[p];r=o.name.replace(this.filters[0],"");l=Number.MAX_VALUE;for(n=0;n<s.length;n++){var q=s[n];x=q.name.replace(this.filters[1],"");if(o!==q){if(r===x){t=n;l=0;break}k=levenshteinDistance(r,x);if(k<l){t=n;l=k}}}var w=1-(l/(Math.max(r.length,x.length)));if(w>=this.matchPercentage){var m=this._pair(h.splice(p,1)[0],s.splice(t,1)[0],{silent:true});v.push(m);if(h.length<=0||s.length<=0){return v}}else{p+=1}}return v},autoPairLCSs:function(){var n=0,l,u=this._splitByFilters(),h=u[0],s=u[1],r,y,x,t,p,v=[];if(!h.length||!s.length){return v}while(n<h.length){var m=h[n];r=m.name.replace(this.filters[0],"");p=0;for(l=0;l<s.length;l++){var q=s[l];y=q.name.replace(this.filters[1],"");if(m!==q){if(r===y){t=l;p=r.length;break}var o=this._naiveStartingAndEndingLCS(r,y);x=o.length;if(x>p){t=l;p=x}}}var w=p/(Math.min(r.length,y.length));if(w>=this.matchPercentage){var k=this._pair(h.splice(n,1)[0],s.splice(t,1)[0],{silent:true});v.push(k);if(h.length<=0||s.length<=0){return v}}else{n+=1}}return v},_naiveStartingAndEndingLCS:function(m,k){var n="",o="",l=0,h=0;while(l<m.length&&l<k.length){if(m[l]!==k[l]){break}n+=m[l];l+=1}if(l===m.length){return m}if(l===k.length){return k}l=(m.length-1);h=(k.length-1);while(l>=0&&h>=0){if(m[l]!==k[h]){break}o=[m[l],o].join("");l-=1;h-=1}return n+o},_pair:function(j,h,i){i=i||{};var k=this._createPair(j,h,i.name);this.paired.push(k);this.unpaired=_.without(this.unpaired,j,h);if(!i.silent){this.trigger("pair:new",k)}return k},_createPair:function(j,h,i){if(!(j&&h)||(j===h)){throw new Error("Bad pairing: "+[JSON.stringify(j),JSON.stringify(h)])}i=i||this._guessNameForPair(j,h);return{forward:j,name:i,reverse:h}},_guessNameForPair:function(j,h,k){k=(k!==undefined)?(k):(this.removeExtensions);var i=this._naiveStartingAndEndingLCS(j.name.replace(this.filters[0],""),h.name.replace(this.filters[1],""));if(k){var l=i.lastIndexOf(".");if(l>0){i=i.slice(0,l)}}return i||(j.name+" & "+h.name)},_unpair:function(i,h){h=h||{};if(!i){throw new Error("Bad pair: "+JSON.stringify(i))}this.paired=_.without(this.paired,i);this._addToUnpaired(i.forward);this._addToUnpaired(i.reverse);if(!h.silent){this.trigger("pair:unpair",[i])}return i},unpairAll:function(){var h=[];while(this.paired.length){h.push(this._unpair(this.paired[0],{silent:true}))}this.trigger("pair:unpair",h)},_pairToJSON:function(h){return{collection_type:"paired",src:"new_collection",name:h.name,element_identifiers:[{name:"forward",id:h.forward.id,src:"hda"},{name:"reverse",id:h.reverse.id,src:"hda"}]}},createList:function(){var j=this,i;if(j.historyId){i="/api/histories/"+this.historyId+"/contents/dataset_collections"}var h={type:"dataset_collection",collection_type:"list:paired",name:_.escape(j.$(".collection-name").val()),element_identifiers:j.paired.map(function(k){return j._pairToJSON(k)})};return jQuery.ajax(i,{type:"POST",contentType:"application/json",dataType:"json",data:JSON.stringify(h)}).fail(function(m,k,l){j._ajaxErrHandler(m,k,l)}).done(function(k,l,m){j.trigger("collection:created",k,l,m);if(typeof j.oncreate==="function"){j.oncreate.call(this,k,l,m)}})},_ajaxErrHandler:function(k,h,j){this.error(k,h,j);var i=d("An error occurred while creating this collection");if(k){if(k.readyState===0&&k.status===0){i+=": "+d("Galaxy could not be reached and may be updating.")+d(" Try again in a few minutes.")}else{if(k.responseJSON){i+="<br /><pre>"+JSON.stringify(k.responseJSON)+"</pre>"}else{i+=": "+j}}}creator._showAlert(i,"alert-danger")},render:function(h,i){this.$el.empty().html(e.templates.main());this._renderHeader(h);this._renderMiddle(h);this._renderFooter(h);this._addPluginComponents();this.trigger("rendered",this);return this},_renderHeader:function(i,j){var h=this.$(".header").empty().html(e.templates.header()).find(".help-content").prepend($(e.templates.helpContent()));this._renderFilters();return h},_renderFilters:function(){return this.$(".forward-column .column-header input").val(this.filters[0]).add(this.$(".reverse-column .column-header input").val(this.filters[1]))},_renderMiddle:function(i,j){var h=this.$(".middle").empty().html(e.templates.middle());if(this.unpairedPanelHidden){this.$(".unpaired-columns").hide()}else{if(this.pairedPanelHidden){this.$(".paired-columns").hide()}}this._renderUnpaired();this._renderPaired();return h},_renderUnpaired:function(m,n){var k=this,l,i,h=[],j=this._splitByFilters();this.$(".forward-column .title").text([j[0].length,d("unpaired forward")].join(" "));this.$(".forward-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[0].length));this.$(".reverse-column .title").text([j[1].length,d("unpaired reverse")].join(" "));this.$(".reverse-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[1].length));this.$(".unpaired-columns .column-datasets").empty();this.$(".autopair-link").toggle(this.unpaired.length!==0);if(this.unpaired.length===0){this._renderUnpairedEmpty();return}i=j[1].map(function(p,o){if((j[0][o]!==undefined)&&(j[0][o]!==p)){h.push(k._renderPairButton())}return k._renderUnpairedDataset(p)});l=j[0].map(function(o){return k._renderUnpairedDataset(o)});if(!l.length&&!i.length){this._renderUnpairedNotShown();return}this.$(".unpaired-columns .forward-column .column-datasets").append(l).add(this.$(".unpaired-columns .paired-column .column-datasets").append(h)).add(this.$(".unpaired-columns .reverse-column .column-datasets").append(i));this._adjUnpairedOnScrollbar()},_renderUnpairedDisplayStr:function(h){return["(",h," ",d("filtered out"),")"].join("")},_renderUnpairedDataset:function(h){return $("<li/>").attr("id","dataset-"+h.id).addClass("dataset unpaired").attr("draggable",true).addClass(h.selected?"selected":"").append($("<span/>").addClass("dataset-name").text(h.name)).data("dataset",h)},_renderPairButton:function(){return $("<li/>").addClass("dataset unpaired").append($("<span/>").addClass("dataset-name").text(d("Pair these datasets")))},_renderUnpairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no remaining unpaired datasets")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_renderUnpairedNotShown:function(){var h=$('<div class="empty-message"></div>').text("("+d("no datasets were found matching the current filters")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_adjUnpairedOnScrollbar:function(){var k=this.$(".unpaired-columns").last(),l=this.$(".unpaired-columns .reverse-column .dataset").first();if(!l.size()){return}var h=k.offset().left+k.outerWidth(),j=l.offset().left+l.outerWidth(),i=Math.floor(h)-Math.floor(j);this.$(".unpaired-columns .forward-column").css("margin-left",(i>0)?i:0)},_renderPaired:function(i,j){this.$(".paired-column-title .title").text([this.paired.length,d("paired")].join(" "));this.$(".unpair-all-link").toggle(this.paired.length!==0);if(this.paired.length===0){this._renderPairedEmpty();return}else{this.$(".remove-extensions-link").show()}this.$(".paired-columns .column-datasets").empty();var h=this;this.paired.forEach(function(m,k){var l=new f({pair:m});h.$(".paired-columns .column-datasets").append(l.render().$el).append(['<button class="unpair-btn">','<span class="fa fa-unlink" title="',d("Unpair"),'"></span>',"</button>"].join(""))})},_renderPairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no paired datasets yet")+")");this.$(".paired-columns .column-datasets").empty().prepend(h);return h},_renderFooter:function(i,j){var h=this.$(".footer").empty().html(e.templates.footer());this.$(".remove-extensions").prop("checked",this.removeExtensions);if(typeof this.oncancel==="function"){this.$(".cancel-create.btn").show()}return h},_addPluginComponents:function(){this._chooseFiltersPopover(".choose-filters-link");this.$(".help-content i").hoverhighlight(".collection-creator","rgba( 64, 255, 255, 1.0 )")},_chooseFiltersPopover:function(h){function i(l,k){return['<button class="filter-choice btn" ','data-forward="',l,'" data-reverse="',k,'">',d("Forward"),": ",l,", ",d("Reverse"),": ",k,"</button>"].join("")}var j=$(_.template(['<div class="choose-filters">','<div class="help">',d("Choose from the following filters to change which unpaired reads are shown in the display"),":</div>",i("_1","_2"),i("_R1","_R2"),"</div>"].join(""))({}));return this.$(h).popover({container:".collection-creator",placement:"bottom",html:true,content:j})},_validationWarning:function(i,h){var j="validation-warning";if(i==="name"){i=this.$(".collection-name").add(this.$(".collection-name-prompt"));this.$(".collection-name").focus().select()}if(h){i=i||this.$("."+j);i.removeClass(j)}else{i.addClass(j)}},_setUpBehaviors:function(){this.once("rendered",function(){this.trigger("rendered:initial",this)});this.on("pair:new",function(){this._renderUnpaired();this._renderPaired();this.$(".paired-columns").scrollTop(8000000)});this.on("pair:unpair",function(h){this._renderUnpaired();this._renderPaired();this.splitView()});this.on("filter-change",function(){this.filters=[this.$(".forward-unpaired-filter input").val(),this.$(".reverse-unpaired-filter input").val()];this._renderFilters();this._renderUnpaired()});this.on("autopair",function(){this._renderUnpaired();this._renderPaired();var h,i=null;if(this.paired.length){i="alert-success";h=this.paired.length+" "+d("pairs created");if(!this.unpaired.length){h+=": "+d("all datasets have been successfully paired");this.hideUnpaired();this.$(".collection-name").focus()}}else{h=d("Could not automatically create any pairs from the given dataset names")}this._showAlert(h,i)});return this},events:{"click .more-help":"_clickMoreHelp","click .less-help":"_clickLessHelp","click .header .alert button":"_hideAlert","click .forward-column .column-title":"_clickShowOnlyUnpaired","click .reverse-column .column-title":"_clickShowOnlyUnpaired","click .unpair-all-link":"_clickUnpairAll","change .forward-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .forward-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .autopair-link":"_clickAutopair","click .choose-filters .filter-choice":"_clickFilterChoice","click .clear-filters-link":"_clearFilters","change .reverse-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .reverse-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .forward-column .dataset.unpaired":"_clickUnpairedDataset","click .reverse-column .dataset.unpaired":"_clickUnpairedDataset","click .paired-column .dataset.unpaired":"_clickPairRow","click .unpaired-columns":"clearSelectedUnpaired","mousedown .unpaired-columns .dataset":"_mousedownUnpaired","click .paired-column-title":"_clickShowOnlyPaired","mousedown .flexible-partition-drag":"_startPartitionDrag","click .paired-columns .dataset.paired":"selectPair","click .paired-columns":"clearSelectedPaired","click .paired-columns .pair-name":"_clickPairName","click .unpair-btn":"_clickUnpair","dragover .paired-columns .column-datasets":"_dragoverPairedColumns","drop .paired-columns .column-datasets":"_dropPairedColumns","pair.dragstart .paired-columns .column-datasets":"_pairDragstart","pair.dragend .paired-columns .column-datasets":"_pairDragend","change .remove-extensions":function(h){this.toggleExtensions()},"change .collection-name":"_changeName","keydown .collection-name":"_nameCheckForEnter","click .cancel-create":function(h){if(typeof this.oncancel==="function"){this.oncancel.call(this)}},"click .create-collection":"_clickCreate"},_clickMoreHelp:function(h){this.$(".main-help").addClass("expanded");this.$(".more-help").hide()},_clickLessHelp:function(h){this.$(".main-help").removeClass("expanded");this.$(".more-help").show()},_showAlert:function(i,h){h=h||"alert-danger";this.$(".main-help").hide();this.$(".header .alert").attr("class","alert alert-dismissable").addClass(h).show().find(".alert-message").html(i)},_hideAlert:function(h){this.$(".main-help").show();this.$(".header .alert").hide()},_clickShowOnlyUnpaired:function(h){if(this.$(".paired-columns").is(":visible")){this.hidePaired()}else{this.splitView()}},_clickShowOnlyPaired:function(h){if(this.$(".unpaired-columns").is(":visible")){this.hideUnpaired()}else{this.splitView()}},hideUnpaired:function(h,i){this.unpairedPanelHidden=true;this.pairedPanelHidden=false;this._renderMiddle(h,i)},hidePaired:function(h,i){this.unpairedPanelHidden=false;this.pairedPanelHidden=true;this._renderMiddle(h,i)},splitView:function(h,i){this.unpairedPanelHidden=this.pairedPanelHidden=false;this._renderMiddle(h,i);return this},_clickUnpairAll:function(h){this.unpairAll()},_clickAutopair:function(h){this.autoPair();this.trigger("autopair")},_clickFilterChoice:function(i){var h=$(i.currentTarget);this.$(".forward-unpaired-filter input").val(h.data("forward"));this.$(".reverse-unpaired-filter input").val(h.data("reverse"));this._hideChooseFilters();this.trigger("filter-change")},_hideChooseFilters:function(){this.$(".choose-filters-link").popover("hide");this.$(".popover").css("display","none")},_clearFilters:function(h){this.$(".forward-unpaired-filter input").val("");this.$(".reverse-unpaired-filter input").val("");this.trigger("filter-change")},_clickUnpairedDataset:function(h){h.stopPropagation();return this.toggleSelectUnpaired($(h.currentTarget))},toggleSelectUnpaired:function(j,i){i=i||{};var k=j.data("dataset"),h=i.force!==undefined?i.force:!j.hasClass("selected");if(!j.size()||k===undefined){return j}if(h){j.addClass("selected");if(!i.waitToPair){this.pairAllSelected()}}else{j.removeClass("selected")}return j},pairAllSelected:function(i){i=i||{};var j=this,k=[],h=[],l=[];j.$(".unpaired-columns .forward-column .dataset.selected").each(function(){k.push($(this).data("dataset"))});j.$(".unpaired-columns .reverse-column .dataset.selected").each(function(){h.push($(this).data("dataset"))});k.length=h.length=Math.min(k.length,h.length);k.forEach(function(n,m){try{l.push(j._pair(n,h[m],{silent:true}))}catch(o){j.error(o)}});if(l.length&&!i.silent){this.trigger("pair:new",l)}return l},clearSelectedUnpaired:function(){this.$(".unpaired-columns .dataset.selected").removeClass("selected")},_mousedownUnpaired:function(j){if(j.shiftKey){var i=this,h=$(j.target).addClass("selected"),k=function(l){i.$(l.target).filter(".dataset").addClass("selected")};h.parent().on("mousemove",k);$(document).one("mouseup",function(l){h.parent().off("mousemove",k);i.pairAllSelected()})}},_clickPairRow:function(j){var k=$(j.currentTarget).index(),i=$(".unpaired-columns .forward-column .dataset").eq(k).data("dataset"),h=$(".unpaired-columns .reverse-column .dataset").eq(k).data("dataset");this._pair(i,h)},_startPartitionDrag:function(i){var h=this,l=i.pageY;$("body").css("cursor","ns-resize");h.$(".flexible-partition-drag").css("color","black");function k(m){h.$(".flexible-partition-drag").css("color","");$("body").css("cursor","").unbind("mousemove",j)}function j(m){var n=m.pageY-l;if(!h.adjPartition(n)){$("body").trigger("mouseup")}h._adjUnpairedOnScrollbar();l+=n}$("body").mousemove(j);$("body").one("mouseup",k)},adjPartition:function(i){var h=this.$(".unpaired-columns"),j=this.$(".paired-columns"),k=parseInt(h.css("height"),10),l=parseInt(j.css("height"),10);k=Math.max(10,k+i);l=l-i;var m=i<0;if(m){if(this.unpairedPanelHidden){return false}else{if(k<=10){this.hideUnpaired();return false}}}else{if(this.unpairedPanelHidden){h.show();this.unpairedPanelHidden=false}}if(!m){if(this.pairedPanelHidden){return false}else{if(l<=15){this.hidePaired();return false}}}else{if(this.pairedPanelHidden){j.show();this.pairedPanelHidden=false}}h.css({height:k+"px",flex:"0 0 auto"});return true},selectPair:function(h){h.stopPropagation();$(h.currentTarget).toggleClass("selected")},clearSelectedPaired:function(h){this.$(".paired-columns .dataset.selected").removeClass("selected")},_clickPairName:function(j){j.stopPropagation();var i=$(j.currentTarget),k=this.paired[i.parent().parent().index()/2],h=prompt("Enter a new name for the pair:",k.name);if(h){k.name=h;k.customizedName=true;i.text(k.name)}},_clickUnpair:function(i){var h=Math.floor($(i.currentTarget).index()/2);this._unpair(this.paired[h])},_dragoverPairedColumns:function(k){k.preventDefault();var i=this.$(".paired-columns .column-datasets");this._checkForAutoscroll(i,k.originalEvent.clientY);var j=this._getNearestPairedDatasetLi(k.originalEvent.clientY);$(".paired-drop-placeholder").remove();var h=$('<div class="paired-drop-placeholder"></div>');if(!j.size()){i.append(h)}else{j.before(h)}},_checkForAutoscroll:function(h,n){var l=2;var m=h.offset(),k=h.scrollTop(),i=n-m.top,j=(m.top+h.outerHeight())-n;if(i>=0&&i<this.autoscrollDist){h.scrollTop(k-l)}else{if(j>=0&&j<this.autoscrollDist){h.scrollTop(k+l)}}},_getNearestPairedDatasetLi:function(o){var l=4,j=this.$(".paired-columns .column-datasets li").toArray();for(var k=0;k<j.length;k++){var n=$(j[k]),m=n.offset().top,h=Math.floor(n.outerHeight()/2)+l;if(m+h>o&&m-h<o){return n}}return $()},_dropPairedColumns:function(i){i.preventDefault();i.dataTransfer.dropEffect="move";var h=this._getNearestPairedDatasetLi(i.originalEvent.clientY);if(h.size()){this.$dragging.insertBefore(h)}else{this.$dragging.insertAfter(this.$(".paired-columns .unpair-btn").last())}this._syncPairsToDom();return false},_syncPairsToDom:function(){var h=[];this.$(".paired-columns .dataset.paired").each(function(){h.push($(this).data("pair"))});this.paired=h;this._renderPaired()},_pairDragstart:function(i,j){j.$el.addClass("selected");var h=this.$(".paired-columns .dataset.selected");this.$dragging=h},_pairDragend:function(h,i){$(".paired-drop-placeholder").remove();this.$dragging=null},toggleExtensions:function(i){var h=this;h.removeExtensions=(i!==undefined)?(i):(!h.removeExtensions);_.each(h.paired,function(j){if(j.customizedName){return}j.name=h._guessNameForPair(j.forward,j.reverse)});h._renderPaired();h._renderFooter()},_changeName:function(h){this._validationWarning("name",!!this._getName())},_nameCheckForEnter:function(h){if(h.keyCode===13){this._clickCreate()}},_getName:function(){return _.escape(this.$(".collection-name").val())},_clickCreate:function(i){var h=this._getName();if(!h){this._validationWarning("name")}else{this.createList()}},_printList:function(i){var h=this;_.each(i,function(j){if(i===h.paired){h._printPair(j)}else{}})},_printPair:function(h){this.debug(h.forward.name,h.reverse.name,": ->",h.name)},toString:function(){return"PairedCollectionCreator"}});e.templates=e.templates||{main:_.template(['<div class="header flex-row no-flex"></div>','<div class="middle flex-row flex-row-container"></div>','<div class="footer flex-row no-flex">'].join("")),header:_.template(['<div class="main-help well clear">','<a class="more-help" href="javascript:void(0);">',d("More help"),"</a>",'<div class="help-content">','<a class="less-help" href="javascript:void(0);">',d("Less"),"</a>","</div>","</div>",'<div class="alert alert-dismissable">','<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>','<span class="alert-message"></span>',"</div>",'<div class="column-headers vertically-spaced flex-column-container">','<div class="forward-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired forward"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter forward-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>",'<div class="paired-column flex-column no-flex column">','<div class="column-header">','<a class="choose-filters-link" href="javascript:void(0)">',d("Choose filters"),"</a>",'<a class="clear-filters-link" href="javascript:void(0);">',d("Clear filters"),"</a><br />",'<a class="autopair-link" href="javascript:void(0);">',d("Auto-pair"),"</a>","</div>","</div>",'<div class="reverse-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired reverse"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter reverse-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>","</div>"].join("")),middle:_.template(['<div class="unpaired-columns flex-column-container scroll-container flex-row">','<div class="forward-column flex-column column">','<ol class="column-datasets"></ol>',"</div>",'<div class="paired-column flex-column no-flex column">','<ol class="column-datasets"></ol>',"</div>",'<div class="reverse-column flex-column column">','<ol class="column-datasets"></ol>',"</div>","</div>",'<div class="flexible-partition">','<div class="flexible-partition-drag" title="',d("Drag to change"),'"></div>','<div class="column-header">','<div class="column-title paired-column-title">','<span class="title"></span>',"</div>",'<a class="unpair-all-link" href="javascript:void(0);">',d("Unpair all"),"</a>","</div>","</div>",'<div class="paired-columns flex-column-container scroll-container flex-row">','<ol class="column-datasets"></ol>',"</div>"].join("")),footer:_.template(['<div class="attributes clear">','<div class="clear">','<label class="remove-extensions-prompt pull-right">',d("Remove file extensions from pair names"),"?",'<input class="remove-extensions pull-right" type="checkbox" />',"</label>","</div>",'<div class="clear">','<input class="collection-name form-control pull-right" ','placeholder="',d("Enter a name for your new list"),'" />','<div class="collection-name-prompt pull-right">',d("Name"),":</div>","</div>","</div>",'<div class="actions clear vertically-spaced">','<div class="other-options pull-left">','<button class="cancel-create btn" tabindex="-1">',d("Cancel"),"</button>",'<div class="create-other btn-group dropup">','<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">',d("Create a different kind of collection"),' <span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">','<li><a href="#">',d("Create a <i>single</i> pair"),"</a></li>",'<li><a href="#">',d("Create a list of <i>unpaired</i> datasets"),"</a></li>","</ul>","</div>","</div>",'<div class="main-options pull-right">','<button class="create-collection btn btn-primary">',d("Create list"),"</button>","</div>","</div>"].join("")),helpContent:_.template(["<p>",d(["Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). ","These collections can be passed to tools and workflows in order to have analyses done on each member of ","the entire group. This interface allows you to create a collection, choose which datasets are paired, ","and re-order the final collection."].join("")),"</p>","<p>",d(['Unpaired datasets are shown in the <i data-target=".unpaired-columns">unpaired section</i> ',"(hover over the underlined words to highlight below). ",'Paired datasets are shown in the <i data-target=".paired-columns">paired section</i>.',"<ul>To pair datasets, you can:","<li>Click a dataset in the ",'<i data-target=".unpaired-columns .forward-column .column-datasets,','.unpaired-columns .forward-column">forward column</i> ',"to select it then click a dataset in the ",'<i data-target=".unpaired-columns .reverse-column .column-datasets,','.unpaired-columns .reverse-column">reverse column</i>.',"</li>",'<li>Click one of the "Pair these datasets" buttons in the ','<i data-target=".unpaired-columns .paired-column .column-datasets,','.unpaired-columns .paired-column">middle column</i> ',"to pair the datasets in a particular row.","</li>",'<li>Click <i data-target=".autopair-link">"Auto-pair"</i> ',"to have your datasets automatically paired based on name.","</li>","</ul>"].join("")),"</p>","<p>",d(["<ul>You can filter what is shown in the unpaired sections by:","<li>Entering partial dataset names in either the ",'<i data-target=".forward-unpaired-filter input">forward filter</i> or ','<i data-target=".reverse-unpaired-filter input">reverse filter</i>.',"</li>","<li>Choosing from a list of preset filters by clicking the ",'<i data-target=".choose-filters-link">"Choose filters" link</i>.',"</li>","<li>Entering regular expressions to match dataset names. See: ",'<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expre…"',' target="_blank">MDN\'s JavaScript Regular Expression Tutorial</a>. ',"Note: forward slashes (\\) are not needed.","</li>","<li>Clearing the filters by clicking the ",'<i data-target=".clear-filters-link">"Clear filters" link</i>.',"</li>","</ul>"].join("")),"</p>","<p>",d(["To unpair individual dataset pairs, click the ",'<i data-target=".unpair-btn">unpair buttons ( <span class="fa fa-unlink"></span> )</i>. ','Click the <i data-target=".unpair-all-link">"Unpair all" link</i> to unpair all pairs.'].join("")),"</p>","<p>",d(['You can include or remove the file extensions (e.g. ".fastq") from your pair names by toggling the ','<i data-target=".remove-extensions-prompt">"Remove file extensions from pair names?"</i> control.'].join("")),"</p>","<p>",d(['Once your collection is complete, enter a <i data-target=".collection-name">name</i> and ','click <i data-target=".create-collection">"Create list"</i>. ',"(Note: you do not have to pair all unpaired datasets to finish.)"].join("")),"</p>"].join(""))};(function(){jQuery.fn.extend({hoverhighlight:function h(j,i){j=j||"body";if(!this.size()){return this}$(this).each(function(){var l=$(this),k=l.data("target");if(k){l.mouseover(function(m){$(k,j).css({background:i})}).mouseout(function(m){$(k).css({background:""})})}});return this}})}());var b=function c(j,h){h=_.defaults(h||{},{datasets:j,oncancel:function(){Galaxy.modal.hide()},oncreate:function(){Galaxy.modal.hide();Galaxy.currHistoryPanel.refreshContents()}});if(!window.Galaxy||!Galaxy.modal){throw new Error("Galaxy or Galaxy.modal not found")}var i=new e(h).render();Galaxy.modal.show({title:"Create a collection of paired datasets",body:i.$el,width:"80%",height:"800px",closing_events:true});window.PCC=i;return i};return{PairedCollectionCreator:e,pairedCollectionCreatorModal:b}});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: UI: remove unused LazyDataLoader module
by commits-noreply@bitbucket.org 09 Feb '15
by commits-noreply@bitbucket.org 09 Feb '15
09 Feb '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/27bc860232d7/
Changeset: 27bc860232d7
User: carlfeberhard
Date: 2015-02-09 22:47:30+00:00
Summary: UI: remove unused LazyDataLoader module
Affected #: 3 files
diff -r e3179a43319070d78d02a55e394fa765a3549a84 -r 27bc860232d7e531133f0413d6200fe5c171695d client/galaxy/scripts/utils/LazyDataLoader.js
--- a/client/galaxy/scripts/utils/LazyDataLoader.js
+++ /dev/null
@@ -1,228 +0,0 @@
-//==============================================================================
-/*
-TODO:
- ?? superclass dataloader, subclass lazydataloader??
-
-*/
-//==============================================================================
-/**
- * Object to progressively load JSON data from a REST url, delaying some time between loading chunks
- *
- * Will load size amount of data every delay ms, starting at start and ending at total.
- *
- * NOTE: Data from ajax loading is aggregated in a list, with one element for each ajax response.
- * It's up to the calling code to combine the results in a meaningful, correct way.
- *
- * example:
- * var loader = new scatterplot.LazyDataLoader({
- * //logger : console,
- * url : ( apiDatasetsURL + '/' + hda.id + '?data_type=raw_data'
- * + '&columns=[10,14]' ),
- * total : hda.metadata_data_lines,
- * size : 500,
- *
- * initialize : function( config ){
- * // ... do some stuff
- * },
- *
- * buildUrl : function( start, size ){
- * // change the formation of start, size in query string
- * return loader.url + '&' + jQuery.param({
- * start_val: start,
- * max_vals: size
- * });
- * },
- * });
- *
- * // you can use events
- * $( loader ).bind( 'error', function( event, xhr, status, error ){
- * alert( loader + ' ERROR:' + status + '\n' + error );
- * // bail out...
- * });
- * $( loader ).bind( 'loaded.new', function( event, response ){
- * console.info( 'new data available:', event, response );
- * // ... do stuff with new data
- * });
- * $( loader ).bind( 'complete', function( event, allDataArray, total ){
- * console.info( 'final load complete:', event, allDataArray, total );
- * // ... do stuff with all data
- * });
- *
- * // ...or use a callback called when all data is loaded
- * loader.load( function( dataArray ){ console.debug( 'FINISHED!', x, y, z ); } );
- */
-function LazyDataLoader( config ){
- // for now assume:
- // get, async, and params sent via url query string
- // we want json
- // we know the size of the data on the server beforehand
- var loader = this,
- // events to trigger when new or all data has been loaded
- // new batches of data (including last). Will be sent: the ajax response data, start value, and size
- LOADED_NEW_EVENT = 'loaded.new',
- // all data has been loaded: the final loader's data array and the total
- LOADED_ALL_EVENT = 'complete';
- // error from ajax
- ERROR_EVENT = 'error';
-
- jQuery.extend( loader, LoggableMixin );
- jQuery.extend( loader, {
-
- //NOTE: the next two need to be sent in config (required)
- // total size of data on server
- total : undefined,
- // url of service to get the data
- url : undefined,
-
- // holds the interval id for the current load delay
- currentIntervalId : undefined,
-
- // each load call will add an element to this array
- // it's the responsibility of the code using this to combine them properly
- data : [],
- // ms btwn recursive loads
- delay : 4000,
- // starting line, element, whatever
- start : 0,
- // size to fetch per load
- size : 4000,
-
- // loader init func: extends loader with config and calls config.init if there
- //@param {object} config : object containing variables to override (or additional)
- initialize : function( config ){
- jQuery.extend( loader, config );
-
- // call the custom initialize function if any
- // only dangerous if the user tries LazyDataLoader.prototype.init
- if( config.hasOwnProperty( 'initialize' ) ){
- config.initialize.call( loader, config );
- }
- this.log( this + ' initialized:', loader );
- },
-
- // returns query string formatted start and size (for the next fetch) appended to the loader.url
- //OVERRIDE: to change how params are passed, param names, etc.
- //@param {int} start : the line/row/datum indicating where in the dataset the next load begins
- //@param {int} size : the number of lines/rows/data to get on the next load
- buildUrl : function( start, size ){
- // currently VERY SPECIFIC to using data_providers.py start_val, max_vals params
- return this.url + '&' + jQuery.param({
- start_val: start,
- max_vals: size
- });
- },
-
- //OVERRIDE: to handle ajax errors differently
- ajaxErrorFn : function( xhr, status, error ){
- console.error( 'ERROR fetching data:', error );
- },
-
- // converters passed to the jQuery ajax call for data type parsing
- //OVERRIDE: to provide custom parsing
- converters : {
- '* text' : window.String,
- 'text html' : true,
- 'text xml' : jQuery.parseXML,
- 'text json' : jQuery.parseJSON
- },
-
- // interface to begin load (and first recursive call)
- //@param {Function} callback : function to execute when all data is loaded. callback is passed loader.data
- load : function( callback ){
- this.log( this + '.load' );
-
- // ensure necessary stuff
- if( !loader.url ){ throw( loader + ' requires a url' ); }
-
- if( this.total === null ){
- this.log( '\t total is null (will load all)' );
- } else {
- this.log( '\t total:', this.total );
- }
- //if( !loader.total ){ throw( loader + ' requires a total (total size of the data)' ); }
-
- //FIRST RECURSION: start
- var startingSize = loader.size;
- if( ( loader.total !== null ) && ( loader.total < loader.size ) ){
- startingSize = loader.total;
- }
- loader.log( loader + '\t beginning recursion' );
- loadHelper( loader.start, startingSize );
-
- //FIRST, SUBSEQUENT RECURSION function
- function loadHelper( start, size ){
- loader.log( loader + '.loadHelper, start:', start, 'size:', size );
- var url = loader.buildUrl( start, size );
- loader.log( '\t url:', url );
-
- jQuery.ajax({
- url : loader.buildUrl( start, size ),
- converters : loader.converters,
- dataType : 'json',
-
- error : function( xhr, status, error ){
- loader.log( '\t ajax error, status:', status, 'error:', error );
- if( loader.currentIntervalId ){
- clearInterval( loader.currentIntervalId );
- }
- $( loader ).trigger( ERROR_EVENT, [ status, error ] );
- loader.ajaxErrorFn( xhr, status, error );
- },
-
- success : function( response ){
- loader.log( '\t ajax success, response:', response, 'next:', next, 'remainder:', remainder );
-
- if( response !== null ){
- // store the response as is in a new element
- //TODO:?? store start, size as well?
- loader.data.push( response );
-
- //TODO: these might not be the best way to split this up
- // fire the first load event (if this is the first batch) AND partial
- $( loader ).trigger( LOADED_NEW_EVENT, [ response, start, size ] );
-
- //RECURSION:
- var next = start + size,
- remainder = loader.size;
-
- if( loader.total !== null ){
- remainder = Math.min( loader.total - next, loader.size );
- }
- loader.log( '\t next recursion, start:', next, 'size:', remainder );
-
- // if we haven't gotten everything yet, so set up for next recursive call and set the timer
- if( loader.total === null || remainder > 0 ){
- loader.currentIntervalId = setTimeout(
- function(){ loadHelper( next, remainder ); },
- loader.delay
- );
- loader.log( '\t currentIntervalId:', loader.currentIntervalId );
-
- // otherwise (base-case), don't do anything
- } else {
- loadFinished();
- }
-
- } else { //response === null --> base-case, server sez nuthin left
- loadFinished();
- }
- }
- });
- }
-
- //HANDLE BASE-CASE, LAST RECURSION
- function loadFinished(){
- loader.log( loader + '.loadHelper, has finished:', loader.data );
- $( loader ).trigger( LOADED_ALL_EVENT, [ loader.data, loader.total ] );
- if( callback ){ callback( loader.data ); }
- }
- },
-
- toString : function(){ return 'LazyDataLoader'; }
- });
-
- loader.initialize( config );
- return loader;
-}
-
-//==============================================================================
diff -r e3179a43319070d78d02a55e394fa765a3549a84 -r 27bc860232d7e531133f0413d6200fe5c171695d static/scripts/packed/utils/LazyDataLoader.js
--- a/static/scripts/packed/utils/LazyDataLoader.js
+++ /dev/null
@@ -1,1 +0,0 @@
-function LazyDataLoader(c){var a=this,d="loaded.new",b="complete";ERROR_EVENT="error";jQuery.extend(a,LoggableMixin);jQuery.extend(a,{total:undefined,url:undefined,currentIntervalId:undefined,data:[],delay:4000,start:0,size:4000,initialize:function(e){jQuery.extend(a,e);if(e.hasOwnProperty("initialize")){e.initialize.call(a,e)}this.log(this+" initialized:",a)},buildUrl:function(f,e){return this.url+"&"+jQuery.param({start_val:f,max_vals:e})},ajaxErrorFn:function(g,e,f){console.error("ERROR fetching data:",f)},converters:{"* text":window.String,"text html":true,"text xml":jQuery.parseXML,"text json":jQuery.parseJSON},load:function(h){this.log(this+".load");if(!a.url){throw (a+" requires a url")}if(this.total===null){this.log("\t total is null (will load all)")}else{this.log("\t total:",this.total)}var g=a.size;if((a.total!==null)&&(a.total<a.size)){g=a.total}a.log(a+"\t beginning recursion");f(a.start,g);function f(k,j){a.log(a+".loadHelper, start:",k,"size:",j);var i=a.buildUrl(k,j);a.log("\t url:",i);jQuery.ajax({url:a.buildUrl(k,j),converters:a.converters,dataType:"json",error:function(n,l,m){a.log("\t ajax error, status:",l,"error:",m);if(a.currentIntervalId){clearInterval(a.currentIntervalId)}$(a).trigger(ERROR_EVENT,[l,m]);a.ajaxErrorFn(n,l,m)},success:function(l){a.log("\t ajax success, response:",l,"next:",m,"remainder:",n);if(l!==null){a.data.push(l);$(a).trigger(d,[l,k,j]);var m=k+j,n=a.size;if(a.total!==null){n=Math.min(a.total-m,a.size)}a.log("\t next recursion, start:",m,"size:",n);if(a.total===null||n>0){a.currentIntervalId=setTimeout(function(){f(m,n)},a.delay);a.log("\t currentIntervalId:",a.currentIntervalId)}else{e()}}else{e()}}})}function e(){a.log(a+".loadHelper, has finished:",a.data);$(a).trigger(b,[a.data,a.total]);if(h){h(a.data)}}},toString:function(){return"LazyDataLoader"}});a.initialize(c);return a};
\ No newline at end of file
diff -r e3179a43319070d78d02a55e394fa765a3549a84 -r 27bc860232d7e531133f0413d6200fe5c171695d static/scripts/utils/LazyDataLoader.js
--- a/static/scripts/utils/LazyDataLoader.js
+++ /dev/null
@@ -1,228 +0,0 @@
-//==============================================================================
-/*
-TODO:
- ?? superclass dataloader, subclass lazydataloader??
-
-*/
-//==============================================================================
-/**
- * Object to progressively load JSON data from a REST url, delaying some time between loading chunks
- *
- * Will load size amount of data every delay ms, starting at start and ending at total.
- *
- * NOTE: Data from ajax loading is aggregated in a list, with one element for each ajax response.
- * It's up to the calling code to combine the results in a meaningful, correct way.
- *
- * example:
- * var loader = new scatterplot.LazyDataLoader({
- * //logger : console,
- * url : ( apiDatasetsURL + '/' + hda.id + '?data_type=raw_data'
- * + '&columns=[10,14]' ),
- * total : hda.metadata_data_lines,
- * size : 500,
- *
- * initialize : function( config ){
- * // ... do some stuff
- * },
- *
- * buildUrl : function( start, size ){
- * // change the formation of start, size in query string
- * return loader.url + '&' + jQuery.param({
- * start_val: start,
- * max_vals: size
- * });
- * },
- * });
- *
- * // you can use events
- * $( loader ).bind( 'error', function( event, xhr, status, error ){
- * alert( loader + ' ERROR:' + status + '\n' + error );
- * // bail out...
- * });
- * $( loader ).bind( 'loaded.new', function( event, response ){
- * console.info( 'new data available:', event, response );
- * // ... do stuff with new data
- * });
- * $( loader ).bind( 'complete', function( event, allDataArray, total ){
- * console.info( 'final load complete:', event, allDataArray, total );
- * // ... do stuff with all data
- * });
- *
- * // ...or use a callback called when all data is loaded
- * loader.load( function( dataArray ){ console.debug( 'FINISHED!', x, y, z ); } );
- */
-function LazyDataLoader( config ){
- // for now assume:
- // get, async, and params sent via url query string
- // we want json
- // we know the size of the data on the server beforehand
- var loader = this,
- // events to trigger when new or all data has been loaded
- // new batches of data (including last). Will be sent: the ajax response data, start value, and size
- LOADED_NEW_EVENT = 'loaded.new',
- // all data has been loaded: the final loader's data array and the total
- LOADED_ALL_EVENT = 'complete';
- // error from ajax
- ERROR_EVENT = 'error';
-
- jQuery.extend( loader, LoggableMixin );
- jQuery.extend( loader, {
-
- //NOTE: the next two need to be sent in config (required)
- // total size of data on server
- total : undefined,
- // url of service to get the data
- url : undefined,
-
- // holds the interval id for the current load delay
- currentIntervalId : undefined,
-
- // each load call will add an element to this array
- // it's the responsibility of the code using this to combine them properly
- data : [],
- // ms btwn recursive loads
- delay : 4000,
- // starting line, element, whatever
- start : 0,
- // size to fetch per load
- size : 4000,
-
- // loader init func: extends loader with config and calls config.init if there
- //@param {object} config : object containing variables to override (or additional)
- initialize : function( config ){
- jQuery.extend( loader, config );
-
- // call the custom initialize function if any
- // only dangerous if the user tries LazyDataLoader.prototype.init
- if( config.hasOwnProperty( 'initialize' ) ){
- config.initialize.call( loader, config );
- }
- this.log( this + ' initialized:', loader );
- },
-
- // returns query string formatted start and size (for the next fetch) appended to the loader.url
- //OVERRIDE: to change how params are passed, param names, etc.
- //@param {int} start : the line/row/datum indicating where in the dataset the next load begins
- //@param {int} size : the number of lines/rows/data to get on the next load
- buildUrl : function( start, size ){
- // currently VERY SPECIFIC to using data_providers.py start_val, max_vals params
- return this.url + '&' + jQuery.param({
- start_val: start,
- max_vals: size
- });
- },
-
- //OVERRIDE: to handle ajax errors differently
- ajaxErrorFn : function( xhr, status, error ){
- console.error( 'ERROR fetching data:', error );
- },
-
- // converters passed to the jQuery ajax call for data type parsing
- //OVERRIDE: to provide custom parsing
- converters : {
- '* text' : window.String,
- 'text html' : true,
- 'text xml' : jQuery.parseXML,
- 'text json' : jQuery.parseJSON
- },
-
- // interface to begin load (and first recursive call)
- //@param {Function} callback : function to execute when all data is loaded. callback is passed loader.data
- load : function( callback ){
- this.log( this + '.load' );
-
- // ensure necessary stuff
- if( !loader.url ){ throw( loader + ' requires a url' ); }
-
- if( this.total === null ){
- this.log( '\t total is null (will load all)' );
- } else {
- this.log( '\t total:', this.total );
- }
- //if( !loader.total ){ throw( loader + ' requires a total (total size of the data)' ); }
-
- //FIRST RECURSION: start
- var startingSize = loader.size;
- if( ( loader.total !== null ) && ( loader.total < loader.size ) ){
- startingSize = loader.total;
- }
- loader.log( loader + '\t beginning recursion' );
- loadHelper( loader.start, startingSize );
-
- //FIRST, SUBSEQUENT RECURSION function
- function loadHelper( start, size ){
- loader.log( loader + '.loadHelper, start:', start, 'size:', size );
- var url = loader.buildUrl( start, size );
- loader.log( '\t url:', url );
-
- jQuery.ajax({
- url : loader.buildUrl( start, size ),
- converters : loader.converters,
- dataType : 'json',
-
- error : function( xhr, status, error ){
- loader.log( '\t ajax error, status:', status, 'error:', error );
- if( loader.currentIntervalId ){
- clearInterval( loader.currentIntervalId );
- }
- $( loader ).trigger( ERROR_EVENT, [ status, error ] );
- loader.ajaxErrorFn( xhr, status, error );
- },
-
- success : function( response ){
- loader.log( '\t ajax success, response:', response, 'next:', next, 'remainder:', remainder );
-
- if( response !== null ){
- // store the response as is in a new element
- //TODO:?? store start, size as well?
- loader.data.push( response );
-
- //TODO: these might not be the best way to split this up
- // fire the first load event (if this is the first batch) AND partial
- $( loader ).trigger( LOADED_NEW_EVENT, [ response, start, size ] );
-
- //RECURSION:
- var next = start + size,
- remainder = loader.size;
-
- if( loader.total !== null ){
- remainder = Math.min( loader.total - next, loader.size );
- }
- loader.log( '\t next recursion, start:', next, 'size:', remainder );
-
- // if we haven't gotten everything yet, so set up for next recursive call and set the timer
- if( loader.total === null || remainder > 0 ){
- loader.currentIntervalId = setTimeout(
- function(){ loadHelper( next, remainder ); },
- loader.delay
- );
- loader.log( '\t currentIntervalId:', loader.currentIntervalId );
-
- // otherwise (base-case), don't do anything
- } else {
- loadFinished();
- }
-
- } else { //response === null --> base-case, server sez nuthin left
- loadFinished();
- }
- }
- });
- }
-
- //HANDLE BASE-CASE, LAST RECURSION
- function loadFinished(){
- loader.log( loader + '.loadHelper, has finished:', loader.data );
- $( loader ).trigger( LOADED_ALL_EVENT, [ loader.data, loader.total ] );
- if( callback ){ callback( loader.data ); }
- }
- },
-
- toString : function(){ return 'LazyDataLoader'; }
- });
-
- loader.initialize( config );
- return loader;
-}
-
-//==============================================================================
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0