galaxy-dev
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
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
August 2009
- 12 participants
- 156 discussions
details: http://www.bx.psu.edu/hg/galaxy/rev/e9d70dca2ff5
changeset: 2578:e9d70dca2ff5
user: Kanwei Li <kanwei(a)gmail.com>
date: Wed Aug 19 11:33:48 2009 -0400
description:
Fix workflow layout
1 file(s) affected in this change:
static/scripts/galaxy.workflow_editor.canvas.js
diffs (12 lines):
diff -r 5b6146705e80 -r e9d70dca2ff5 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js Thu Aug 13 13:44:04 2009 -0400
+++ b/static/scripts/galaxy.workflow_editor.canvas.js Wed Aug 19 11:33:48 2009 -0400
@@ -502,7 +502,7 @@
var v = level_parents[k];
delete n_pred[v];
for ( var sk in successors[v] ) {
- n_pred[ sucessors[v][sk] ] -= 1;
+ n_pred[ successors[v][sk] ] -= 1;
}
}
}
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/ea6708c96cd1
changeset: 2580:ea6708c96cd1
user: Kanwei Li <kanwei(a)gmail.com>
date: Wed Aug 19 17:27:00 2009 -0400
description:
Auto-save for workflow forms
5 file(s) affected in this change:
static/scripts/galaxy.workflow_editor.canvas.js
static/scripts/packed/galaxy.workflow_editor.canvas.js
templates/workflow/editor.mako
templates/workflow/editor_generic_form.mako
templates/workflow/editor_tool_form.mako
diffs (215 lines):
diff -r c5968ee9399b -r ea6708c96cd1 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js Wed Aug 19 11:33:58 2009 -0400
+++ b/static/scripts/galaxy.workflow_editor.canvas.js Wed Aug 19 17:27:00 2009 -0400
@@ -359,6 +359,7 @@
this.nodes = {};
this.name = null;
this.has_changes = false;
+ this.active_form_has_changes = false;
}
$.extend( Workflow.prototype, {
add_node : function( node ) {
@@ -438,6 +439,28 @@
});
});
},
+ enable_auto_save : function() {
+ // Implements auto-saving based on whether the inputs change. We consider
+ // "changed" to be when a field is accessed and not necessarily modified
+ // because of an issue where "onchange" is not triggered when activating
+ // another node, or saving the workflow.
+ outer_this = this;
+ $(".toolFormBody").find("input,textarea,select").each( function() {
+ $(this).focus( function() {
+ outer_this.active_form_has_changes = true;
+ });
+ });
+ },
+ check_changes_in_active_form : function() {
+ // If active form has changed, save it
+ if (this.active_form_has_changes) {
+ this.has_changes = true;
+ $(".toolFormBody").find("form").each( function() {
+ $(this).submit();
+ });
+ this.active_form_has_changes = false;
+ }
+ },
clear_active_node : function() {
if ( this.active_node ) {
this.active_node.make_inactive();
@@ -447,6 +470,7 @@
},
activate_node : function( node ) {
if ( this.active_node != node ) {
+ this.check_changes_in_active_form();
this.clear_active_node();
parent.show_form_for_tool( node.form_html, node );
node.make_active();
@@ -461,6 +485,7 @@
}
},
layout : function () {
+ this.check_changes_in_active_form();
// Prepare predecessor / successor tracking
var n_pred = {};
var successors = {};
diff -r c5968ee9399b -r ea6708c96cd1 static/scripts/packed/galaxy.workflow_editor.canvas.js
--- a/static/scripts/packed/galaxy.workflow_editor.canvas.js Wed Aug 19 11:33:58 2009 -0400
+++ b/static/scripts/packed/galaxy.workflow_editor.canvas.js Wed Aug 19 17:27:00 2009 -0400
@@ -1,1 +1,1 @@
-function Terminal(a){this.element=a;this.connectors=[]}$.extend(Terminal.prototype,{connect:function(a){this.connectors.push(a);if(this.node){this.node.changed()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.changed()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}});function OutputTerminal(a,b){Terminal.call(this,a);this.datatype=b}OutputTerminal.prototype=new Terminal();function InputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}InputTerminal.prototype=new Terminal();$.extend(InputTerminal.prototype,{can_accept:function(a){if(this.connectors.length<1){for(var b in this.datatypes){if(a.datatype=="input"){return true}if(issubtype(a.datatype,this.datatypes[b])){return true}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a)
{this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;this.handle1.connect(this);this.handle2=a;this.handle2.connect(this)},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var n=function(c){return $(c).offset().left-d.offset().left};var i=function(c){return $(c).offset().top-d.offset().top};var h=n(this.handle1.element)+5;var g=i(this.handle1.element)+5;var p=n(this.handle2.element)+5;var m=i(this.handle2.element)+5;var f=100;var k=Math.min(h,p);var a=Math.max(h,p);var j=Math.min(g,m);var t=Math.max(g,m);var b=Math.min(Math.max(Math.abs(t-j)/2,100),300);var o=k-f;var s=j-f;var q=a-k+2*f;var l=t-j+2*f;
this.canvas.style.left=o+"px";this.canvas.style.top=s+"px";this.canvas.setAttribute("width",q);this.canvas.setAttribute("height",l);h-=o;g-=s;p-=o;m-=s;var r=this.canvas.getContext("2d");r.lineCap="round";r.strokeStyle=this.outer_color;r.lineWidth=7;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke();r.strokeStyle=this.inner_color;r.lineWidth=5;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke()}});function Node(a){this.element=a;this.input_terminals={};this.output_terminals={};this.tool_errors={}}$.extend(Node.prototype,{enable_input_terminal:function(d,a,b){var c=this;$(d).each(function(){var f=this.terminal=new InputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dropstart",function(g){g.dragProxy.terminal.connectors[0].inner_color="#BBFFBB"}).bind("dropend",function(g){g.dragProxy.terminal.connectors[0].inner_color="#FFFFFF"}).bind("drop",function(g){(new Connector(g.dragTarget.terminal,g.dropTarget.terminal)).redraw()}).bind("hov
er",function(){if(f.connectors.length>0){var g=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='buttons'></div>").append($("<img src='../images/delete_icon.png' />").click(function(){$.each(f.connectors,function(i,h){h.destroy()});g.remove()}))).bind("mouseleave",function(){$(this).remove()});g.css({top:$(this).offset().top-2,left:$(this).offset().left-g.width(),"padding-right":$(this).width()}).show()}});c.input_terminals[a]=f})},enable_output_terminal:function(d,a,b){var c=this;$(d).each(function(){var g=this;var f=this.terminal=new OutputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dragstart",function(j){var i=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);i.terminal=new OutputTerminal(i);var k=new Connector();k.dragging=true;k.connect(this.terminal,i.terminal);$.dropManage({filter:function(h){return this.terminal.can_accept(f)}}).addClass("input-terminal-active");ret
urn i}).bind("drag",function(i){var h=function(){var k=$(i.dragProxy).offsetParent().offset(),j=i.offsetX-k.left,l=i.offsetY-k.top;$(i.dragProxy).css({left:j,top:l});i.dragProxy.terminal.redraw();canvas_manager.update_viewport_overlay()};h();$("#canvas-container").get(0).scroll_panel.test(i,h)}).bind("dragend",function(h){h.dragProxy.terminal.connectors[0].destroy();$(h.dragProxy).remove();$.dropManage().removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()});c.output_terminals[a]=f})},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b
.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(g){var d=this.element;if(g.type){this.type=g.type}this.name=g.name;this.form_html=g.form_html;this.tool_state=g.tool_state;this.tool_errors=g.tool_errors;if(this.tool_errors){d.addClass("tool-node-error")}else{d.removeClass("tool-node-error")}var c=this;var a=d.find(".toolFormBody");a.find("div").remove();var h=$("<div class='inputs'></div>").appendTo(a);$.each(g.data_inputs,function(j,b){var f=$("<div class='terminal input-terminal'></div>");c.enable_input_terminal(f,b.name,b.extensions);h.append($("<div class='form-row dataRow input-data-row' name='"+b.name+"'>"+b.label+"</div>").prepend(f))});if((g.data_inputs.length>0)&&(g.data_outputs.length>0)){a.append($("<div class='rule'></div>"))}$.each(g.data_outputs,function(k,b){var j=$("<div class='terminal output-terminal'></div>");c.enable_output_terminal(j,b.name,b.extension);var f=b.name;if(b.extension!="input"){f=f+" ("+b.extensio
n+")"}a.append($("<div class='form-row dataRow'>"+f+"</div>").append(j))});workflow.node_changed(this)},update_field_data:function(f){var c=$(this.element),d=this;this.tool_state=f.tool_state;this.form_html=f.form_html;this.tool_errors=f.tool_errors;if(this.tool_errors){c.addClass("tool-node-error")}else{c.removeClass("tool-node-error")}var g=c.find("div.inputs");var b=$("<div class='inputs'></div>");var a=g.find("div.input-data-row");$.each(f.data_inputs,function(k,h){var j=$("<div class='terminal input-terminal'></div>");d.enable_input_terminal(j,h.name,h.extensions);g.find("div[name="+h.name+"]").each(function(){$(this).find(".input-terminal").each(function(){var i=this.terminal.connectors[0];if(i){j[0].terminal.connectors[0]=i;i.handle2=j[0].terminal}});$(this).remove()});b.append($("<div class='form-row dataRow input-data-row' name='"+h.name+"'>"+h.label+"</div>").prepend(j))});g.replaceWith(b);g.find("div.input-data-row > .terminal").each(function(){this.terminal.destr
oy()});this.changed();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},changed:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},to_simple:function(){var a={};$.each(this.nodes,function(b,d){var f={};$.each(d.input_terminals,function(g,h){f[h.name]=null;$.each(h.connectors,function(j,k){f[h.name]={id:k.ha
ndle1.node.id,output_name:k.handle1.name}})});var c={id:d.id,type:d.type,tool_id:d.tool_id,tool_state:d.tool_state,tool_errors:d.tool_errors,input_connections:f,position:$(d.element).position()};a[d.id]=c});return{steps:a}},from_simple:function(a){wf=this;var b=0;wf.name=a.name;$.each(a.steps,function(f,d){var c=prebuild_node("tool",d.name,d.tool_id);c.init_field_data(d);if(d.position){c.element.css({top:d.position.top,left:d.position.left})}c.id=d.id;wf.nodes[c.id]=c;b=Math.max(b,parseInt(f))});wf.id_counter=b+1;$.each(a.steps,function(f,d){var c=wf.nodes[f];$.each(d.input_connections,function(h,g){if(g){var i=wf.nodes[g.id];var j=new Connector();j.connect(i.output_terminals[g.output_name],c.input_terminals[h]);j.redraw()}})})},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.clear_active_node();parent.show_
form_for_tool(a.form_html,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){parent.show_form_for_tool(a.form_html,a)}},layout:function(){var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[sucessors[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var
q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(
this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node(i);g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='../images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<img src='../images/delete_icon.png' />").click(function(b){g.destroy()}).hover(function(){$(this).attr("src","../images/delete_icon_dark.png")},function(){$(this).attr("src","../images/delete_icon.png")}));i.appendTo("#canvas-container");var
d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o){var f=$(this).offsetParent().offset(),b=o.offsetX-f.left,p=o.offsetY-f.top;$(this).css({left:b,top:p});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prot
otype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;
var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(g){var h=$(this).offset();var f=b.cc.position();c=f.top-h.top;d=f.left-h.left}).bind("drag",function(f){a(f.offsetX+d,f.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k){var j=b.cc.width(),g=b.cc.height(),f=b.oc.width(),h=b.oc.height(),i=$(this).offsetParent().offset(),m=k.offsetX-i.left,l=k.offsetY-i.top;a(-(m/f*j),-(l/h*g))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g){var i=$(this).offsetParent();var h=i.offset();var f=Math.max(i.width()-(g.offsetX-h.left),i.height()-(g.offsetY-h.top));$(this).css({wi
dth:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(f){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;$.each(workflow.nodes,function(t,q){var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;i.fillRe
ct(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
\ No newline at end of file
+function Terminal(a){this.element=a;this.connectors=[]}$.extend(Terminal.prototype,{connect:function(a){this.connectors.push(a);if(this.node){this.node.changed()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.changed()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}});function OutputTerminal(a,b){Terminal.call(this,a);this.datatype=b}OutputTerminal.prototype=new Terminal();function InputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}InputTerminal.prototype=new Terminal();$.extend(InputTerminal.prototype,{can_accept:function(a){if(this.connectors.length<1){for(var b in this.datatypes){if(a.datatype=="input"){return true}if(issubtype(a.datatype,this.datatypes[b])){return true}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a)
{this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;this.handle1.connect(this);this.handle2=a;this.handle2.connect(this)},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var n=function(c){return $(c).offset().left-d.offset().left};var i=function(c){return $(c).offset().top-d.offset().top};var h=n(this.handle1.element)+5;var g=i(this.handle1.element)+5;var p=n(this.handle2.element)+5;var m=i(this.handle2.element)+5;var f=100;var k=Math.min(h,p);var a=Math.max(h,p);var j=Math.min(g,m);var t=Math.max(g,m);var b=Math.min(Math.max(Math.abs(t-j)/2,100),300);var o=k-f;var s=j-f;var q=a-k+2*f;var l=t-j+2*f;
this.canvas.style.left=o+"px";this.canvas.style.top=s+"px";this.canvas.setAttribute("width",q);this.canvas.setAttribute("height",l);h-=o;g-=s;p-=o;m-=s;var r=this.canvas.getContext("2d");r.lineCap="round";r.strokeStyle=this.outer_color;r.lineWidth=7;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke();r.strokeStyle=this.inner_color;r.lineWidth=5;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke()}});function Node(a){this.element=a;this.input_terminals={};this.output_terminals={};this.tool_errors={}}$.extend(Node.prototype,{enable_input_terminal:function(d,a,b){var c=this;$(d).each(function(){var f=this.terminal=new InputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dropstart",function(g){g.dragProxy.terminal.connectors[0].inner_color="#BBFFBB"}).bind("dropend",function(g){g.dragProxy.terminal.connectors[0].inner_color="#FFFFFF"}).bind("drop",function(g){(new Connector(g.dragTarget.terminal,g.dropTarget.terminal)).redraw()}).bind("hov
er",function(){if(f.connectors.length>0){var g=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='buttons'></div>").append($("<img src='../images/delete_icon.png' />").click(function(){$.each(f.connectors,function(i,h){h.destroy()});g.remove()}))).bind("mouseleave",function(){$(this).remove()});g.css({top:$(this).offset().top-2,left:$(this).offset().left-g.width(),"padding-right":$(this).width()}).show()}});c.input_terminals[a]=f})},enable_output_terminal:function(d,a,b){var c=this;$(d).each(function(){var g=this;var f=this.terminal=new OutputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dragstart",function(j){var i=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);i.terminal=new OutputTerminal(i);var k=new Connector();k.dragging=true;k.connect(this.terminal,i.terminal);$.dropManage({filter:function(h){return this.terminal.can_accept(f)}}).addClass("input-terminal-active");ret
urn i}).bind("drag",function(i){var h=function(){var k=$(i.dragProxy).offsetParent().offset(),j=i.offsetX-k.left,l=i.offsetY-k.top;$(i.dragProxy).css({left:j,top:l});i.dragProxy.terminal.redraw();canvas_manager.update_viewport_overlay()};h();$("#canvas-container").get(0).scroll_panel.test(i,h)}).bind("dragend",function(h){h.dragProxy.terminal.connectors[0].destroy();$(h.dragProxy).remove();$.dropManage().removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()});c.output_terminals[a]=f})},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b
.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(g){var d=this.element;if(g.type){this.type=g.type}this.name=g.name;this.form_html=g.form_html;this.tool_state=g.tool_state;this.tool_errors=g.tool_errors;if(this.tool_errors){d.addClass("tool-node-error")}else{d.removeClass("tool-node-error")}var c=this;var a=d.find(".toolFormBody");a.find("div").remove();var h=$("<div class='inputs'></div>").appendTo(a);$.each(g.data_inputs,function(j,b){var f=$("<div class='terminal input-terminal'></div>");c.enable_input_terminal(f,b.name,b.extensions);h.append($("<div class='form-row dataRow input-data-row' name='"+b.name+"'>"+b.label+"</div>").prepend(f))});if((g.data_inputs.length>0)&&(g.data_outputs.length>0)){a.append($("<div class='rule'></div>"))}$.each(g.data_outputs,function(k,b){var j=$("<div class='terminal output-terminal'></div>");c.enable_output_terminal(j,b.name,b.extension);var f=b.name;if(b.extension!="input"){f=f+" ("+b.extensio
n+")"}a.append($("<div class='form-row dataRow'>"+f+"</div>").append(j))});workflow.node_changed(this)},update_field_data:function(f){var c=$(this.element),d=this;this.tool_state=f.tool_state;this.form_html=f.form_html;this.tool_errors=f.tool_errors;if(this.tool_errors){c.addClass("tool-node-error")}else{c.removeClass("tool-node-error")}var g=c.find("div.inputs");var b=$("<div class='inputs'></div>");var a=g.find("div.input-data-row");$.each(f.data_inputs,function(k,h){var j=$("<div class='terminal input-terminal'></div>");d.enable_input_terminal(j,h.name,h.extensions);g.find("div[name="+h.name+"]").each(function(){$(this).find(".input-terminal").each(function(){var i=this.terminal.connectors[0];if(i){j[0].terminal.connectors[0]=i;i.handle2=j[0].terminal}});$(this).remove()});b.append($("<div class='form-row dataRow input-data-row' name='"+h.name+"'>"+h.label+"</div>").prepend(j))});g.replaceWith(b);g.find("div.input-data-row > .terminal").each(function(){this.terminal.destr
oy()});this.changed();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},changed:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},to_simple:function(){var a={};$.each(this.nodes,function(b,d){var f={};$.each(d.input_terminals,function(g,h){f[h.name]=null;$.each(h.connecto
rs,function(j,k){f[h.name]={id:k.handle1.node.id,output_name:k.handle1.name}})});var c={id:d.id,type:d.type,tool_id:d.tool_id,tool_state:d.tool_state,tool_errors:d.tool_errors,input_connections:f,position:$(d.element).position()};a[d.id]=c});return{steps:a}},from_simple:function(a){wf=this;var b=0;wf.name=a.name;$.each(a.steps,function(f,d){var c=prebuild_node("tool",d.name,d.tool_id);c.init_field_data(d);if(d.position){c.element.css({top:d.position.top,left:d.position.left})}c.id=d.id;wf.nodes[c.id]=c;b=Math.max(b,parseInt(f))});wf.id_counter=b+1;$.each(a.steps,function(f,d){var c=wf.nodes[f];$.each(d.input_connections,function(h,g){if(g){var i=wf.nodes[g.id];var j=new Connector();j.connect(i.output_terminals[g.output_name],c.input_terminals[h]);j.redraw()}})})},enable_auto_save:function(){outer_this=this;$(".toolFormBody").find("input,textarea,select").each(function(){$(this).focus(function(){outer_this.active_form_has_changes=true})})},check_changes_in_active_form:functio
n(){if(this.active_form_has_changes){this.has_changes=true;$(".toolFormBody").find("form").each(function(){$(this).submit()});this.active_form_has_changes=false}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){parent.show_form_for_tool(a.form_html,a)}},layout:function(){this.check_changes_in_active_form();var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){l
evel_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this
.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node(i);g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></d
iv>");var h="<div><img height='16' align='middle' src='../images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<img src='../images/delete_icon.png' />").click(function(b){g.destroy()}).hover(function(){$(this).attr("src","../images/delete_icon_dark.png")},function(){$(this).attr("src","../images/delete_icon.png")}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o){var f=$(this).
offsetParent().offset(),b=o.offsetX-f.left,p=o.offsetY-f.top;$(this).css({left:b,top:p});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.c
ss("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(g){var h=$(this).offset();var f=b.cc.position();c=f.top-h.top;d=f.left-h.left}).bind("drag",function(f){a(f.offsetX+d,f.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_n
odes();b.draw_overview()});this.ov.bind("drag",function(k){var j=b.cc.width(),g=b.cc.height(),f=b.oc.width(),h=b.oc.height(),i=$(this).offsetParent().offset(),m=k.offsetX-i.left,l=k.offsetY-i.top;a(-(m/f*j),-(l/h*g))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g){var i=$(this).offsetParent();var h=i.offset();var f=Math.max(i.width()-(g.offsetX-h.left),i.height()-(g.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(f){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var
g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;$.each(workflow.nodes,function(t,q){var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
\ No newline at end of file
diff -r c5968ee9399b -r ea6708c96cd1 templates/workflow/editor.mako
--- a/templates/workflow/editor.mako Wed Aug 19 11:33:58 2009 -0400
+++ b/templates/workflow/editor.mako Wed Aug 19 17:27:00 2009 -0400
@@ -282,10 +282,6 @@
beforeSubmit: function( data ) {
data.push( { name: 'tool_state', value: node.tool_state } );
data.push( { name: '_', value: "true" } );
- $("#tool-form-save-button").each( function() {
- this.value = "Saving...";
- this.disabled = true;
- });
}
}).each( function() {
form = this;
@@ -312,6 +308,7 @@
var close_editor = function() {
<% next_url = h.url_for( controller='workflow', action='index' ) %>
+ workflow.check_changes_in_active_form();
if ( workflow && workflow.has_changes ) {
do_close = function() {
window.onbeforeunload = undefined;
@@ -334,39 +331,46 @@
var save_current_workflow = function ( success_callback ) {
show_modal( "Saving workflow", "progress" );
- $.ajax( {
- url: "${h.url_for( action='save_workflow' )}",
- type: "POST",
- data: {
- id: "${trans.security.encode_id( workflow_id )}",
- workflow_data: $.toJSON( workflow.to_simple() ),
- "_": "true"
- },
- dataType: 'json',
- success: function( data ) {
- var body = $("<div></div>").text( data.message );
- if ( data.errors ) {
- body.addClass( "warningmark" )
- var errlist = $( "<ul/>" );
- $.each( data.errors, function( i, v ) {
- $("<li></li>").text( v ).appendTo( errlist );
- });
- body.append( errlist );
- } else {
- body.addClass( "donemark" );
+ workflow.check_changes_in_active_form();
+ // We bind to ajaxStop because of auto-saving, since the form submission ajax
+ // call needs to be completed so that the new data is saved
+ $(document).bind('ajaxStop.save_workflow', function() {
+ $(document).unbind('ajaxStop.save_workflow');
+ $.ajax( {
+ url: "${h.url_for( action='save_workflow' )}",
+ type: "POST",
+ data: {
+ id: "${trans.security.encode_id( workflow_id )}",
+ workflow_data: function() { return $.toJSON( workflow.to_simple() ) },
+ "_": "true"
+ },
+ dataType: 'json',
+ success: function( data ) {
+ var body = $("<div></div>").text( data.message );
+ if ( data.errors ) {
+ body.addClass( "warningmark" )
+ var errlist = $( "<ul/>" );
+ $.each( data.errors, function( i, v ) {
+ $("<li></li>").text( v ).appendTo( errlist );
+ });
+ body.append( errlist );
+ } else {
+ body.addClass( "donemark" );
+ }
+ workflow.name = data.name;
+ workflow.has_changes = false;
+ workflow.stored = true;
+ if ( success_callback ) {
+ success_callback();
+ }
+ if ( data.errors ) {
+ show_modal( "Saving workflow", body, { "Ok" : hide_modal } );
+ } else {
+ hide_modal();
+ }
}
- workflow.name = data.name;
- workflow.has_changes = false;
- workflow.stored = true;
- if ( success_callback ) {
- success_callback();
- }
- if ( data.errors ) {
- show_modal( "Saving workflow", body, { "Ok" : hide_modal } );
- } else {
- hide_modal();
- }
- }
+ });
+ $(document).unbind('ajaxStop.save_workflow'); // IE7 needs it here
});
}
diff -r c5968ee9399b -r ea6708c96cd1 templates/workflow/editor_generic_form.mako
--- a/templates/workflow/editor_generic_form.mako Wed Aug 19 11:33:58 2009 -0400
+++ b/templates/workflow/editor_generic_form.mako Wed Aug 19 17:27:00 2009 -0400
@@ -33,11 +33,14 @@
</div>
%endfor
- <div class="form-row"><input type="submit" value="${form.submit_text}"></div>
%else:
<div class="form-row"><i>No options</i></div>
%endif
</table>
</form>
</div>
-</div>
\ No newline at end of file
+</div>
+
+<script type="text/javascript">
+ workflow.enable_auto_save();
+</script>
diff -r c5968ee9399b -r ea6708c96cd1 templates/workflow/editor_tool_form.mako
--- a/templates/workflow/editor_tool_form.mako Wed Aug 19 11:33:58 2009 -0400
+++ b/templates/workflow/editor_tool_form.mako Wed Aug 19 17:27:00 2009 -0400
@@ -93,7 +93,7 @@
<div style="clear: both"></div>
</div>
</%def>
-
+
<div class="toolForm">
<div class="toolFormTitle">Tool: ${tool.name}</div>
<div class="toolFormBody">
@@ -105,9 +105,11 @@
%endif
${do_inputs( inputs, values, errors, "" )}
%endfor
- <div class="form-row">
- <input type="submit" id="tool-form-save-button" value="Save"></input>
- </div>
</form>
</div>
-</div>
\ No newline at end of file
+</div>
+
+<script type="text/javascript">
+ workflow.enable_auto_save();
+</script>
+
1
0
24 Aug '09
details: http://www.bx.psu.edu/hg/galaxy/rev/7d48dc7e60b4
changeset: 2569:7d48dc7e60b4
user: Kelly Vincent <kpvincent(a)bx.psu.edu>
date: Wed Aug 19 11:08:58 2009 -0400
description:
Added sniff import statement to tabular.py so sam tests will pass
1 file(s) affected in this change:
lib/galaxy/datatypes/tabular.py
diffs (11 lines):
diff -r 670f8800a2bf -r 7d48dc7e60b4 lib/galaxy/datatypes/tabular.py
--- a/lib/galaxy/datatypes/tabular.py Wed Aug 19 09:13:21 2009 -0400
+++ b/lib/galaxy/datatypes/tabular.py Wed Aug 19 11:08:58 2009 -0400
@@ -11,6 +11,7 @@
from cgi import escape
from galaxy.datatypes import metadata
from galaxy.datatypes.metadata import MetadataElement
+from sniff import *
log = logging.getLogger(__name__)
1
0
24 Aug '09
details: http://www.bx.psu.edu/hg/galaxy/rev/e1f9132aebe0
changeset: 2570:e1f9132aebe0
user: Kanwei Li <kanwei(a)gmail.com>
date: Thu Aug 06 16:07:53 2009 -0400
description:
Can only resize overview using the border panels
1 file(s) affected in this change:
static/scripts/galaxy.workflow_editor.canvas.js
diffs (12 lines):
diff -r 397800eff312 -r e1f9132aebe0 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js Thu Aug 06 15:25:18 2009 -0400
+++ b/static/scripts/galaxy.workflow_editor.canvas.js Thu Aug 06 16:07:53 2009 -0400
@@ -805,6 +805,8 @@
self.draw_overview();
});
+ $("#overview-border>*").bind("drag", function(e) { });
+
},
update_viewport_overlay: function() {
var cc = this.cc,
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/3c64aa0a0f85
changeset: 2571:3c64aa0a0f85
user: Kanwei Li <kanwei(a)gmail.com>
date: Thu Aug 06 16:11:40 2009 -0400
description:
Documentation for dragging change
1 file(s) affected in this change:
static/scripts/galaxy.workflow_editor.canvas.js
diffs (12 lines):
diff -r e1f9132aebe0 -r 3c64aa0a0f85 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js Thu Aug 06 16:07:53 2009 -0400
+++ b/static/scripts/galaxy.workflow_editor.canvas.js Thu Aug 06 16:11:40 2009 -0400
@@ -805,6 +805,8 @@
self.draw_overview();
});
+ /* Disable dragging for child elements of the panel so that resizing can
+ only be done with the border panels */
$("#overview-border>*").bind("drag", function(e) { });
},
1
0
24 Aug '09
details: http://www.bx.psu.edu/hg/galaxy/rev/6b8e1ff3141a
changeset: 2573:6b8e1ff3141a
user: Kanwei Li <kanwei(a)gmail.com>
date: Mon Aug 10 13:27:04 2009 -0400
description:
Made workflow's "Input Dataset" name text field smaller to fit default size
1 file(s) affected in this change:
templates/workflow/editor_generic_form.mako
diffs (12 lines):
diff -r a6be5c3955e9 -r 6b8e1ff3141a templates/workflow/editor_generic_form.mako
--- a/templates/workflow/editor_generic_form.mako Mon Aug 10 12:09:50 2009 -0400
+++ b/templates/workflow/editor_generic_form.mako Mon Aug 10 13:27:04 2009 -0400
@@ -15,7 +15,7 @@
${input.label}:
</label>
<div style="float: left; width: 250px; margin-right: 10px;">
- <input type="${input.type}" name="${input.name}" value="${input.value}" size="40">
+ <input type="${input.type}" name="${input.name}" value="${input.value}" size="30">
</div>
%if input.error:
<div style="float: left; color: red; font-weight: bold; padding-top: 1px; padding-bottom: 3px;">
1
0
24 Aug '09
details: http://www.bx.psu.edu/hg/galaxy/rev/a6be5c3955e9
changeset: 2572:a6be5c3955e9
user: Kanwei Li <kanwei(a)gmail.com>
date: Mon Aug 10 12:09:50 2009 -0400
description:
Allows storing of multiple preferences in one cookie using JSON. Use this to store workflow overview settings
3 file(s) affected in this change:
static/scripts/json2.js
static/scripts/json_cookie.js
templates/workflow/editor.mako
diffs (641 lines):
diff -r 3c64aa0a0f85 -r a6be5c3955e9 static/scripts/json2.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/json2.js Mon Aug 10 12:09:50 2009 -0400
@@ -0,0 +1,476 @@
+/*
+ http://www.JSON.org/json2.js
+ 2009-06-29
+
+ Public Domain.
+
+ NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+
+ See http://www.JSON.org/js.html
+
+ This file creates a global JSON object containing two methods: stringify
+ and parse.
+
+ JSON.stringify(value, replacer, space)
+ value any JavaScript value, usually an object or array.
+
+ replacer an optional parameter that determines how object
+ values are stringified for objects. It can be a
+ function or an array of strings.
+
+ space an optional parameter that specifies the indentation
+ of nested structures. If it is omitted, the text will
+ be packed without extra whitespace. If it is a number,
+ it will specify the number of spaces to indent at each
+ level. If it is a string (such as '\t' or ' '),
+ it contains the characters used to indent at each level.
+
+ This method produces a JSON text from a JavaScript value.
+
+ When an object value is found, if the object contains a toJSON
+ method, its toJSON method will be called and the result will be
+ stringified. A toJSON method does not serialize: it returns the
+ value represented by the name/value pair that should be serialized,
+ or undefined if nothing should be serialized. The toJSON method
+ will be passed the key associated with the value, and this will be
+ bound to the object holding the key.
+
+ For example, this would serialize Dates as ISO strings.
+
+ Date.prototype.toJSON = function (key) {
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10 ? '0' + n : n;
+ }
+
+ return this.getUTCFullYear() + '-' +
+ f(this.getUTCMonth() + 1) + '-' +
+ f(this.getUTCDate()) + 'T' +
+ f(this.getUTCHours()) + ':' +
+ f(this.getUTCMinutes()) + ':' +
+ f(this.getUTCSeconds()) + 'Z';
+ };
+
+ You can provide an optional replacer method. It will be passed the
+ key and value of each member, with this bound to the containing
+ object. The value that is returned from your method will be
+ serialized. If your method returns undefined, then the member will
+ be excluded from the serialization.
+
+ If the replacer parameter is an array of strings, then it will be
+ used to select the members to be serialized. It filters the results
+ such that only members with keys listed in the replacer array are
+ stringified.
+
+ Values that do not have JSON representations, such as undefined or
+ functions, will not be serialized. Such values in objects will be
+ dropped; in arrays they will be replaced with null. You can use
+ a replacer function to replace those with JSON values.
+ JSON.stringify(undefined) returns undefined.
+
+ The optional space parameter produces a stringification of the
+ value that is filled with line breaks and indentation to make it
+ easier to read.
+
+ If the space parameter is a non-empty string, then that string will
+ be used for indentation. If the space parameter is a number, then
+ the indentation will be that many spaces.
+
+ Example:
+
+ text = JSON.stringify(['e', {pluribus: 'unum'}]);
+ // text is '["e",{"pluribus":"unum"}]'
+
+
+ text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
+ // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
+
+ text = JSON.stringify([new Date()], function (key, value) {
+ return this[key] instanceof Date ?
+ 'Date(' + this[key] + ')' : value;
+ });
+ // text is '["Date(---current time---)"]'
+
+
+ JSON.parse(text, reviver)
+ This method parses a JSON text to produce an object or array.
+ It can throw a SyntaxError exception.
+
+ The optional reviver parameter is a function that can filter and
+ transform the results. It receives each of the keys and values,
+ and its return value is used instead of the original value.
+ If it returns what it received, then the structure is not modified.
+ If it returns undefined then the member is deleted.
+
+ Example:
+
+ // Parse the text. Values that look like ISO date strings will
+ // be converted to Date objects.
+
+ myData = JSON.parse(text, function (key, value) {
+ var a;
+ if (typeof value === 'string') {
+ a =
+/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
+ if (a) {
+ return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+ +a[5], +a[6]));
+ }
+ }
+ return value;
+ });
+
+ myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
+ var d;
+ if (typeof value === 'string' &&
+ value.slice(0, 5) === 'Date(' &&
+ value.slice(-1) === ')') {
+ d = new Date(value.slice(5, -1));
+ if (d) {
+ return d;
+ }
+ }
+ return value;
+ });
+
+
+ This is a reference implementation. You are free to copy, modify, or
+ redistribute.
+
+ This code should be minified before deployment.
+ See http://javascript.crockford.com/jsmin.html
+
+ USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
+ NOT CONTROL.
+*/
+
+/*jslint evil: true */
+
+/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
+ call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
+ getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
+ lastIndex, length, parse, prototype, push, replace, slice, stringify,
+ test, toJSON, toString, valueOf
+*/
+
+// Create a JSON object only if one does not already exist. We create the
+// methods in a closure to avoid creating global variables.
+
+var JSON = JSON || {};
+
+(function () {
+
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10 ? '0' + n : n;
+ }
+
+ if (typeof Date.prototype.toJSON !== 'function') {
+
+ Date.prototype.toJSON = function (key) {
+
+ return isFinite(this.valueOf()) ?
+ this.getUTCFullYear() + '-' +
+ f(this.getUTCMonth() + 1) + '-' +
+ f(this.getUTCDate()) + 'T' +
+ f(this.getUTCHours()) + ':' +
+ f(this.getUTCMinutes()) + ':' +
+ f(this.getUTCSeconds()) + 'Z' : null;
+ };
+
+ String.prototype.toJSON =
+ Number.prototype.toJSON =
+ Boolean.prototype.toJSON = function (key) {
+ return this.valueOf();
+ };
+ }
+
+ var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ gap,
+ indent,
+ meta = { // table of character substitutions
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"' : '\\"',
+ '\\': '\\\\'
+ },
+ rep;
+
+
+ function quote(string) {
+
+// If the string contains no control characters, no quote characters, and no
+// backslash characters, then we can safely slap some quotes around it.
+// Otherwise we must also replace the offending characters with safe escape
+// sequences.
+
+ escapable.lastIndex = 0;
+ return escapable.test(string) ?
+ '"' + string.replace(escapable, function (a) {
+ var c = meta[a];
+ return typeof c === 'string' ? c :
+ '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ }) + '"' :
+ '"' + string + '"';
+ }
+
+
+ function str(key, holder) {
+
+// Produce a string from holder[key].
+
+ var i, // The loop counter.
+ k, // The member key.
+ v, // The member value.
+ length,
+ mind = gap,
+ partial,
+ value = holder[key];
+
+// If the value has a toJSON method, call it to obtain a replacement value.
+
+ if (value && typeof value === 'object' &&
+ typeof value.toJSON === 'function') {
+ value = value.toJSON(key);
+ }
+
+// If we were called with a replacer function, then call the replacer to
+// obtain a replacement value.
+
+ if (typeof rep === 'function') {
+ value = rep.call(holder, key, value);
+ }
+
+// What happens next depends on the value's type.
+
+ switch (typeof value) {
+ case 'string':
+ return quote(value);
+
+ case 'number':
+
+// JSON numbers must be finite. Encode non-finite numbers as null.
+
+ return isFinite(value) ? String(value) : 'null';
+
+ case 'boolean':
+ case 'null':
+
+// If the value is a boolean or null, convert it to a string. Note:
+// typeof null does not produce 'null'. The case is included here in
+// the remote chance that this gets fixed someday.
+
+ return String(value);
+
+// If the type is 'object', we might be dealing with an object or an array or
+// null.
+
+ case 'object':
+
+// Due to a specification blunder in ECMAScript, typeof null is 'object',
+// so watch out for that case.
+
+ if (!value) {
+ return 'null';
+ }
+
+// Make an array to hold the partial results of stringifying this object value.
+
+ gap += indent;
+ partial = [];
+
+// Is the value an array?
+
+ if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+// The value is an array. Stringify every element. Use null as a placeholder
+// for non-JSON values.
+
+ length = value.length;
+ for (i = 0; i < length; i += 1) {
+ partial[i] = str(i, value) || 'null';
+ }
+
+// Join all of the elements together, separated with commas, and wrap them in
+// brackets.
+
+ v = partial.length === 0 ? '[]' :
+ gap ? '[\n' + gap +
+ partial.join(',\n' + gap) + '\n' +
+ mind + ']' :
+ '[' + partial.join(',') + ']';
+ gap = mind;
+ return v;
+ }
+
+// If the replacer is an array, use it to select the members to be stringified.
+
+ if (rep && typeof rep === 'object') {
+ length = rep.length;
+ for (i = 0; i < length; i += 1) {
+ k = rep[i];
+ if (typeof k === 'string') {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ } else {
+
+// Otherwise, iterate through all of the keys in the object.
+
+ for (k in value) {
+ if (Object.hasOwnProperty.call(value, k)) {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ }
+
+// Join all of the member texts together, separated with commas,
+// and wrap them in braces.
+
+ v = partial.length === 0 ? '{}' :
+ gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
+ mind + '}' : '{' + partial.join(',') + '}';
+ gap = mind;
+ return v;
+ }
+ }
+
+// If the JSON object does not yet have a stringify method, give it one.
+
+ if (typeof JSON.stringify !== 'function') {
+ JSON.stringify = function (value, replacer, space) {
+
+// The stringify method takes a value and an optional replacer, and an optional
+// space parameter, and returns a JSON text. The replacer can be a function
+// that can replace values, or an array of strings that will select the keys.
+// A default replacer method can be provided. Use of the space parameter can
+// produce text that is more easily readable.
+
+ var i;
+ gap = '';
+ indent = '';
+
+// If the space parameter is a number, make an indent string containing that
+// many spaces.
+
+ if (typeof space === 'number') {
+ for (i = 0; i < space; i += 1) {
+ indent += ' ';
+ }
+
+// If the space parameter is a string, it will be used as the indent string.
+
+ } else if (typeof space === 'string') {
+ indent = space;
+ }
+
+// If there is a replacer, it must be a function or an array.
+// Otherwise, throw an error.
+
+ rep = replacer;
+ if (replacer && typeof replacer !== 'function' &&
+ (typeof replacer !== 'object' ||
+ typeof replacer.length !== 'number')) {
+ throw new Error('JSON.stringify');
+ }
+
+// Make a fake root object containing our value under the key of ''.
+// Return the result of stringifying the value.
+
+ return str('', {'': value});
+ };
+ }
+
+
+// If the JSON object does not yet have a parse method, give it one.
+
+ if (typeof JSON.parse !== 'function') {
+ JSON.parse = function (text, reviver) {
+
+// The parse method takes a text and an optional reviver function, and returns
+// a JavaScript value if the text is a valid JSON text.
+
+ var j;
+
+ function walk(holder, key) {
+
+// The walk method is used to recursively walk the resulting structure so
+// that modifications can be made.
+
+ var k, v, value = holder[key];
+ if (value && typeof value === 'object') {
+ for (k in value) {
+ if (Object.hasOwnProperty.call(value, k)) {
+ v = walk(value, k);
+ if (v !== undefined) {
+ value[k] = v;
+ } else {
+ delete value[k];
+ }
+ }
+ }
+ }
+ return reviver.call(holder, key, value);
+ }
+
+
+// Parsing happens in four stages. In the first stage, we replace certain
+// Unicode characters with escape sequences. JavaScript handles many characters
+// incorrectly, either silently deleting them, or treating them as line endings.
+
+ cx.lastIndex = 0;
+ if (cx.test(text)) {
+ text = text.replace(cx, function (a) {
+ return '\\u' +
+ ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ });
+ }
+
+// In the second stage, we run the text against regular expressions that look
+// for non-JSON patterns. We are especially concerned with '()' and 'new'
+// because they can cause invocation, and '=' because it can cause mutation.
+// But just to be safe, we want to reject all unexpected forms.
+
+// We split the second stage into 4 regexp operations in order to work around
+// crippling inefficiencies in IE's and Safari's regexp engines. First we
+// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+// replace all simple value tokens with ']' characters. Third, we delete all
+// open brackets that follow a colon or comma or that begin the text. Finally,
+// we look to see that the remaining characters are only whitespace or ']' or
+// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+ if (/^[\],:{}\s]*$/.
+test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
+replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+// In the third stage we use the eval function to compile the text into a
+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+// in JavaScript: it can begin a block or an object literal. We wrap the text
+// in parens to eliminate the ambiguity.
+
+ j = eval('(' + text + ')');
+
+// In the optional fourth stage, we recursively walk the new structure, passing
+// each name/value pair to a reviver function for possible transformation.
+
+ return typeof reviver === 'function' ?
+ walk({'': j}, '') : j;
+ }
+
+// If the text is not JSON parseable, then a SyntaxError is thrown.
+
+ throw new SyntaxError('JSON.parse');
+ };
+ }
+}());
diff -r 3c64aa0a0f85 -r a6be5c3955e9 static/scripts/json_cookie.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/json_cookie.js Mon Aug 10 12:09:50 2009 -0400
@@ -0,0 +1,61 @@
+/*
+ JSONCookie: Uses JSON to allow the settings of multiple preferences in one cookie.
+ Kanwei Li, 2009
+
+ cookie = new JSONCookie("cookie_name"); // Pass in the name of the cookie
+
+ // Gets the value of a preference, returns optional second argument if pref not found
+ cookie.get("pref", "val_if_not_found");
+
+ cookie.set("pref", "val"); // Sets a value for the preference and saves cookie
+ cookie.unset("pref"); // Unsets the preference and saves cookie
+ cookie.clear() // Deletes the cookie
+
+*/
+
+function JSONCookie(name) {
+ this.cookie_name = name;
+
+}
+
+JSONCookie.prototype = {
+ json_data : function() {
+ cookie = $.cookie(this.cookie_name);
+ return cookie ? JSON.parse(cookie) : null;
+ },
+
+ save : function(data) {
+ $.cookie(this.cookie_name, JSON.stringify(data));
+ },
+
+ get : function(attr, else_val) {
+ data = this.json_data();
+ if (data && data[attr]) { return data[attr];
+ } else if (else_val) { return else_val;
+ } else { return null;
+ }
+ },
+
+ set : function(attr, val) {
+ data = this.json_data();
+ if (data) {
+ data[attr] = val;
+ } else {
+ data = { attr : val }
+ }
+ this.save(data);
+ },
+
+ unset : function(attr) {
+ data = this.json_data();
+ if (data) {
+ delete data[attr];
+ }
+ this.save(data);
+ },
+
+ clear : function() {
+ this.save(null);
+ }
+
+};
\ No newline at end of file
diff -r 3c64aa0a0f85 -r a6be5c3955e9 templates/workflow/editor.mako
--- a/templates/workflow/editor.mako Thu Aug 06 16:11:40 2009 -0400
+++ b/templates/workflow/editor.mako Mon Aug 10 12:09:50 2009 -0400
@@ -31,6 +31,9 @@
<script type='text/javascript' src="${h.url_for('/static/scripts/jquery.event.hover.js')}"> </script>
<script type='text/javascript' src="${h.url_for('/static/scripts/jquery.form.js')}"> </script>
<script type='text/javascript' src="${h.url_for('/static/scripts/jquery.json.js')}"> </script>
+ <script type='text/javascript' src="${h.url_for('/static/scripts/jquery.cookie.js')}"> </script>
+ <script type='text/javascript' src="${h.url_for('/static/scripts/json2.js')}"> </script>
+ <script type='text/javascript' src="${h.url_for('/static/scripts/json_cookie.js')}"> </script>
<script type='text/javascript' src="${h.url_for('/static/scripts/galaxy.base.js')}"> </script>
<script type='text/javascript' src="${h.url_for('/static/scripts/galaxy.workflow_editor.canvas.js')}"> </script>
@@ -56,6 +59,10 @@
}
// Canvas overview management
canvas_manager = new CanvasManager( $("#canvas-viewport"), $("#overview") );
+
+ // Preferences cookie stored as JSON so that only one cookie is needed for multiple settings
+ var prefs_cookie = new JSONCookie("galaxy.workflow");
+
// Initialize workflow state
reset();
// Load the datatype info
@@ -121,17 +128,42 @@
canvas_manager.draw_overview();
});
- /* Lets the viewport be toggled visible and invisible, adjusting the arrows accordingly */
+ // Stores the size of the overview in a cookie when it's resized
+ $("#overview-border").bind( "dragend", function( e ) {
+ var op = $(this).offsetParent();
+ var opo = op.offset();
+ var new_size = Math.max( op.width() - ( e.offsetX - opo.left ),
+ op.height() - ( e.offsetY - opo.top ) );
+ prefs_cookie.set("overview-size", new_size);
+ });
+
+ // On load, set the size to the pref stored in cookie if it exists
+ overview_size = prefs_cookie.get("overview-size");
+ if (overview_size) {
+ $("#overview-border").css( {
+ width: overview_size,
+ height: overview_size
+ });
+ }
+
+ function show_overview() {
+ prefs_cookie.unset("overview-off");
+ $("#overview-border").css("right", "0px");
+ $("#close-viewport").css("background-position", "0px 0px");
+ }
+
+ function hide_overview() {
+ prefs_cookie.set("overview-off", true);
+ $("#overview-border").css("right", "20000px");
+ $("#close-viewport").css("background-position", "12px 0px");
+ }
+
+ // Show viewport on load unless pref says it's off
+ prefs_cookie.get("overview-off") == true ? hide_overview() : show_overview()
+
+ // Lets the overview be toggled visible and invisible, adjusting the arrows accordingly
$("#close-viewport").click( function() {
- if ( $("#overview-border").css("right") == "0px" ) {
- $("#overview-border").css("right", "20000px");
- $("#close-viewport").css("background-position", "12px 0px");
-
- } else {
- $("#overview-border").css("right", "0px");
- $("#close-viewport").css("background-position", "0px 0px");
- }
-
+ $("#overview-border").css("right") == "0px" ? hide_overview() : show_overview();
});
// Unload handler
@@ -642,7 +674,7 @@
<div id="canvas-viewport" style="width: 100%; height: 100%; position: absolute; overflow: hidden; background: #EEEEEE; background: white url(${h.url_for('/static/images/light_gray_grid.gif')}) repeat;">
<div id="canvas-container" style="position: absolute; width: 100%; height: 100%;"></div>
</div>
- <div id="overview-border" style="position: absolute; width: 150px; height: 150px; right: 0px; bottom: 0px; border-top: solid gray 1px; border-left: solid grey 1px; padding: 7px 0 0 7px; background: #EEEEEE no-repeat url(${h.url_for('/static/images/resizable.png')}); z-index: 20000; overflow: hidden; max-width: 300px; max-height: 300px; min-width: 50px; min-height: 50px">
+ <div id="overview-border" style="position: absolute; width: 150px; height: 150px; right: 20000px; bottom: 0px; border-top: solid gray 1px; border-left: solid grey 1px; padding: 7px 0 0 7px; background: #EEEEEE no-repeat url(${h.url_for('/static/images/resizable.png')}); z-index: 20000; overflow: hidden; max-width: 300px; max-height: 300px; min-width: 50px; min-height: 50px">
<div style="position: relative; overflow: hidden; width: 100%; height: 100%; border-top: solid gray 1px; border-left: solid grey 1px;">
<div id="overview" style="position: absolute;">
<canvas width="0" height="0" style="background: white; width: 100%; height: 100%;" id="overview-canvas"></canvas>
@@ -650,7 +682,7 @@
</div>
</div>
</div>
- <div id="close-viewport" style="border-left: 1px solid #999; border-top: 1px solid #999; background: #ddd url(${h.url_for('/static/images/overview_arrows.png')}); position: absolute; right: 0px; bottom: 0px; width: 12px; height: 12px; z-index: 25000;"></div>
+ <div id="close-viewport" style="border-left: 1px solid #999; border-top: 1px solid #999; background: #ddd url(${h.url_for('/static/images/overview_arrows.png')}) 12px 0px; position: absolute; right: 0px; bottom: 0px; width: 12px; height: 12px; z-index: 25000;"></div>
</div>
</%def>
1
0
24 Aug '09
details: http://www.bx.psu.edu/hg/galaxy/rev/7df41ad788de
changeset: 2574:7df41ad788de
user: Kanwei Li <kanwei(a)gmail.com>
date: Tue Aug 11 15:46:23 2009 -0400
description:
Escape HTML entities using cgi.escape so that html attributes (like value="") don't truncate with quotes.
Fixes #123
2 file(s) affected in this change:
lib/galaxy/web/form_builder.py
templates/workflow/editor_generic_form.mako
diffs (98 lines):
diff -r 6b8e1ff3141a -r 7df41ad788de lib/galaxy/web/form_builder.py
--- a/lib/galaxy/web/form_builder.py Mon Aug 10 13:27:04 2009 -0400
+++ b/lib/galaxy/web/form_builder.py Tue Aug 11 15:46:23 2009 -0400
@@ -3,6 +3,7 @@
"""
import logging,sys
+from cgi import escape
log = logging.getLogger(__name__)
class BaseField(object):
@@ -28,7 +29,7 @@
self.value = value or ""
def get_html( self, prefix="" ):
return '<input type="text" name="%s%s" size="%d" value="%s">' \
- % ( prefix, self.name, self.size, self.value )
+ % ( prefix, self.name, self.size, escape(str(self.value), quote=True) )
def set_size(self, size):
self.size = int( size )
@@ -49,7 +50,7 @@
self.value = value or ""
def get_html( self, prefix="" ):
return '<textarea name="%s%s" rows="%d" cols="%d">%s</textarea>' \
- % ( prefix, self.name, self.rows, self.cols, self.value )
+ % ( prefix, self.name, self.rows, self.cols, escape(str(self.value), quote=True) )
def set_size(self, rows, cols):
self.rows = rows
self.cols = cols
@@ -113,7 +114,7 @@
self.name = name
self.value = value or ""
def get_html( self, prefix="" ):
- return '<input type="hidden" name="%s%s" value="%s">' % ( prefix, self.name, self.value )
+ return '<input type="hidden" name="%s%s" value="%s">' % ( prefix, self.name, escape(str(self.value), quote=True) )
class SelectField(BaseField):
"""
@@ -190,9 +191,9 @@
if len(self.options) > 2 and ctr % 2 == 1:
style = " class=\"odd_row\""
if selected:
- rval.append( '<div%s><input type="checkbox" name="%s%s" value="%s" checked>%s</div>' % ( style, prefix, self.name, value, text) )
+ rval.append( '<div%s><input type="checkbox" name="%s%s" value="%s" checked>%s</div>' % ( style, prefix, self.name, escape(str(value), quote=True), text) )
else:
- rval.append( '<div%s><input type="checkbox" name="%s%s" value="%s">%s</div>' % ( style, prefix, self.name, value, text) )
+ rval.append( '<div%s><input type="checkbox" name="%s%s" value="%s">%s</div>' % ( style, prefix, self.name, escape(str(value), quote=True), text) )
ctr += 1
return "\n".join( rval )
def get_html_radio( self, prefix="" ):
@@ -204,7 +205,7 @@
style = " class=\"odd_row\""
if selected: selected_text = " checked"
else: selected_text = ""
- rval.append( '<div%s><input type="radio" name="%s%s"%s value="%s"%s>%s</div>' % ( style, prefix, self.name, self.refresh_on_change_text, value, selected_text, text ) )
+ rval.append( '<div%s><input type="radio" name="%s%s"%s value="%s"%s>%s</div>' % ( style, prefix, self.name, self.refresh_on_change_text, escape(str(value), quote=True), selected_text, text ) )
ctr += 1
return "\n".join( rval )
def get_html_default( self, prefix="" ):
@@ -217,9 +218,9 @@
selected_text = " selected"
last_selected_value = value
else: selected_text = ""
- rval.append( '<option value="%s"%s>%s</option>' % ( value, selected_text, text ) )
+ rval.append( '<option value="%s"%s>%s</option>' % ( escape(str(value), quote=True), selected_text, text ) )
if last_selected_value:
- last_selected_value = ' last_selected_value="%s"' % last_selected_value
+ last_selected_value = ' last_selected_value="%s"' % escape(str(last_selected_value), quote=True)
rval.insert( 0, '<select name="%s%s"%s%s%s>' % ( prefix, self.name, multiple, self.refresh_on_change_text, last_selected_value ) )
rval.append( '</select>' )
return "\n".join( rval )
@@ -326,12 +327,12 @@
if option['value'] in expanded_options:
default_state = 'expanded'
default_icon = '[-]'
- html.append( '<li><span class="toolParameterExpandableCollapsable">%s</span><input type="%s" name="%s%s" value="%s"%s">%s' % ( default_icon, self.display, prefix, self.name, option['value'], selected, option['name']) )
+ html.append( '<li><span class="toolParameterExpandableCollapsable">%s</span><input type="%s" name="%s%s" value="%s"%s">%s' % ( default_icon, self.display, prefix, self.name, escape(str(option['value']), quote=True), selected, option['name']) )
html.append( '<ul class="toolParameterExpandableCollapsable" default_state="%s">' % default_state )
recurse_options( html, option['options'], expanded_options )
html.append( '</ul>')
else:
- html.append( '<li><input type="%s" name="%s%s" value="%s"%s">%s' % ( self.display, prefix, self.name, option['value'], selected, option['name']) )
+ html.append( '<li><input type="%s" name="%s%s" value="%s"%s">%s' % ( self.display, prefix, self.name, escape(str(option['value']), quote=True), selected, option['name']) )
html.append( '</li>' )
rval = []
rval.append( '<div><ul class="toolParameterExpandableCollapsable">' )
diff -r 6b8e1ff3141a -r 7df41ad788de templates/workflow/editor_generic_form.mako
--- a/templates/workflow/editor_generic_form.mako Mon Aug 10 13:27:04 2009 -0400
+++ b/templates/workflow/editor_generic_form.mako Tue Aug 11 15:46:23 2009 -0400
@@ -15,7 +15,7 @@
${input.label}:
</label>
<div style="float: left; width: 250px; margin-right: 10px;">
- <input type="${input.type}" name="${input.name}" value="${input.value}" size="30">
+ <input type="${input.type}" name="${input.name | h}" value="${input.value | h}" size="30">
</div>
%if input.error:
<div style="float: left; color: red; font-weight: bold; padding-top: 1px; padding-bottom: 3px;">
1
0
24 Aug '09
details: http://www.bx.psu.edu/hg/galaxy/rev/55c0eb35fad7
changeset: 2575:55c0eb35fad7
user: Kanwei Li <kanwei(a)gmail.com>
date: Thu Aug 13 13:16:58 2009 -0400
description:
Implemented local storage for preferences, obsoleting cookies that were used for this purpose
7 file(s) affected in this change:
static/jStore.Flash.html
static/jStore.swf
static/scripts/jquery.jstore-all.js
static/scripts/packed/jquery.jstore-all.js
static/scripts/packed/json2.js
templates/root/history.mako
templates/workflow/editor.mako
diffs (1380 lines):
diff -r 7df41ad788de -r 55c0eb35fad7 static/jStore.Flash.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/jStore.Flash.html Thu Aug 13 13:16:58 2009 -0400
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+ <head>
+ <title>Flash External Object</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <script type="text/javascript">
+ /**
+ * This function captures the flash_ready event. We need to relay this
+ * back to the parent so it knows flash is ready.
+ */
+ function flash_ready(){
+ parent.flash_ready();
+ }
+ </script>
+ </head>
+ <body>
+ <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#versi…" width="1" height="1" id="jStoreFlash"><param name="allowScriptAccess" value="always" /><param name="movie" value="jStore.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffcc00" /><embed src="jStore.swf" quality="high" bgcolor="#ffcc00" width="1" height="1" name="jStoreFlash" align="middle" allowScriptAccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" /></object>
+ </body>
+</html>
\ No newline at end of file
diff -r 7df41ad788de -r 55c0eb35fad7 static/jStore.swf
Binary file static/jStore.swf has changed
diff -r 7df41ad788de -r 55c0eb35fad7 static/scripts/jquery.jstore-all.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/jquery.jstore-all.js Thu Aug 13 13:16:58 2009 -0400
@@ -0,0 +1,748 @@
+/*!
+ * jStore - Persistent Client-Side Storage
+ *
+ * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
+ *
+ * Dual licensed under:
+ * MIT: http://www.opensource.org/licenses/mit-license.php
+ * GPLv3: http://www.opensource.org/licenses/gpl-3.0.html
+ *//**
+ * Javascript Class Framework
+ *
+ * Copyright (c) 2008 John Resig (http://ejohn.org/blog/simple-javascript-inheritance/)
+ * Inspired by base2 and Prototype
+ */
+(function(){
+ var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
+
+ // The base Class implementation (does nothing)
+ this.Class = function(){};
+
+ // Create a new Class that inherits from this class
+ Class.extend = function(prop) {
+ var _super = this.prototype;
+
+ // Instantiate a base class (but only create the instance,
+ // don't run the init constructor)
+ initializing = true;
+ var prototype = new this();
+ initializing = false;
+
+ // Copy the properties over onto the new prototype
+ for (var name in prop) {
+ // Check if we're overwriting an existing function
+ prototype[name] = typeof prop[name] == "function" &&
+ typeof _super[name] == "function" && fnTest.test(prop[name]) ?
+ (function(name, fn){
+ return function() {
+ var tmp = this._super;
+
+ // Add a new ._super() method that is the same method
+ // but on the super-class
+ this._super = _super[name];
+
+ // The method only need to be bound temporarily, so we
+ // remove it when we're done executing
+ var ret = fn.apply(this, arguments);
+ this._super = tmp;
+
+ return ret;
+ };
+ })(name, prop[name]) :
+ prop[name];
+ }
+
+ // The dummy class constructor
+ function Class() {
+ // All construction is actually done in the init method
+ if ( !initializing && this.init )
+ this.init.apply(this, arguments);
+ }
+
+ // Populate our constructed prototype object
+ Class.prototype = prototype;
+
+ // Enforce the constructor to be what we expect
+ Class.constructor = Class;
+
+ // And make this class extendable
+ Class.extend = arguments.callee;
+
+ return Class;
+ };
+})();
+/*!
+ * jStore Delegate Framework
+ * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
+ */
+(function($){
+
+ this.jStoreDelegate = Class.extend({
+ init: function(parent){
+ // The Object this delgate operates for
+ this.parent = parent;
+ // Container for callbacks to dispatch.
+ // eventType => [ callback, callback, ... ]
+ this.callbacks = {};
+ },
+ bind: function(event, callback){
+ if ( !$.isFunction(callback) ) return this;
+ if ( !this.callbacks[ event ] ) this.callbacks[ event ] = [];
+
+ this.callbacks[ event ].push(callback);
+
+ return this;
+ },
+ trigger: function(){
+ var parent = this.parent,
+ args = [].slice.call(arguments),
+ event = args.shift(),
+ handlers = this.callbacks[ event ];
+
+ if ( !handlers ) return false;
+
+ $.each(handlers, function(){ this.apply(parent, args) });
+ return this;
+ }
+ });
+
+})(jQuery);/**
+ * jStore-jQuery Interface
+ * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
+ */
+(function($){
+
+ // Setup the jStore namespace in jQuery for options storage
+ $.jStore = {};
+
+ // Seed the options in
+ $.extend($.jStore, {
+ EngineOrder: [],
+ // Engines should put their availability tests within jStore.Availability
+ Availability: {},
+ // Defined engines should enter themselves into the jStore.Engines
+ Engines: {},
+ // Instanciated engines should exist within jStore.Instances
+ Instances: {},
+ // The current engine to use for storage
+ CurrentEngine: null,
+ // Provide global settings for overwriting
+ defaults: {
+ project: null,
+ engine: null,
+ autoload: true,
+ flash: 'jStore.Flash.html'
+ },
+ // Boolean for ready state handling
+ isReady: false,
+ // Boolean for flash ready state handling
+ isFlashReady: false,
+ // An event delegate
+ delegate: new jStoreDelegate($.jStore)
+ .bind('jStore-ready', function(engine){
+ $.jStore.isReady = true;
+ if ($.jStore.defaults.autoload) engine.connect();
+ })
+ .bind('flash-ready', function(){
+ $.jStore.isFlashReady = true;
+ })
+ });
+
+ // Enable ready callback for jStore
+ $.jStore.ready = function(callback){
+ if ($.jStore.isReady) callback.apply($.jStore, [$.jStore.CurrentEngine]);
+ else $.jStore.delegate.bind('jStore-ready', callback);
+ }
+
+ // Enable failure callback registration for jStore
+ $.jStore.fail = function(callback){
+ $.jStore.delegate.bind('jStore-failure', callback);
+ }
+
+ // Enable ready callback for Flash
+ $.jStore.flashReady = function(callback){
+ if ($.jStore.isFlashReady) callback.apply($.jStore, [$.jStore.CurrentEngine]);
+ else $.jStore.delegate.bind('flash-ready', callback);
+ }
+
+ // Enable and test an engine
+ $.jStore.use = function(engine, project, identifier){
+ project = project || $.jStore.defaults.project || location.hostname.replace(/\./g, '-') || 'unknown';
+
+ var e = $.jStore.Engines[engine.toLowerCase()] || null,
+ name = (identifier ? identifier + '.' : '') + project + '.' + engine;
+
+ if ( !e ) throw 'JSTORE_ENGINE_UNDEFINED';
+
+ // Instanciate the engine
+ e = new e(project, name);
+
+ // Prevent against naming conflicts
+ if ($.jStore.Instances[name]) throw 'JSTORE_JRI_CONFLICT';
+
+ // Test the engine
+ if (e.isAvailable()){
+ $.jStore.Instances[name] = e; // The Easy Way
+ if (!$.jStore.CurrentEngine){
+ $.jStore.CurrentEngine = e;
+ }
+ $.jStore.delegate.trigger('jStore-ready', e);
+ } else {
+ if (!e.autoload) // Not available
+ throw 'JSTORE_ENGINE_UNAVILABLE';
+ else { // The hard way
+ e.included(function(){
+ if (this.isAvailable()) { // Worked out
+ $.jStore.Instances[name] = this;
+ // If there is no current engine, use this one
+ if (!$.jStore.CurrentEngine){
+ $.jStore.CurrentEngine = this;
+ }
+ $.jStore.delegate.trigger('jStore-ready', this);
+ }
+ else $.jStore.delegate.trigger('jStore-failure', this);
+ }).include();
+ }
+ }
+ }
+
+ // Set the current storage engine
+ $.jStore.setCurrentEngine = function(name){
+ if (!$.jStore.Instances.length ) // If no instances exist, attempt to load one
+ return $.jStore.FindEngine();
+
+ if (!name && $.jStore.Instances.length >= 1) { // If no name is specified, use the first engine
+ $.jStore.delegate.trigger('jStore-ready', $.jStore.Instances[0]);
+ return $.jStore.CurrentEngine = $.jStore.Instances[0];
+ }
+
+ if (name && $.jStore.Instances[name]) { // If a name is specified and exists, use it
+ $.jStore.delegate.trigger('jStore-ready', $.jStore.Instances[name]);
+ return $.jStore.CurrentEngine = $.jStore.Instances[name];
+ }
+
+ throw 'JSTORE_JRI_NO_MATCH';
+ }
+
+ // Test all possible engines for straightforward useability
+ $.jStore.FindEngine = function(){
+ $.each($.jStore.EngineOrder, function(k){
+ if ($.jStore.Availability[this]()){ // Find the first, easiest option and use it.
+ $.jStore.use(this, $.jStore.defaults.project, 'default');
+ return false;
+ }
+ })
+ }
+
+ // Provide a simple interface for storing/getting values
+ $.jStore.store = function(key, value){
+ if (!$.jStore.CurrentEngine) return false;
+
+ if ( !value ) // Executing a get command
+ return $.jStore.CurrentEngine.get(key);
+ // Executing a set command
+ return $.jStore.CurrentEngine.set(key, value);
+ }
+ // Provide a simple interface for storing/getting values
+ $.jStore.remove = function(key){
+ if (!$.jStore.CurrentEngine) return false;
+
+ return $.jStore.CurrentEngine.rem(key);
+ }
+
+ // Provide a chainable interface for storing values/getting a value at the end of a chain
+ $.fn.store = function(key, value){
+ if (!$.jStore.CurrentEngine) return this;
+
+ var result = $.jStore.store(key, value);
+
+ return !value ? result : this;
+ }
+
+ // Provide a chainable interface for removing values
+ $.fn.removeStore = function(key){
+ $.jStore.remove(key);
+
+ return this;
+ }
+
+ // Provide a way for users to call for auto-loading
+ $.jStore.load = function(){
+ if ($.jStore.defaults.engine)
+ return $.jStore.use($.jStore.defaults.engine, $.jStore.defaults.project, 'default');
+
+ // Attempt to find a valid engine, and catch any exceptions if we can't
+ try {
+ $.jStore.FindEngine();
+ } catch (e) {}
+ }
+
+})(jQuery);
+/**
+ * jStore Engine Core
+ * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
+ */
+(function($){
+
+ this.StorageEngine = Class.extend({
+ init: function(project, name){
+ // Configure the project name
+ this.project = project;
+ // The JRI name given by the manager
+ this.jri = name;
+ // Cache the data so we can work synchronously
+ this.data = {};
+ // The maximum limit of the storage engine
+ this.limit = -1;
+ // Third party script includes
+ this.includes = [];
+ // Create an event delegate for users to subscribe to event triggers
+ this.delegate = new jStoreDelegate(this)
+ .bind('engine-ready', function(){
+ this.isReady = true;
+ })
+ .bind('engine-included', function(){
+ this.hasIncluded = true;
+ });
+ // If enabled, the manager will check availability, then run include(), then check again
+ this.autoload = false; // This should be changed by the engines, if they have required includes
+ // When set, we're ready to transact data
+ this.isReady = false;
+ // When the includer is finished, it will set this to true
+ this.hasIncluded = false;
+ },
+ // Performs all necessary script includes
+ include: function(){
+ var self = this,
+ total = this.includes.length,
+ count = 0;
+
+ $.each(this.includes, function(){
+ $.ajax({type: 'get', url: this, dataType: 'script', cache: true,
+ success: function(){
+ count++;
+ if (count == total) self.delegate.trigger('engine-included');
+ }
+ })
+ });
+ },
+ // This should be overloaded with an actual functionality presence check
+ isAvailable: function(){
+ return false;
+ },
+ /** Event Subscription Shortcuts **/
+ ready: function(callback){
+ if (this.isReady) callback.apply(this);
+ else this.delegate.bind('engine-ready', callback);
+ return this;
+ },
+ included: function(callback){
+ if (this.hasIncluded) callback.apply(this);
+ else this.delegate.bind('engine-included', callback);
+ return this;
+ },
+ /** Cache Data Access **/
+ get: function(key){
+ return this.data[key] || null;
+ },
+ set: function(key, value){
+ this.data[key] = value;
+ return value;
+ },
+ rem: function(key){
+ var beforeDelete = this.data[key];
+ this.data[key] = null;
+ return beforeDelete;
+ }
+ });
+
+})(jQuery);
+/*!
+ * jStore DOM Storage Engine
+ * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
+ */
+(function($){
+
+ // Set up a static test function for this instance
+ var sessionAvailability = $.jStore.Availability.session = function(){
+ return !!window.sessionStorage;
+ },
+ localAvailability = $.jStore.Availability.local = function(){
+ return !!(window.localStorage || window.globalStorage);
+ };
+
+ this.jStoreDom = StorageEngine.extend({
+ init: function(project, name){
+ // Call the parental init object
+ this._super(project, name);
+
+ // The type of storage engine
+ this.type = 'DOM';
+
+ // Set the Database limit
+ this.limit = 5 * 1024 * 1024;
+ },
+ connect: function(){
+ // Fire our delegate to indicate we're ready for data transactions
+ this.delegate.trigger('engine-ready');
+ },
+ get: function(key){
+ var out = this.db.getItem(key);
+ // Gecko's getItem returns {value: 'the value'}, WebKit returns 'the value'
+ return out && out.value ? out.value : out
+ },
+ set: function(key, value){
+ this.db.setItem(key,value);
+ return value;
+ },
+ rem: function(key){
+ var out = this.get(key);
+ this.db.removeItem(key);
+ return out
+ }
+ })
+
+ this.jStoreLocal = jStoreDom.extend({
+ connect: function(){
+ // Gecko uses a non-standard globalStorage[ www.example.com ] DOM access object for persistant storage.
+ this.db = !window.globalStorage ? window.localStorage : window.globalStorage[location.hostname];
+ this._super();
+ },
+ isAvailable: localAvailability
+ })
+
+ this.jStoreSession = jStoreDom.extend({
+ connect: function(){
+ this.db = sessionStorage;
+ this._super();
+ },
+ isAvailable: sessionAvailability
+ })
+
+ $.jStore.Engines.local = jStoreLocal;
+ $.jStore.Engines.session = jStoreSession;
+
+ // Store the ordering preference
+ $.jStore.EngineOrder[ 1 ] = 'local';
+
+})(jQuery);
+/*!
+ * jStore Flash Storage Engine
+ * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
+ * jStore.swf Copyright (c) 2008 Daniel Bulli (http://www.nuff-respec.com)
+ */
+(function($){
+
+ // Set up a static test function for this instance
+ var avilability = $.jStore.Availability.flash = function(){
+ return !!($.jStore.hasFlash('8.0.0'));
+ }
+
+ this.jStoreFlash = StorageEngine.extend({
+ init: function(project, name){
+ // Call the parental init object
+ this._super(project, name);
+
+ // The type of storage engine
+ this.type = 'Flash';
+
+ // Bind our flashReady function to the jStore Delegate
+ var self = this;
+ $.jStore.flashReady(function(){ self.flashReady() });
+ },
+ connect: function(){
+ var name = 'jstore-flash-embed-' + this.project;
+
+ // To make Flash Storage work on IE, we have to load up an iFrame
+ // which contains an HTML page that embeds the object using an
+ // object tag wrapping an embed tag. Of course, this is unnecessary for
+ // all browsers except for IE, which, to my knowledge, is the only browser
+ // in existance where you need to complicate your code to fix bugs. Goddamnit. :(
+ $(document.body)
+ .append('<iframe style="height:1px;width:1px;position:absolute;left:0;top:0;margin-left:-100px;" ' +
+ 'id="jStoreFlashFrame" src="' +$.jStore.defaults.flash + '"></iframe>');
+ },
+ flashReady: function(e){
+ var iFrame = $('#jStoreFlashFrame')[0];
+
+ // IE
+ if (iFrame.Document && $.isFunction(iFrame.Document['jStoreFlash'].f_get_cookie)) this.db = iFrame.Document['jStoreFlash'];
+ // Safari && Firefox
+ else if (iFrame.contentWindow && iFrame.contentWindow.document){
+ var doc = iFrame.contentWindow.document;
+ // Safari
+ if ($.isFunction($('object', $(doc))[0].f_get_cookie)) this.db = $('object', $(doc))[0];
+ // Firefox
+ else if ($.isFunction($('embed', $(doc))[0].f_get_cookie)) this.db = $('embed', $(doc))[0];
+ }
+
+ // We're ready to process data
+ if (this.db) this.delegate.trigger('engine-ready');
+ },
+ isAvailable: avilability,
+ get: function(key){
+ var out = this.db.f_get_cookie(key);
+ return out == 'null' ? null : out;
+ },
+ set: function(key, value){
+ this.db.f_set_cookie(key, value);
+ return value;
+ },
+ rem: function(key){
+ var beforeDelete = this.get(key);
+ this.db.f_delete_cookie(key);
+ return beforeDelete;
+ }
+ })
+
+ $.jStore.Engines.flash = jStoreFlash;
+
+ // Store the ordering preference
+ $.jStore.EngineOrder[ 2 ] = 'flash';
+
+ /**
+ * Flash Detection functions copied from the jQuery Flash Plugin
+ * Copyright (c) 2006 Luke Lutman (http://jquery.lukelutman.com/plugins/flash)
+ * Dual licensed under the MIT and GPL licenses.
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.opensource.org/licenses/gpl-license.php
+ */
+ $.jStore.hasFlash = function(version){
+ var pv = $.jStore.flashVersion().match(/\d+/g),
+ rv = version.match(/\d+/g);
+
+ for(var i = 0; i < 3; i++) {
+ pv[i] = parseInt(pv[i] || 0);
+ rv[i] = parseInt(rv[i] || 0);
+ // player is less than required
+ if(pv[i] < rv[i]) return false;
+ // player is greater than required
+ if(pv[i] > rv[i]) return true;
+ }
+ // major version, minor version and revision match exactly
+ return true;
+ }
+
+ $.jStore.flashVersion = function(){
+ // ie
+ try {
+ try {
+ // avoid fp6 minor version lookup issues
+ // see: http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet…
+ var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
+ try { axo.AllowScriptAccess = 'always'; }
+ catch(e) { return '6,0,0'; }
+ } catch(e) {}
+ return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
+ // other browsers
+ } catch(e) {
+ try {
+ if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){
+ return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
+ }
+ } catch(e) {}
+ }
+ return '0,0,0';
+ }
+
+})(jQuery);
+
+// Callback fired when ExternalInterface is established
+function flash_ready(){
+ $.jStore.delegate.trigger('flash-ready');
+}
+/*!
+ * jStore Google Gears Storage Engine
+ * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
+ */
+(function($){
+
+ // Set up a static test function for this instance
+ var avilability = $.jStore.Availability.gears = function(){
+ return !!(window.google && window.google.gears)
+ }
+
+ this.jStoreGears = StorageEngine.extend({
+ init: function(project, name){
+ // Call the parental init object
+ this._super(project, name);
+
+ // The type of storage engine
+ this.type = 'Google Gears';
+
+ // Add required third-party scripts
+ this.includes.push('http://code.google.com/apis/gears/gears_init.js');
+
+ // Allow Autoloading on fail
+ this.autoload = true;
+ },
+ connect: function(){
+ // Create our database connection
+ var db = this.db = google.gears.factory.create('beta.database');
+ db.open( 'jstore-' + this.project );
+ db.execute( 'CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)' );
+
+ // Cache the data from the table
+ this.updateCache();
+ },
+ updateCache: function(){
+ // Read the database into our cache object
+ var result = this.db.execute( 'SELECT k,v FROM jstore' );
+ while (result.isValidRow()){
+ this.data[result.field(0)] = result.field(1);
+ result.next();
+ } result.close();
+
+ // Fire our delegate to indicate we're ready for data transactions
+ this.delegate.trigger('engine-ready');
+ },
+ isAvailable: avilability,
+ set: function(key, value){
+ // Update the database
+ var db = this.db;
+ db.execute( 'BEGIN' );
+ db.execute( 'INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)', [key,value] );
+ db.execute( 'COMMIT' );
+ return this._super(key, value);
+ },
+ rem: function(key){
+ // Update the database
+ var db = this.db;
+ db.execute( 'BEGIN' );
+ db.execute( 'DELETE FROM jstore WHERE k = ?', [key] );
+ db.execute( 'COMMIT' );
+ return this._super(key);
+ }
+ })
+
+ $.jStore.Engines.gears = jStoreGears;
+
+ // Store the ordering preference
+ $.jStore.EngineOrder[ 3 ] = 'gears';
+
+})(jQuery);
+/*!
+ * jStore HTML5 Specification Storage Engine
+ * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
+ */
+(function($){
+
+ // Set up a static test function for this instance
+ var avilability = $.jStore.Availability.html5 = function(){
+ return !!window.openDatabase
+ }
+
+ this.jStoreHtml5 = StorageEngine.extend({
+ init: function(project, name){
+ // Call the parental init object
+ this._super(project, name);
+
+ // The type of storage engine
+ this.type = 'HTML5';
+
+ // Set the Database limit
+ this.limit = 1024 * 200;
+ },
+ connect: function(){
+ // Create our database connection
+ var db = this.db = openDatabase('jstore-' + this.project, '1.0', this.project, this.limit);
+ if (!db) throw 'JSTORE_ENGINE_HTML5_NODB';
+ db.transaction(function(db){
+ db.executeSql( 'CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)' );
+ });
+
+ // Cache the data from the table
+ this.updateCache();
+ },
+ updateCache: function(){
+ var self = this;
+ // Read the database into our cache object
+ this.db.transaction(function(db){
+ db.executeSql( 'SELECT k,v FROM jstore', [], function(db, result){
+ var rows = result.rows, i = 0, row;
+ for (; i < rows.length; ++i){
+ row = rows.item(i);
+ self.data[row.k] = row.v;
+ }
+
+ // Fire our delegate to indicate we're ready for data transactions
+ self.delegate.trigger('engine-ready');
+ });
+ });
+ },
+ isAvailable: avilability,
+ set: function(key, value){
+ // Update the database
+ this.db.transaction(function(db){
+ db.executeSql( 'INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)', [key,value]);
+ });
+ return this._super(key, value);
+ },
+ rem: function(key){
+ // Update the database
+ this.db.transaction(function(db){
+ db.executeSql( 'DELETE FROM jstore WHERE k = ?', [key] )
+ })
+ return this._super(key);
+ }
+ })
+
+ $.jStore.Engines.html5 = jStoreHtml5;
+
+ // Store the ordering preference
+ $.jStore.EngineOrder[ 0 ] = 'html5';
+
+})(jQuery);
+/*!*
+ * jStore IE Storage Engine
+ * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
+ */
+(function($){
+
+ // Set up a static test function for this instance
+ var avilability = $.jStore.Availability.ie = function(){
+ return !!window.ActiveXObject;
+ }
+
+ this.jStoreIE = StorageEngine.extend({
+ init: function(project, name){
+ // Call the parental init object
+ this._super(project, name);
+
+ // The type of storage engine
+ this.type = 'IE';
+
+ // Allow Autoloading on fail
+ this.limit = 64 * 1024;
+ },
+ connect: function(){
+ // Create a hidden div to store attributes in
+ this.db = $('<div style="display:none;behavior:url(\'#default#userData\')" id="jstore-' + this.project + '"></div>')
+ .appendTo(document.body).get(0);
+ // Fire our delegate to indicate we're ready for data transactions
+ this.delegate.trigger('engine-ready');
+ },
+ isAvailable: avilability,
+ get: function(key){
+ this.db.load(this.project);
+ return this.db.getAttribute(key);
+ },
+ set: function(key, value){
+ this.db.setAttribute(key, value);
+ this.db.save(this.project);
+ return value;
+ },
+ rem: function(key){
+ var beforeDelete = this.get(key);
+ this.db.removeAttribute(key);
+ this.db.save(this.project);
+ return beforeDelete;
+ }
+ })
+
+ $.jStore.Engines.ie = jStoreIE;
+
+ // Store the ordering preference
+ $.jStore.EngineOrder[ 4 ] = 'ie';
+
+})(jQuery);
\ No newline at end of file
diff -r 7df41ad788de -r 55c0eb35fad7 static/scripts/packed/jquery.jstore-all.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/packed/jquery.jstore-all.js Thu Aug 13 13:16:58 2009 -0400
@@ -0,0 +1,41 @@
+/*
+ * jStore - Persistent Client-Side Storage
+ *
+ * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
+ *
+ * Dual licensed under:
+ * MIT: http://www.opensource.org/licenses/mit-license.php
+ * GPLv3: http://www.opensource.org/licenses/gpl-3.0.html
+ */
+(function(){var a=false,b=/xyz/.test(function(){xyz})?/\b_super\b/:/.*/;this.Class=function(){};Class.extend=function(g){var f=this.prototype;a=true;var e=new this();a=false;for(var d in g){e[d]=typeof g[d]=="function"&&typeof f[d]=="function"&&b.test(g[d])?(function(h,i){return function(){var k=this._super;this._super=f[h];var j=i.apply(this,arguments);this._super=k;return j}})(d,g[d]):g[d]}function c(){if(!a&&this.init){this.init.apply(this,arguments)}}c.prototype=e;c.constructor=c;c.extend=arguments.callee;return c}})();
+/*
+ * jStore Delegate Framework
+ * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
+ */
+(function(a){this.jStoreDelegate=Class.extend({init:function(b){this.parent=b;this.callbacks={}},bind:function(b,c){if(!a.isFunction(c)){return this}if(!this.callbacks[b]){this.callbacks[b]=[]}this.callbacks[b].push(c);return this},trigger:function(){var d=this.parent,c=[].slice.call(arguments),e=c.shift(),b=this.callbacks[e];if(!b){return false}a.each(b,function(){this.apply(d,c)});return this}})})(jQuery);(function(a){a.jStore={};a.extend(a.jStore,{EngineOrder:[],Availability:{},Engines:{},Instances:{},CurrentEngine:null,defaults:{project:null,engine:null,autoload:true,flash:"jStore.Flash.html"},isReady:false,isFlashReady:false,delegate:new jStoreDelegate(a.jStore).bind("jStore-ready",function(b){a.jStore.isReady=true;if(a.jStore.defaults.autoload){b.connect()}}).bind("flash-ready",function(){a.jStore.isFlashReady=true})});a.jStore.ready=function(b){if(a.jStore.isReady){b.apply(a.jStore,[a.jStore.CurrentEngine])}else{a.jStore.delegate.bind("jStore-ready",b)}};a.jStore.fail
=function(b){a.jStore.delegate.bind("jStore-failure",b)};a.jStore.flashReady=function(b){if(a.jStore.isFlashReady){b.apply(a.jStore,[a.jStore.CurrentEngine])}else{a.jStore.delegate.bind("flash-ready",b)}};a.jStore.use=function(d,g,c){g=g||a.jStore.defaults.project||location.hostname.replace(/\./g,"-")||"unknown";var f=a.jStore.Engines[d.toLowerCase()]||null,b=(c?c+".":"")+g+"."+d;if(!f){throw"JSTORE_ENGINE_UNDEFINED"}f=new f(g,b);if(a.jStore.Instances[b]){throw"JSTORE_JRI_CONFLICT"}if(f.isAvailable()){a.jStore.Instances[b]=f;if(!a.jStore.CurrentEngine){a.jStore.CurrentEngine=f}a.jStore.delegate.trigger("jStore-ready",f)}else{if(!f.autoload){throw"JSTORE_ENGINE_UNAVILABLE"}else{f.included(function(){if(this.isAvailable()){a.jStore.Instances[b]=this;if(!a.jStore.CurrentEngine){a.jStore.CurrentEngine=this}a.jStore.delegate.trigger("jStore-ready",this)}else{a.jStore.delegate.trigger("jStore-failure",this)}}).include()}}};a.jStore.setCurrentEngine=function(b){if(!a.jStore.Instanc
es.length){return a.jStore.FindEngine()}if(!b&&a.jStore.Instances.length>=1){a.jStore.delegate.trigger("jStore-ready",a.jStore.Instances[0]);return a.jStore.CurrentEngine=a.jStore.Instances[0]}if(b&&a.jStore.Instances[b]){a.jStore.delegate.trigger("jStore-ready",a.jStore.Instances[b]);return a.jStore.CurrentEngine=a.jStore.Instances[b]}throw"JSTORE_JRI_NO_MATCH"};a.jStore.FindEngine=function(){a.each(a.jStore.EngineOrder,function(b){if(a.jStore.Availability[this]()){a.jStore.use(this,a.jStore.defaults.project,"default");return false}})};a.jStore.store=function(b,c){if(!a.jStore.CurrentEngine){return false}if(!c){return a.jStore.CurrentEngine.get(b)}return a.jStore.CurrentEngine.set(b,c)};a.jStore.remove=function(b){if(!a.jStore.CurrentEngine){return false}return a.jStore.CurrentEngine.rem(b)};a.fn.store=function(c,d){if(!a.jStore.CurrentEngine){return this}var b=a.jStore.store(c,d);return !d?b:this};a.fn.removeStore=function(b){a.jStore.remove(b);return this};a.jStore.load=f
unction(){if(a.jStore.defaults.engine){return a.jStore.use(a.jStore.defaults.engine,a.jStore.defaults.project,"default")}try{a.jStore.FindEngine()}catch(b){}}})(jQuery);(function(a){this.StorageEngine=Class.extend({init:function(c,b){this.project=c;this.jri=b;this.data={};this.limit=-1;this.includes=[];this.delegate=new jStoreDelegate(this).bind("engine-ready",function(){this.isReady=true}).bind("engine-included",function(){this.hasIncluded=true});this.autoload=false;this.isReady=false;this.hasIncluded=false},include:function(){var b=this,d=this.includes.length,c=0;a.each(this.includes,function(){a.ajax({type:"get",url:this,dataType:"script",cache:true,success:function(){c++;if(c==d){b.delegate.trigger("engine-included")}}})})},isAvailable:function(){return false},ready:function(b){if(this.isReady){b.apply(this)}else{this.delegate.bind("engine-ready",b)}return this},included:function(b){if(this.hasIncluded){b.apply(this)}else{this.delegate.bind("engine-included",b)}return th
is},get:function(b){return this.data[b]||null},set:function(b,c){this.data[b]=c;return c},rem:function(b){var c=this.data[b];this.data[b]=null;return c}})})(jQuery);
+/*
+ * jStore DOM Storage Engine
+ * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
+ */
+(function(c){var b=c.jStore.Availability.session=function(){return !!window.sessionStorage},a=c.jStore.Availability.local=function(){return !!(window.localStorage||window.globalStorage)};this.jStoreDom=StorageEngine.extend({init:function(e,d){this._super(e,d);this.type="DOM";this.limit=5*1024*1024},connect:function(){this.delegate.trigger("engine-ready")},get:function(e){var d=this.db.getItem(e);return d&&d.value?d.value:d},set:function(d,e){this.db.setItem(d,e);return e},rem:function(e){var d=this.get(e);this.db.removeItem(e);return d}});this.jStoreLocal=jStoreDom.extend({connect:function(){this.db=!window.globalStorage?window.localStorage:window.globalStorage[location.hostname];this._super()},isAvailable:a});this.jStoreSession=jStoreDom.extend({connect:function(){this.db=sessionStorage;this._super()},isAvailable:b});c.jStore.Engines.local=jStoreLocal;c.jStore.Engines.session=jStoreSession;c.jStore.EngineOrder[1]="local"})(jQuery);
+/*
+ * jStore Flash Storage Engine
+ * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
+ * jStore.swf Copyright (c) 2008 Daniel Bulli (http://www.nuff-respec.com)
+ */
+(function(b){var a=b.jStore.Availability.flash=function(){return !!(b.jStore.hasFlash("8.0.0"))};this.jStoreFlash=StorageEngine.extend({init:function(e,d){this._super(e,d);this.type="Flash";var c=this;b.jStore.flashReady(function(){c.flashReady()})},connect:function(){var c="jstore-flash-embed-"+this.project;b(document.body).append('<iframe style="height:1px;width:1px;position:absolute;left:0;top:0;margin-left:-100px;" id="jStoreFlashFrame" src="'+b.jStore.defaults.flash+'"></iframe>')},flashReady:function(f){var c=b("#jStoreFlashFrame")[0];if(c.Document&&b.isFunction(c.Document.jStoreFlash.f_get_cookie)){this.db=c.Document.jStoreFlash}else{if(c.contentWindow&&c.contentWindow.document){var d=c.contentWindow.document;if(b.isFunction(b("object",b(d))[0].f_get_cookie)){this.db=b("object",b(d))[0]}else{if(b.isFunction(b("embed",b(d))[0].f_get_cookie)){this.db=b("embed",b(d))[0]}}}}if(this.db){this.delegate.trigger("engine-ready")}},isAvailable:a,get:function(d){var c=this.db.f_g
et_cookie(d);return c=="null"?null:c},set:function(c,d){this.db.f_set_cookie(c,d);return d},rem:function(c){var d=this.get(c);this.db.f_delete_cookie(c);return d}});b.jStore.Engines.flash=jStoreFlash;b.jStore.EngineOrder[2]="flash";b.jStore.hasFlash=function(c){var e=b.jStore.flashVersion().match(/\d+/g),f=c.match(/\d+/g);for(var d=0;d<3;d++){e[d]=parseInt(e[d]||0);f[d]=parseInt(f[d]||0);if(e[d]<f[d]){return false}if(e[d]>f[d]){return true}}return true};b.jStore.flashVersion=function(){try{try{var c=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");try{c.AllowScriptAccess="always"}catch(d){return"6,0,0"}}catch(d){}return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version").replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}catch(d){try{if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){return(navigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}}catch(d){}}r
eturn"0,0,0"}})(jQuery);function flash_ready(){$.jStore.delegate.trigger("flash-ready")}
+/*
+ * jStore Google Gears Storage Engine
+ * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
+ */
+(function(b){var a=b.jStore.Availability.gears=function(){return !!(window.google&&window.google.gears)};this.jStoreGears=StorageEngine.extend({init:function(d,c){this._super(d,c);this.type="Google Gears";this.includes.push("http://code.google.com/apis/gears/gears_init.js");this.autoload=true},connect:function(){var c=this.db=google.gears.factory.create("beta.database");c.open("jstore-"+this.project);c.execute("CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)");this.updateCache()},updateCache:function(){var c=this.db.execute("SELECT k,v FROM jstore");while(c.isValidRow()){this.data[c.field(0)]=c.field(1);c.next()}c.close();this.delegate.trigger("engine-ready")},isAvailable:a,set:function(d,e){var c=this.db;c.execute("BEGIN");c.execute("INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)",[d,e]);c.execute("COMMIT");return this._super(d,e)},rem:function(d){var c=this.db;c.execute("BEGIN");c.execute("DELETE FROM jstore WHERE k = ?",[d]);c.ex
ecute("COMMIT");return this._super(d)}});b.jStore.Engines.gears=jStoreGears;b.jStore.EngineOrder[3]="gears"})(jQuery);
+/*
+ * jStore HTML5 Specification Storage Engine
+ * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
+ */
+(function(b){var a=b.jStore.Availability.html5=function(){return !!window.openDatabase};this.jStoreHtml5=StorageEngine.extend({init:function(d,c){this._super(d,c);this.type="HTML5";this.limit=1024*200},connect:function(){var c=this.db=openDatabase("jstore-"+this.project,"1.0",this.project,this.limit);if(!c){throw"JSTORE_ENGINE_HTML5_NODB"}c.transaction(function(d){d.executeSql("CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)")});this.updateCache()},updateCache:function(){var c=this;this.db.transaction(function(d){d.executeSql("SELECT k,v FROM jstore",[],function(f,e){var h=e.rows,g=0,j;for(;g<h.length;++g){j=h.item(g);c.data[j.k]=j.v}c.delegate.trigger("engine-ready")})})},isAvailable:a,set:function(c,d){this.db.transaction(function(e){e.executeSql("INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)",[c,d])});return this._super(c,d)},rem:function(c){this.db.transaction(function(d){d.executeSql("DELETE FROM jstore WHERE k = ?",[c])});ret
urn this._super(c)}});b.jStore.Engines.html5=jStoreHtml5;b.jStore.EngineOrder[0]="html5"})(jQuery);
+/**
+ * jStore IE Storage Engine
+ * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
+ */
+(function(b){var a=b.jStore.Availability.ie=function(){return !!window.ActiveXObject};this.jStoreIE=StorageEngine.extend({init:function(d,c){this._super(d,c);this.type="IE";this.limit=64*1024},connect:function(){this.db=b('<div style="display:none;behavior:url(\'#default#userData\')" id="jstore-'+this.project+'"></div>').appendTo(document.body).get(0);this.delegate.trigger("engine-ready")},isAvailable:a,get:function(c){this.db.load(this.project);return this.db.getAttribute(c)},set:function(c,d){this.db.setAttribute(c,d);this.db.save(this.project);return d},rem:function(c){var d=this.get(c);this.db.removeAttribute(c);this.db.save(this.project);return d}});b.jStore.Engines.ie=jStoreIE;b.jStore.EngineOrder[4]="ie"})(jQuery);
\ No newline at end of file
diff -r 7df41ad788de -r 55c0eb35fad7 static/scripts/packed/json2.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/packed/json2.js Thu Aug 13 13:16:58 2009 -0400
@@ -0,0 +1,1 @@
+var JSON=JSON||{};(function(){function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0)
.toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||"null"}v=partial.length===0?"[]":gap?"[\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"]":"["+partial.join(",")+"]";gap=mind;return v}if(rep&&typeof rep==="object"){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==="string"){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(
k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}v=partial.length===0?"{}":gap?"{\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"}":"{"+partial.join(",")+"}";gap=mind;return v}}if(typeof JSON.stringify!=="function"){JSON.stringify=function(value,replacer,space){var i;gap="";indent="";if(typeof space==="number"){for(i=0;i<space;i+=1){indent+=" "}}else{if(typeof space==="string"){indent=space}}rep=replacer;if(replacer&&typeof replacer!=="function"&&(typeof replacer!=="object"||typeof replacer.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":value})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("000
0"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}());
\ No newline at end of file
diff -r 7df41ad788de -r 55c0eb35fad7 templates/root/history.mako
--- a/templates/root/history.mako Tue Aug 11 15:46:23 2009 -0400
+++ b/templates/root/history.mako Thu Aug 13 13:16:58 2009 -0400
@@ -15,219 +15,242 @@
<meta http-equiv="Pragma" content="no-cache">
${h.css( "base", "history" )}
-${h.js( "jquery", "jquery.cookie", "cookie_set" )}
-
+${h.js( "jquery", "json2", "jquery.jstore-all" )}
+
<script type="text/javascript">
- $( document ).ready( function() {
- initShowHide();
- setupHistoryItem( $("div.historyItemWrapper") );
- // Collapse all
- $("#top-links").append( "| " ).append( $("<a href='#'>${_('collapse all')}</a>").click( function() {
- $( "div.historyItemBody:visible" ).each( function() {
- if ( $.browser.mozilla )
- {
- $(this).find( "pre.peek" ).css( "overflow", "hidden" );
+$(function() {
+ // Load jStore for local storage
+ $.extend(jQuery.jStore.defaults, { project: 'galaxy', flash: '/static/jStore.Flash.html' })
+ $.jStore.load(); // Auto-select best storage
+
+ $.jStore.ready(function(engine) {
+ engine.ready(function() {
+ // Init stuff that requires the local storage to be running
+ initShowHide();
+ setupHistoryItem( $("div.historyItemWrapper") );
+ });
+ });
+
+ // Generate 'collapse all' link
+ $("#top-links").append( "| " ).append( $("<a href='#'>${_('collapse all')}</a>").click( function() {
+ $( "div.historyItemBody:visible" ).each( function() {
+ if ( $.browser.mozilla ) {
+ $(this).find( "pre.peek" ).css( "overflow", "hidden" );
+ }
+ $(this).slideUp( "fast" );
+ });
+ $.jStore.remove("history_expand_state");
+ }));
+
+ $("#history-rename").click( function() {
+ var old_name = $("#history-name").text()
+ var t = $("<input type='text' value='" + old_name + "'></input>" );
+ t.blur( function() {
+ $(this).remove();
+ $("#history-name").show();
+ });
+ t.keyup( function( e ) {
+ if ( e.keyCode == 27 ) {
+ // Escape key
+ $(this).trigger( "blur" );
+ } else if ( e.keyCode == 13 ) {
+ // Enter key
+ new_value = this.value;
+ $(this).trigger( "blur" );
+ $.ajax({
+ url: "${h.url_for( controller='history', action='rename_async', id=history.id )}",
+ data: { "_": true, new_name: new_value },
+ error: function() { alert( "Rename failed" ) },
+ success: function() {
+ $("#history-name").text( new_value );
+ }
+ });
+ }
+ });
+ $("#history-name").hide();
+ $("#history-name-area").append( t );
+ t.focus();
+ return false;
+ });
+ // Updater
+ updater({
+ %for i, data in enumerate( reversed( datasets ) ):
+ %if data.visible and data.state not in [ "deleted", "empty", "error", "ok" ]:
+ %if i > 0:
+ ,
+ %endif
+ "${data.id}": "${data.state}"
+ %endif
+ %endfor
+ });
+});
+// Functionized so AJAX'd datasets can call them
+// Get shown/hidden state from cookie
+function initShowHide() {
+
+ // Load saved state and show as neccesary
+ try {
+ var stored = $.jStore.store("history_expand_state");
+ if (stored) {
+ var st = JSON.parse(stored);
+ for (var id in st) {
+ $("#" + id + " div.historyItemBody" ).show();
+ }
+ }
+ } catch(err) {
+ // Something was wrong with values in storage, so clear storage
+ $.jStore.remove("history_expand_state");
+ }
+
+ // If Mozilla, hide scrollbars in hidden items since they cause animation bugs
+ if ( $.browser.mozilla ) {
+ $( "div.historyItemBody" ).each( function() {
+ if ( ! $(this).is( ":visible" ) ) $(this).find( "pre.peek" ).css( "overflow", "hidden" );
+ })
+ }
+}
+// Add show/hide link and delete link to a history item
+function setupHistoryItem( query ) {
+ query.each( function() {
+ var id = this.id;
+ var body = $(this).children( "div.historyItemBody" );
+ var peek = body.find( "pre.peek" )
+ $(this).children( ".historyItemTitleBar" ).find( ".historyItemTitle" ).wrap( "<a href='#'></a>" ).click( function() {
+ if ( body.is(":visible") ) {
+ // Hiding stuff here
+ if ( $.browser.mozilla ) { peek.css( "overflow", "hidden" ) }
+ body.slideUp( "fast" );
+
+ // Save setting
+ var stored = $.jStore.store("history_expand_state")
+ var prefs = stored ? JSON.parse(stored) : null
+ if (prefs) {
+ delete prefs[id];
+ $.jStore.store("history_expand_state", JSON.stringify(prefs));
}
- $(this).slideUp( "fast" );
- })
- var state = new CookieSet( "galaxy.history.expand_state" );
- state.removeAll().save();
- return false;
- }));
- $("#history-rename").click( function() {
- var old_name = $("#history-name").text()
- var t = $("<input type='text' value='" + old_name + "'></input>" );
- t.blur( function() {
- $(this).remove();
- $("#history-name").show();
- });
- t.keyup( function( e ) {
- if ( e.keyCode == 27 ) {
- // Escape key
- $(this).trigger( "blur" );
- } else if ( e.keyCode == 13 ) {
- // Enter key
- new_value = this.value;
- $(this).trigger( "blur" );
- $.ajax({
- url: "${h.url_for( controller='history', action='rename_async', id=history.id )}",
- data: { "_": true, new_name: new_value },
- error: function() { alert( "Rename failed" ) },
- success: function() {
- $("#history-name").text( new_value );
- }
- });
- }
- });
- $("#history-name").hide();
- $("#history-name-area").append( t );
- t.focus();
- return false;
- });
- // Updater
- updater({
- %for i, data in enumerate( reversed( datasets ) ):
- %if data.visible and data.state not in [ "deleted", "empty", "error", "ok" ]:
- %if i > 0:
- ,
- %endif
- "${data.id}": "${data.state}"
- %endif
- %endfor
+ }
+ else {
+ // Showing stuff here
+ body.slideDown( "fast", function() {
+ if ( $.browser.mozilla ) { peek.css( "overflow", "auto" ); }
+ });
+
+ // Save setting
+ var stored = $.jStore.store("history_expand_state")
+ var prefs = stored ? JSON.parse(stored) : new Object;
+ prefs[id] = true;
+ $.jStore.store("history_expand_state", JSON.stringify(prefs));
+ }
+ return false;
});
- })
- //' Functionized so AJAX'd datasets can call them
- // Get shown/hidden state from cookie
- function initShowHide() {
- // $( "div.historyItemBody" ).hide();
- // Load saved state and show as neccesary
- var state = new CookieSet( "galaxy.history.expand_state" );
- for ( id in state.store ) {
- if ( id ) {
- $( "#" + id + " div.historyItemBody" ).show();
- }
- }
- // If Mozilla, hide scrollbars in hidden items since they cause animation bugs
- if ( $.browser.mozilla ) {
- $( "div.historyItemBody" ).each( function() {
- if ( ! $(this).is( ":visible" ) ) $(this).find( "pre.peek" ).css( "overflow", "hidden" );
- })
- }
- delete state;
- }
- // Add show/hide link and delete link to a history item
- function setupHistoryItem( query ) {
- query.each( function() {
- var id = this.id;
- var body = $(this).children( "div.historyItemBody" );
- var peek = body.find( "pre.peek" )
- $(this).children( ".historyItemTitleBar" ).find( ".historyItemTitle" ).wrap( "<a href='#'></a>" ).click( function() {
- if ( body.is(":visible") ) {
- if ( $.browser.mozilla ) { peek.css( "overflow", "hidden" ) }
- body.slideUp( "fast" );
- ## other instances of this could be editing the cookie, refetch
- var state = new CookieSet( "galaxy.history.expand_state" );
- state.remove( id ); state.save();
- delete state;
- }
- else {
- body.slideDown( "fast", function() {
- if ( $.browser.mozilla ) { peek.css( "overflow", "auto" ); }
- });
- var state = new CookieSet( "galaxy.history.expand_state" );
- state.add( id ); state.save();
- delete state;
- }
+ // Delete link
+ $(this).find( "div.historyItemButtons > .delete" ).each( function() {
+ var data_id = this.id.split( "-" )[1];
+ $(this).click( function() {
+ $( '#historyItem-' + data_id + "> div.historyItemTitleBar" ).addClass( "spinner" );
+ $.ajax({
+ url: "${h.url_for( action='delete_async', id='XXX' )}".replace( 'XXX', data_id ),
+ error: function() { alert( "Delete failed" ) },
+ success: function() {
+ %if show_deleted:
+ var to_update = {};
+ to_update[data_id] = "none";
+ updater( to_update );
+ %else:
+ $( "#historyItem-" + data_id ).fadeOut( "fast", function() {
+ $( "#historyItemContainer-" + data_id ).remove();
+ if ( $( "div.historyItemContainer" ).length < 1 ) {
+ $( "#emptyHistoryMessage" ).show();
+ }
+ });
+ %endif
+ }
+ });
return false;
});
- // Delete link
- $(this).find( "div.historyItemButtons > .delete" ).each( function() {
- var data_id = this.id.split( "-" )[1];
- $(this).click( function() {
- $( '#historyItem-' + data_id + "> div.historyItemTitleBar" ).addClass( "spinner" );
- $.ajax({
- url: "${h.url_for( action='delete_async', id='XXX' )}".replace( 'XXX', data_id ),
- error: function() { alert( "Delete failed" ) },
- success: function() {
- %if show_deleted:
- var to_update = {};
- to_update[data_id] = "none";
- updater( to_update );
- %else:
- $( "#historyItem-" + data_id ).fadeOut( "fast", function() {
- $( "#historyItemContainer-" + data_id ).remove();
- if ( $( "div.historyItemContainer" ).length < 1 ) {
- $( "#emptyHistoryMessage" ).show();
- }
- });
- %endif
- }
- });
- return false;
+ });
+ // Undelete link
+ $(this).find( "a.historyItemUndelete" ).each( function() {
+ var data_id = this.id.split( "-" )[1];
+ $(this).click( function() {
+ $( '#historyItem-' + data_id + " > div.historyItemTitleBar" ).addClass( "spinner" );
+ $.ajax({
+ url: "${h.url_for( controller='dataset', action='undelete_async', id='XXX' )}".replace( 'XXX', data_id ),
+ error: function() { alert( "Undelete failed" ) },
+ success: function() {
+ var to_update = {};
+ to_update[data_id] = "none";
+ updater( to_update );
+ }
});
- });
- // Undelete link
- $(this).find( "a.historyItemUndelete" ).each( function() {
- var data_id = this.id.split( "-" )[1];
- $(this).click( function() {
- $( '#historyItem-' + data_id + " > div.historyItemTitleBar" ).addClass( "spinner" );
- $.ajax({
- url: "${h.url_for( controller='dataset', action='undelete_async', id='XXX' )}".replace( 'XXX', data_id ),
- error: function() { alert( "Undelete failed" ) },
- success: function() {
- var to_update = {};
- to_update[data_id] = "none";
- updater( to_update );
- }
- });
- return false;
- });
+ return false;
});
});
- };
- // Looks for changes in dataset state using an async request. Keeps
- // calling itself (via setTimeout) until all datasets are in a terminal
- // state.
- var updater = function ( tracked_datasets ) {
- // Check if there are any items left to track
- var empty = true;
- for ( i in tracked_datasets ) {
- empty = false;
- break;
+ });
+};
+// Looks for changes in dataset state using an async request. Keeps
+// calling itself (via setTimeout) until all datasets are in a terminal
+// state.
+var updater = function ( tracked_datasets ) {
+ // Check if there are any items left to track
+ var empty = true;
+ for ( i in tracked_datasets ) {
+ empty = false;
+ break;
+ }
+ if ( ! empty ) {
+ // console.log( "Updater running in 3 seconds" );
+ setTimeout( function() { updater_callback( tracked_datasets ) }, 3000 );
+ } else {
+ // console.log( "Updater finished" );
+ }
+};
+var updater_callback = function ( tracked_datasets ) {
+ // Build request data
+ var ids = []
+ var states = []
+ var force_history_refresh = false
+ $.each( tracked_datasets, function ( id, state ) {
+ ids.push( id );
+ states.push( state );
+ });
+ // Make ajax call
+ $.ajax( {
+ type: "POST",
+ url: "${h.url_for( controller='root', action='history_item_updates' )}",
+ dataType: "json",
+ data: { ids: ids.join( "," ), states: states.join( "," ) },
+ success : function ( data ) {
+ $.each( data, function( id, val ) {
+ // Replace HTML
+ var container = $("#historyItemContainer-" + id);
+ container.html( val.html );
+ setupHistoryItem( container.children( ".historyItemWrapper" ) );
+ initShowHide();
+ // If new state was terminal, stop tracking
+ if (( val.state == "ok") || ( val.state == "error") || ( val.state == "empty") || ( val.state == "deleted" ) || ( val.state == "discarded" )) {
+ if ( val.force_history_refresh ){
+ force_history_refresh = true;
+ }
+ delete tracked_datasets[ parseInt(id) ];
+ } else {
+ tracked_datasets[ parseInt(id) ] = val.state;
+ }
+ });
+ if ( force_history_refresh ) {
+ parent.frames.galaxy_history.location.reload();
+ }
+ else {
+ // Keep going (if there are still any items to track)
+ updater( tracked_datasets );
+ }
+ },
+ error: function() {
+ // Just retry, like the old method, should try to be smarter
+ updater( tracked_datasets );
}
- if ( ! empty ) {
- // console.log( "Updater running in 3 seconds" );
- setTimeout( function() { updater_callback( tracked_datasets ) }, 3000 );
- } else {
- // console.log( "Updater finished" );
- }
- };
- var updater_callback = function ( tracked_datasets ) {
- // Build request data
- var ids = []
- var states = []
- var force_history_refresh = false
- $.each( tracked_datasets, function ( id, state ) {
- ids.push( id );
- states.push( state );
- });
- // Make ajax call
- $.ajax( {
- type: "POST",
- url: "${h.url_for( controller='root', action='history_item_updates' )}",
- dataType: "json",
- data: { ids: ids.join( "," ), states: states.join( "," ) },
- success : function ( data ) {
- $.each( data, function( id, val ) {
- // Replace HTML
- var container = $("#historyItemContainer-" + id);
- container.html( val.html );
- setupHistoryItem( container.children( ".historyItemWrapper" ) );
- initShowHide();
- // If new state was terminal, stop tracking
- if (( val.state == "ok") || ( val.state == "error") || ( val.state == "empty") || ( val.state == "deleted" ) || ( val.state == "discarded" )) {
- if ( val.force_history_refresh ){
- force_history_refresh = true;
- }
- delete tracked_datasets[ parseInt(id) ];
- } else {
- tracked_datasets[ parseInt(id) ] = val.state;
- }
- });
- if ( force_history_refresh ) {
- parent.frames.galaxy_history.location.reload();
- }
- else {
- // Keep going (if there are still any items to track)
- updater( tracked_datasets );
- }
- },
- error: function() {
- // Just retry, like the old method, should try to be smarter
- updater( tracked_datasets );
- }
- });
- };
+ });
+};
</script>
<style>
diff -r 7df41ad788de -r 55c0eb35fad7 templates/workflow/editor.mako
--- a/templates/workflow/editor.mako Tue Aug 11 15:46:23 2009 -0400
+++ b/templates/workflow/editor.mako Thu Aug 13 13:16:58 2009 -0400
@@ -31,9 +31,7 @@
<script type='text/javascript' src="${h.url_for('/static/scripts/jquery.event.hover.js')}"> </script>
<script type='text/javascript' src="${h.url_for('/static/scripts/jquery.form.js')}"> </script>
<script type='text/javascript' src="${h.url_for('/static/scripts/jquery.json.js')}"> </script>
- <script type='text/javascript' src="${h.url_for('/static/scripts/jquery.cookie.js')}"> </script>
- <script type='text/javascript' src="${h.url_for('/static/scripts/json2.js')}"> </script>
- <script type='text/javascript' src="${h.url_for('/static/scripts/json_cookie.js')}"> </script>
+ <script type='text/javascript' src="${h.url_for('/static/scripts/jquery.jstore-all.js')}"> </script>
<script type='text/javascript' src="${h.url_for('/static/scripts/galaxy.base.js')}"> </script>
<script type='text/javascript' src="${h.url_for('/static/scripts/galaxy.workflow_editor.canvas.js')}"> </script>
@@ -50,6 +48,7 @@
canvas_manager = null;
// jQuery onReady
$( function() {
+
if ( window.lt_ie_7 ) {
show_modal(
"Browser not supported",
@@ -57,11 +56,13 @@
);
return;
}
+
+ // Load jStore for local storage
+ $.extend(jQuery.jStore.defaults, { project: 'galaxy', flash: '/static/jStore.Flash.html' })
+ $.jStore.load(); // Auto-select best storage
+
// Canvas overview management
canvas_manager = new CanvasManager( $("#canvas-viewport"), $("#overview") );
-
- // Preferences cookie stored as JSON so that only one cookie is needed for multiple settings
- var prefs_cookie = new JSONCookie("galaxy.workflow");
// Initialize workflow state
reset();
@@ -128,39 +129,43 @@
canvas_manager.draw_overview();
});
- // Stores the size of the overview in a cookie when it's resized
+ $.jStore.ready(function(engine) {
+ engine.ready(function() {
+ // On load, set the size to the pref stored in local storage if it exists
+ overview_size = $.jStore.store("overview-size");
+ if (overview_size) {
+ $("#overview-border").css( {
+ width: overview_size,
+ height: overview_size
+ });
+ }
+
+ // Show viewport on load unless pref says it's off
+ $.jStore.store("overview-off") ? hide_overview() : show_overview()
+ });
+ });
+
+ // Stores the size of the overview into local storage when it's resized
$("#overview-border").bind( "dragend", function( e ) {
var op = $(this).offsetParent();
var opo = op.offset();
var new_size = Math.max( op.width() - ( e.offsetX - opo.left ),
op.height() - ( e.offsetY - opo.top ) );
- prefs_cookie.set("overview-size", new_size);
+ $.jStore.store("overview-size", new_size + "px");
});
- // On load, set the size to the pref stored in cookie if it exists
- overview_size = prefs_cookie.get("overview-size");
- if (overview_size) {
- $("#overview-border").css( {
- width: overview_size,
- height: overview_size
- });
- }
-
function show_overview() {
- prefs_cookie.unset("overview-off");
+ $.jStore.remove("overview-off");
$("#overview-border").css("right", "0px");
$("#close-viewport").css("background-position", "0px 0px");
}
function hide_overview() {
- prefs_cookie.set("overview-off", true);
+ $.jStore.store("overview-off", true);
$("#overview-border").css("right", "20000px");
$("#close-viewport").css("background-position", "12px 0px");
}
- // Show viewport on load unless pref says it's off
- prefs_cookie.get("overview-off") == true ? hide_overview() : show_overview()
-
// Lets the overview be toggled visible and invisible, adjusting the arrows accordingly
$("#close-viewport").click( function() {
$("#overview-border").css("right") == "0px" ? hide_overview() : show_overview();
1
0
24 Aug '09
details: http://www.bx.psu.edu/hg/galaxy/rev/f1f2d1de5f3e
changeset: 2576:f1f2d1de5f3e
user: Kanwei Li <kanwei(a)gmail.com>
date: Thu Aug 13 13:43:25 2009 -0400
description:
Slight tweak to resizing workflow overview
2 file(s) affected in this change:
static/scripts/galaxy.workflow_editor.canvas.js
static/scripts/packed/galaxy.workflow_editor.canvas.js
diffs (24 lines):
diff -r 55c0eb35fad7 -r f1f2d1de5f3e static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js Thu Aug 13 13:16:58 2009 -0400
+++ b/static/scripts/galaxy.workflow_editor.canvas.js Thu Aug 13 13:43:25 2009 -0400
@@ -805,9 +805,9 @@
self.draw_overview();
});
- /* Disable dragging for child elements of the panel so that resizing can
- only be done with the border panels */
- $("#overview-border>*").bind("drag", function(e) { });
+ /* Disable dragging for child element of the panel so that resizing can
+ only be done by dragging the borders */
+ $("#overview-border div").bind("drag", function(e) { });
},
update_viewport_overlay: function() {
diff -r 55c0eb35fad7 -r f1f2d1de5f3e static/scripts/packed/galaxy.workflow_editor.canvas.js
--- a/static/scripts/packed/galaxy.workflow_editor.canvas.js Thu Aug 13 13:16:58 2009 -0400
+++ b/static/scripts/packed/galaxy.workflow_editor.canvas.js Thu Aug 13 13:43:25 2009 -0400
@@ -1,1 +1,1 @@
-function Terminal(a){this.element=a;this.connectors=[]}$.extend(Terminal.prototype,{connect:function(a){this.connectors.push(a);if(this.node){this.node.changed()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.changed()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}});function OutputTerminal(a,b){Terminal.call(this,a);this.datatype=b}OutputTerminal.prototype=new Terminal();function InputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}InputTerminal.prototype=new Terminal();$.extend(InputTerminal.prototype,{can_accept:function(a){if(this.connectors.length<1){for(var b in this.datatypes){if(a.datatype=="input"){return true}if(issubtype(a.datatype,this.datatypes[b])){return true}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a)
{this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;this.handle1.connect(this);this.handle2=a;this.handle2.connect(this)},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var n=function(c){return $(c).offset().left-d.offset().left};var i=function(c){return $(c).offset().top-d.offset().top};var h=n(this.handle1.element)+5;var g=i(this.handle1.element)+5;var p=n(this.handle2.element)+5;var m=i(this.handle2.element)+5;var f=100;var k=Math.min(h,p);var a=Math.max(h,p);var j=Math.min(g,m);var t=Math.max(g,m);var b=Math.min(Math.max(Math.abs(t-j)/2,100),300);var o=k-f;var s=j-f;var q=a-k+2*f;var l=t-j+2*f;
this.canvas.style.left=o+"px";this.canvas.style.top=s+"px";this.canvas.setAttribute("width",q);this.canvas.setAttribute("height",l);h-=o;g-=s;p-=o;m-=s;var r=this.canvas.getContext("2d");r.lineCap="round";r.strokeStyle=this.outer_color;r.lineWidth=7;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke();r.strokeStyle=this.inner_color;r.lineWidth=5;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke()}});function Node(a){this.element=a;this.input_terminals={};this.output_terminals={};this.tool_errors={}}$.extend(Node.prototype,{enable_input_terminal:function(d,a,b){var c=this;$(d).each(function(){var f=this.terminal=new InputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dropstart",function(g){g.dragProxy.terminal.connectors[0].inner_color="#BBFFBB"}).bind("dropend",function(g){g.dragProxy.terminal.connectors[0].inner_color="#FFFFFF"}).bind("drop",function(g){(new Connector(g.dragTarget.terminal,g.dropTarget.terminal)).redraw()}).bind("hov
er",function(){if(f.connectors.length>0){var g=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='buttons'></div>").append($("<img src='../images/delete_icon.png' />").click(function(){$.each(f.connectors,function(i,h){h.destroy()});g.remove()}))).bind("mouseleave",function(){$(this).remove()});g.css({top:$(this).offset().top-2,left:$(this).offset().left-g.width(),"padding-right":$(this).width()}).show()}});c.input_terminals[a]=f})},enable_output_terminal:function(d,a,b){var c=this;$(d).each(function(){var g=this;var f=this.terminal=new OutputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dragstart",function(j){var i=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);i.terminal=new OutputTerminal(i);var k=new Connector();k.dragging=true;k.connect(this.terminal,i.terminal);$.dropManage({filter:function(h){return this.terminal.can_accept(f)}}).addClass("input-terminal-active");ret
urn i}).bind("drag",function(i){var h=function(){var k=$(i.dragProxy).offsetParent().offset(),j=i.offsetX-k.left,l=i.offsetY-k.top;$(i.dragProxy).css({left:j,top:l});i.dragProxy.terminal.redraw();canvas_manager.update_viewport_overlay()};h();$("#canvas-container").get(0).scroll_panel.test(i,h)}).bind("dragend",function(h){h.dragProxy.terminal.connectors[0].destroy();$(h.dragProxy).remove();$.dropManage().removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()});c.output_terminals[a]=f})},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b
.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(g){var d=this.element;if(g.type){this.type=g.type}this.name=g.name;this.form_html=g.form_html;this.tool_state=g.tool_state;this.tool_errors=g.tool_errors;if(this.tool_errors){d.addClass("tool-node-error")}else{d.removeClass("tool-node-error")}var c=this;var a=d.find(".toolFormBody");a.find("div").remove();var h=$("<div class='inputs'></div>").appendTo(a);$.each(g.data_inputs,function(j,b){var f=$("<div class='terminal input-terminal'></div>");c.enable_input_terminal(f,b.name,b.extensions);h.append($("<div class='form-row dataRow input-data-row' name='"+b.name+"'>"+b.label+"</div>").prepend(f))});if((g.data_inputs.length>0)&&(g.data_outputs.length>0)){a.append($("<div class='rule'></div>"))}$.each(g.data_outputs,function(k,b){var j=$("<div class='terminal output-terminal'></div>");c.enable_output_terminal(j,b.name,b.extension);var f=b.name;if(b.extension!="input"){f=f+" ("+b.extensio
n+")"}a.append($("<div class='form-row dataRow'>"+f+"</div>").append(j))});workflow.node_changed(this)},update_field_data:function(f){var c=$(this.element),d=this;this.tool_state=f.tool_state;this.form_html=f.form_html;this.tool_errors=f.tool_errors;if(this.tool_errors){c.addClass("tool-node-error")}else{c.removeClass("tool-node-error")}var g=c.find("div.inputs");var b=$("<div class='inputs'></div>");var a=g.find("div.input-data-row");$.each(f.data_inputs,function(k,h){var j=$("<div class='terminal input-terminal'></div>");d.enable_input_terminal(j,h.name,h.extensions);g.find("div[name="+h.name+"]").each(function(){$(this).find(".input-terminal").each(function(){var i=this.terminal.connectors[0];if(i){j[0].terminal.connectors[0]=i;i.handle2=j[0].terminal}});$(this).remove()});b.append($("<div class='form-row dataRow input-data-row' name='"+h.name+"'>"+h.label+"</div>").prepend(j))});g.replaceWith(b);g.find("div.input-data-row > .terminal").each(function(){this.terminal.destr
oy()});this.changed();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},changed:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},to_simple:function(){var a={};$.each(this.nodes,function(b,d){var f={};$.each(d.input_terminals,function(g,h){f[h.name]=null;$.each(h.connectors,function(j,k){f[h.name]={id:k.ha
ndle1.node.id,output_name:k.handle1.name}})});var c={id:d.id,type:d.type,tool_id:d.tool_id,tool_state:d.tool_state,tool_errors:d.tool_errors,input_connections:f,position:$(d.element).position()};a[d.id]=c});return{steps:a}},from_simple:function(a){wf=this;var b=0;wf.name=a.name;$.each(a.steps,function(f,d){var c=prebuild_node("tool",d.name,d.tool_id);c.init_field_data(d);if(d.position){c.element.css({top:d.position.top,left:d.position.left})}c.id=d.id;wf.nodes[c.id]=c;b=Math.max(b,parseInt(f))});wf.id_counter=b+1;$.each(a.steps,function(f,d){var c=wf.nodes[f];$.each(d.input_connections,function(h,g){if(g){var i=wf.nodes[g.id];var j=new Connector();j.connect(i.output_terminals[g.output_name],c.input_terminals[h]);j.redraw()}})})},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.clear_active_node();parent.show_
form_for_tool(a.form_html,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){parent.show_form_for_tool(a.form_html,a)}},layout:function(){var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[sucessors[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var
q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(
this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node(i);g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='../images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<img src='../images/delete_icon.png' />").click(function(b){g.destroy()}).hover(function(){$(this).attr("src","../images/delete_icon_dark.png")},function(){$(this).attr("src","../images/delete_icon.png")}));i.appendTo("#canvas-container");var
d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o){var f=$(this).offsetParent().offset(),b=o.offsetX-f.left,p=o.offsetY-f.top;$(this).css({left:b,top:p});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prot
otype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;
var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(g){var h=$(this).offset();var f=b.cc.position();c=f.top-h.top;d=f.left-h.left}).bind("drag",function(f){a(f.offsetX+d,f.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k){var j=b.cc.width(),g=b.cc.height(),f=b.oc.width(),h=b.oc.height(),i=$(this).offsetParent().offset(),m=k.offsetX-i.left,l=k.offsetY-i.top;a(-(m/f*j),-(l/h*g))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g){var i=$(this).offsetParent();var h=i.offset();var f=Math.max(i.width()-(g.offsetX-h.left),i.height()-(g.offsetY-h.top));$(this).css({wi
dth:f,height:f});b.draw_overview()})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;$.each(workflow.nodes,function(t,q){var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewp
ort_overlay()}});
\ No newline at end of file
+function Terminal(a){this.element=a;this.connectors=[]}$.extend(Terminal.prototype,{connect:function(a){this.connectors.push(a);if(this.node){this.node.changed()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.changed()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}});function OutputTerminal(a,b){Terminal.call(this,a);this.datatype=b}OutputTerminal.prototype=new Terminal();function InputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}InputTerminal.prototype=new Terminal();$.extend(InputTerminal.prototype,{can_accept:function(a){if(this.connectors.length<1){for(var b in this.datatypes){if(a.datatype=="input"){return true}if(issubtype(a.datatype,this.datatypes[b])){return true}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a)
{this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;this.handle1.connect(this);this.handle2=a;this.handle2.connect(this)},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var n=function(c){return $(c).offset().left-d.offset().left};var i=function(c){return $(c).offset().top-d.offset().top};var h=n(this.handle1.element)+5;var g=i(this.handle1.element)+5;var p=n(this.handle2.element)+5;var m=i(this.handle2.element)+5;var f=100;var k=Math.min(h,p);var a=Math.max(h,p);var j=Math.min(g,m);var t=Math.max(g,m);var b=Math.min(Math.max(Math.abs(t-j)/2,100),300);var o=k-f;var s=j-f;var q=a-k+2*f;var l=t-j+2*f;
this.canvas.style.left=o+"px";this.canvas.style.top=s+"px";this.canvas.setAttribute("width",q);this.canvas.setAttribute("height",l);h-=o;g-=s;p-=o;m-=s;var r=this.canvas.getContext("2d");r.lineCap="round";r.strokeStyle=this.outer_color;r.lineWidth=7;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke();r.strokeStyle=this.inner_color;r.lineWidth=5;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke()}});function Node(a){this.element=a;this.input_terminals={};this.output_terminals={};this.tool_errors={}}$.extend(Node.prototype,{enable_input_terminal:function(d,a,b){var c=this;$(d).each(function(){var f=this.terminal=new InputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dropstart",function(g){g.dragProxy.terminal.connectors[0].inner_color="#BBFFBB"}).bind("dropend",function(g){g.dragProxy.terminal.connectors[0].inner_color="#FFFFFF"}).bind("drop",function(g){(new Connector(g.dragTarget.terminal,g.dropTarget.terminal)).redraw()}).bind("hov
er",function(){if(f.connectors.length>0){var g=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='buttons'></div>").append($("<img src='../images/delete_icon.png' />").click(function(){$.each(f.connectors,function(i,h){h.destroy()});g.remove()}))).bind("mouseleave",function(){$(this).remove()});g.css({top:$(this).offset().top-2,left:$(this).offset().left-g.width(),"padding-right":$(this).width()}).show()}});c.input_terminals[a]=f})},enable_output_terminal:function(d,a,b){var c=this;$(d).each(function(){var g=this;var f=this.terminal=new OutputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dragstart",function(j){var i=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);i.terminal=new OutputTerminal(i);var k=new Connector();k.dragging=true;k.connect(this.terminal,i.terminal);$.dropManage({filter:function(h){return this.terminal.can_accept(f)}}).addClass("input-terminal-active");ret
urn i}).bind("drag",function(i){var h=function(){var k=$(i.dragProxy).offsetParent().offset(),j=i.offsetX-k.left,l=i.offsetY-k.top;$(i.dragProxy).css({left:j,top:l});i.dragProxy.terminal.redraw();canvas_manager.update_viewport_overlay()};h();$("#canvas-container").get(0).scroll_panel.test(i,h)}).bind("dragend",function(h){h.dragProxy.terminal.connectors[0].destroy();$(h.dragProxy).remove();$.dropManage().removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()});c.output_terminals[a]=f})},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b
.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(g){var d=this.element;if(g.type){this.type=g.type}this.name=g.name;this.form_html=g.form_html;this.tool_state=g.tool_state;this.tool_errors=g.tool_errors;if(this.tool_errors){d.addClass("tool-node-error")}else{d.removeClass("tool-node-error")}var c=this;var a=d.find(".toolFormBody");a.find("div").remove();var h=$("<div class='inputs'></div>").appendTo(a);$.each(g.data_inputs,function(j,b){var f=$("<div class='terminal input-terminal'></div>");c.enable_input_terminal(f,b.name,b.extensions);h.append($("<div class='form-row dataRow input-data-row' name='"+b.name+"'>"+b.label+"</div>").prepend(f))});if((g.data_inputs.length>0)&&(g.data_outputs.length>0)){a.append($("<div class='rule'></div>"))}$.each(g.data_outputs,function(k,b){var j=$("<div class='terminal output-terminal'></div>");c.enable_output_terminal(j,b.name,b.extension);var f=b.name;if(b.extension!="input"){f=f+" ("+b.extensio
n+")"}a.append($("<div class='form-row dataRow'>"+f+"</div>").append(j))});workflow.node_changed(this)},update_field_data:function(f){var c=$(this.element),d=this;this.tool_state=f.tool_state;this.form_html=f.form_html;this.tool_errors=f.tool_errors;if(this.tool_errors){c.addClass("tool-node-error")}else{c.removeClass("tool-node-error")}var g=c.find("div.inputs");var b=$("<div class='inputs'></div>");var a=g.find("div.input-data-row");$.each(f.data_inputs,function(k,h){var j=$("<div class='terminal input-terminal'></div>");d.enable_input_terminal(j,h.name,h.extensions);g.find("div[name="+h.name+"]").each(function(){$(this).find(".input-terminal").each(function(){var i=this.terminal.connectors[0];if(i){j[0].terminal.connectors[0]=i;i.handle2=j[0].terminal}});$(this).remove()});b.append($("<div class='form-row dataRow input-data-row' name='"+h.name+"'>"+h.label+"</div>").prepend(j))});g.replaceWith(b);g.find("div.input-data-row > .terminal").each(function(){this.terminal.destr
oy()});this.changed();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},changed:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},to_simple:function(){var a={};$.each(this.nodes,function(b,d){var f={};$.each(d.input_terminals,function(g,h){f[h.name]=null;$.each(h.connectors,function(j,k){f[h.name]={id:k.ha
ndle1.node.id,output_name:k.handle1.name}})});var c={id:d.id,type:d.type,tool_id:d.tool_id,tool_state:d.tool_state,tool_errors:d.tool_errors,input_connections:f,position:$(d.element).position()};a[d.id]=c});return{steps:a}},from_simple:function(a){wf=this;var b=0;wf.name=a.name;$.each(a.steps,function(f,d){var c=prebuild_node("tool",d.name,d.tool_id);c.init_field_data(d);if(d.position){c.element.css({top:d.position.top,left:d.position.left})}c.id=d.id;wf.nodes[c.id]=c;b=Math.max(b,parseInt(f))});wf.id_counter=b+1;$.each(a.steps,function(f,d){var c=wf.nodes[f];$.each(d.input_connections,function(h,g){if(g){var i=wf.nodes[g.id];var j=new Connector();j.connect(i.output_terminals[g.output_name],c.input_terminals[h]);j.redraw()}})})},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.clear_active_node();parent.show_
form_for_tool(a.form_html,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){parent.show_form_for_tool(a.form_html,a)}},layout:function(){var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[sucessors[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var
q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(
this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node(i);g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='../images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<img src='../images/delete_icon.png' />").click(function(b){g.destroy()}).hover(function(){$(this).attr("src","../images/delete_icon_dark.png")},function(){$(this).attr("src","../images/delete_icon.png")}));i.appendTo("#canvas-container");var
d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o){var f=$(this).offsetParent().offset(),b=o.offsetX-f.left,p=o.offsetY-f.top;$(this).css({left:b,top:p});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prot
otype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;
var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(g){var h=$(this).offset();var f=b.cc.position();c=f.top-h.top;d=f.left-h.left}).bind("drag",function(f){a(f.offsetX+d,f.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k){var j=b.cc.width(),g=b.cc.height(),f=b.oc.width(),h=b.oc.height(),i=$(this).offsetParent().offset(),m=k.offsetX-i.left,l=k.offsetY-i.top;a(-(m/f*j),-(l/h*g))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g){var i=$(this).offsetParent();var h=i.offset();var f=Math.max(i.width()-(g.offsetX-h.left),i.height()-(g.offsetY-h.top));$(this).css({wi
dth:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(f){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;$.each(workflow.nodes,function(t,q){var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;i.fillRe
ct(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
\ No newline at end of file
1
0