Index: ../trunk-jpl/src/m/classes/clusters/generic.js
===================================================================
--- ../trunk-jpl/src/m/classes/clusters/generic.js (revision 20822)
+++ ../trunk-jpl/src/m/classes/clusters/generic.js (revision 20823)
@@ -45,18 +45,18 @@
fprintf(fid,'mpiexec -np %i %s/%s %s %s %s 2> %s.errlog >%s.outlog ',cluster.np,cluster.codepath,executable,EnumToString(solution),cluster.executionpath+'/'+dirname,modelname,modelname,modelname);
fclose(fid);
} //}}}
- this.UploadAndRun = function (md,callbackfunction,fid,toolkitsstring,solutionstring,name,runtimename) { //{{{
+ this.UploadAndRun = function (md,callbackfunction,callbackid,fid,toolkitsstring,solutionstring,name,runtimename) { //{{{
var request = new XMLHttpRequest();
- $(".run-button").html(sprintf("%-16s", "CONNECTING...")).prop("disabled", true);
+ $(callbackid).html(sprintf("%-16s", "CONNECTING...")).prop("disabled", true);
request.position = 0; //Keep track of current parsing position in repsonseText
request.timeout = 30000;
request.ontimeout = function (event) { //{{{
- $(".run-button").html(sprintf("%-16s", "RUN")).prop("disabled", false);
+ $(callbackid).html(sprintf("%-16s", "RUN")).prop("disabled", false);
} //}}}
request.upload.onprogress = function(event) { //{{{
var progress = (event.loaded / event.total * 100).toFixed(0);
- $(".run-button").html(sprintf("%-20s", "UPLOADING: " + progress + "%"));
+ $(callbackid).html(sprintf("%-20s", "UPLOADING: " + progress + "%"));
} //}}}
request.onprogress = function (event) { //{{{
//Receive updates by parsing message length as a 32-bit hex string of form 0x*09ABCDEF))
@@ -67,11 +67,11 @@
startIndex = endIndex;
endIndex = startIndex + chunkSize;
if (chunkSize >= 1024) { //Arbitrary maximium size of message (Must be below minimium size of model results)
- $(".run-button").html(sprintf("%-20s", "DOWNLOADING: " + ((request.responseText.length - request.position) / chunkSize * 100).toFixed(0) + "%")).prop("disabled", true);
+ $(callbackid).html(sprintf("%-20s", "DOWNLOADING: " + ((request.responseText.length - request.position) / chunkSize * 100).toFixed(0) + "%")).prop("disabled", true);
}
else if (request.responseText.length >= endIndex) { //Ensure entire chunk is loaded
var responseChunk = request.responseText.slice(startIndex, endIndex);
- $(".run-button").html(responseChunk);
+ $(callbackid).html(responseChunk);
request.position = endIndex;
}
}
@@ -95,7 +95,7 @@
catch (e) {
console.log(e);
}
- $(".run-button").html(sprintf("%-16s", "RUN")).prop("disabled", false);
+ $(callbackid).html(sprintf("%-16s", "RUN")).prop("disabled", false);
callbackfunction();
}; //}}}
Index: ../trunk-jpl/src/m/plot/slider.js
===================================================================
--- ../trunk-jpl/src/m/plot/slider.js (revision 20822)
+++ ../trunk-jpl/src/m/plot/slider.js (revision 20823)
@@ -1,143 +1,179 @@
-function slider() {
- //SLIDER - Slider bar with initial value, callback on change, unique name, min/max value range, description message, fill color, widht/height, value precision, value step, and the id of the div to create the slider in.
- //
- // Usage:
- // slider('value',0,'callback',function(value){PlotGreenland(value,0);PlotSlr()},'name','greenland','min',0,'max',100,'message',['Remove ice: ','%'],'color','#BBBBBB','width','100%','height','24px','precision',2,'step',5,'slidersdiv','greenland-sliders');
+/*
+ Name:
+ sliderInit
+
+ Description:
+ Initialize slider corresponding to passed selector with passed value,
+ minimum and maximum values, step (which is the increment for the
+ slider), and callback function (which is called when slider is changed).
+
+ Options are passed as pairs to the function according to the usage
+ example below.
+
+ Usage:
+ sliderInit(
+ 'selector', #some-element,
+ 'value', 0,
+ 'min', -1,
+ 'max', 1,
+ 'step', 0.1,
+ 'callback', function(value){someEngineFunction(value)}
+ );
+
+ NOTE: jQuery Mobile will reflect changes to slider in its input "label"
+ based on the width of the slider. For example, step might be set to
+ 0.1, but if the width of the slider is too narrow, changes to the
+ slider will only be reflected in whole numeral increments in the
+ slider' label. That said, *all* sliders can be adjusted via the
+ "up" and "down" keys by whatever increment step is set to.
+*/
+function sliderInit(){
+
+ // Convert arguments to options
+ var args = Array.prototype.slice.call(arguments);
+ var options = new pairoptions(args.slice());
- //Convert arguments to options
- var args = Array.prototype.slice.call(arguments);
- var options = new pairoptions(args.slice());
+ // Recover option values
+ var selector = options.getfieldvalue('selector', '');
+ var value = options.getfieldvalue('value', 0);
+ var callback = options.getfieldvalue('callback', function(event, ui){});
+ var min = options.getfieldvalue('min', 0.6 * value);
+ var max = options.getfieldvalue('max', 1.4 * value);
+ var step = options.getfieldvalue('step', 1);
- //Recover option values:
- var value = options.getfieldvalue('value',0);
- var callback = options.getfieldvalue('callback',function(){});
- var name = options.getfieldvalue('name','');
- var min = options.getfieldvalue('min',0.6*value);
- var max = options.getfieldvalue('max',1.4*value);
- var width = options.getfieldvalue('width','auto');
- var height = options.getfieldvalue('height',32);
- var message = options.getfieldvalue('message','');
- var startmessage = options.getfieldvalue('startmessage',message);
- var middlemessage = options.getfieldvalue('middlemessage',message);
- var endmessage = options.getfieldvalue('endmessage',message);
- var color = options.getfieldvalue('color','#bbbbbb');
- var precision = options.getfieldvalue('precision',3);
- var step = options.getfieldvalue('step',1);
- var slidersdiv = options.getfieldvalue('slidersdiv','slidersdiv');
+ /*
+ Update slider attributes.
+
+ NOTE: Although slider has already been created, need to call slider()
+ in order to avoid:
+
+ Error: cannot call methods on slider prior to
+ initialization; attempted to call method 'refresh'
+
+ Attempted all other methods for intialization of slider widget
+ from jQuery Mobile, and this is the only one that seemed to work
+ (see index.php for related markup).
+ */
+ $(selector).slider();
+ $(selector).val(value);
+ $(selector).attr('min', min);
+ $(selector).attr('max', max);
+ $(selector).attr('step', step);
+ $(selector).on('slidestop', function(event, ui){
+ callback(parseFloat($(selector).val()));
+ });
- $('
').appendTo('#'+slidersdiv);
- $(''+startmessage[0]+value.toFixed(precision)+startmessage[1]+'
').appendTo('#'+slidersdiv);
- var info=$('.info'+name);
- $('.'+name+'-slider').slider({
- range:'min',
- value:value,
- min:min,
- max:max,
- step:step,
- slide:function(event,ui){
- info.text(middlemessage[0]+ui.value.toFixed(precision)+middlemessage[1]);
- },
- stop:function(event,ui){
- info.text(middlemessage[0]+ui.value.toFixed(precision)+middlemessage[1]);
- callback(ui.value);
- info.text(endmessage[0]+ui.value.toFixed(precision)+endmessage[1]);
- }
- });
- $('.'+name+'-slider.ui-slider').css({
- width:'auto',
- height:height,
- background:color,
- margin:'8px'
- });
- $('.'+name+'-slider .ui-slider-handle').css({
- background:color,
- height:parseInt(height)+8
- });
- $('.'+name+'-slider .ui-slider-range').css({
- background:color
- });
+ /*
+ NOTE: Slider must be "refreshed" after any JavaScript change to it, as
+ it is an AJAX object.
+ */
+ $(selector).slider('refresh');
}
+/* exported sliderInit, refreshErrorMessages */
-function progress() {
- //PROGRESS - Progress bar with initial value, unique name, width/height, and the id of the div to create the slider in. One progress per canvas, value/label updated by node transient runs in plot_unit.
- //
- // Usage:
- // progress('value',0,'name','hma','width','100%','height',sliderheight,'progressdiv','hma-progressdiv');
- //
- // See also: PLOT_UNIT
+
+/*
+ Name:
+ sliderMoveInput
- //Convert arguments to options
- var args = Array.prototype.slice.call(arguments);
- var options = new pairoptions(args.slice());
+ Description:
+ Appends a jQuery Mobile slider input to an element whose selector
+ adheres to the following protocol,
+
+ destination = sliderSelector + '-value'
+
+ Usage:
+ sliderMoveInput('#someSliderSelector');
+
+ NOTE: Destination element must, obviously, be hardcoded into markup for a
+ call to this function to work as expected.
+*/
+function sliderMoveInput(selector){
- var value = options.getfieldvalue('value',0);
- var name = options.getfieldvalue('name','hma');
- var min = options.getfieldvalue('min',0.6*value);
- var max = options.getfieldvalue('max',1.4*value);
- var width = options.getfieldvalue('width','auto');
- var height = options.getfieldvalue('height',32);
- var color = options.getfieldvalue('color','#bbbbbb');
- var progressdiv = options.getfieldvalue('progressdiv','progressdiv');
+ $(selector).appendTo(selector + '-value');
+ $(selector).slider('refresh');
+}
+
+/*
+ value/label updated by node transient runs in plot_unit.
+*/
+function progressInit(){
- var canvas = $('#'+name)[0];
- var progressbar = $('#'+name+'-progressbar');
- var playbutton = $('#'+name+'-playbutton');
- var reversebutton = $('#'+name+'-reversebutton');
- var timelabel = $('#'+name+'-timelabel');
+ // Convert arguments to options.
+ var args = Array.prototype.slice.call(arguments);
+ var options = new pairoptions(args.slice());
+
+ // Recover option values
+ var sim = options.getfieldvalue('sim', '');
+
+ var canvas = $(sim + '-canvas')[0];
+ var progressBar = $(sim + '-controls-slider-progress');
+ var playButton = $(sim + '-controls-button-play');
+ var reverseButton = $(sim + '-controls-button-reverse');
+ var timeText = $(sim + '-controls-text-time');
+
+ /*
+ Update progress bar slider attributes.
+
+ NOTE: Although slider has already been created, need to call slider()
+ in order to avoid:
+
+ Error: cannot call methods on slider prior to
+ initialization; attempted to call method 'refresh'
+
+ Attempted all other methods for intialization of slider widget
+ from jQuery Mobile, and this is the only one that seemed to work
+ (see index.php for related markup).
+ */
+ $(progressBar).slider();
+ $(progressBar).val(value);
+ $(progressBar).attr('min', 0);
+ $(progressBar).attr('max', 1);
+ $(progressBar).attr('step', 1);
+ $(progressBar).on('slidestop', function(event, ui){
+ canvas.movieIncrement = true;
+ canvas.movieFrame = parseInt($(progressBar).val());
+ });
+ $(progressBar).on('change', function(event, ui){
+ canvas.movieFrame = parseInt($(progressBar).val());
+ });
+ $(progressBar).on('slidestart', function(event, ui){
+ canvas.movieIncrement = false;
+ canvas.movieFrame = parseInt($(progressBar).val());
+ });
+ /*
+ NOTE: Slider must be "refreshed" after any JavaScript change to it, as
+ it is an AJAX object.
+ */
+ $(progressBar).slider('refresh');
- playbutton.click(function() {
+ // Attach progress bar slider to simulation.
+ canvas.progressBar = progressBar;
+
+ playButton.click(function(){
canvas.moviePlay = !canvas.moviePlay;
- if (canvas.moviePlay) {
- $("#playButton").html("❚❚");
+ if (canvas.moviePlay){
+ playButton.find("span").removeClass("fa-play");
+ playButton.find("span").addClass("fa-pause");
}
- else {
- $("#playButton").html("▶");
+ else{
+ playButton.find("span").removeClass("fa-pause");
+ playButton.find("span").addClass("fa-play");
}
});
- reversebutton.click(function() {
+
+ reverseButton.click(function(){
canvas.movieReverse = !canvas.movieReverse;
if (canvas.movieReverse) {
- reversebutton.html("◀◀");
+ reverseButton.find("span").removeClass("fa-backward");
+ reverseButton.find("span").addClass("fa-forward");
}
else {
- reversebutton.html("▶▶");
+ reverseButton.find("span").removeClass("fa-forward");
+ reverseButton.find("span").addClass("fa-backward");
}
});
- canvas.timeLabel = timelabel;
- $('').prependTo('#'+progressdiv);
- $('.'+name+'-progressbar').slider({
- range:'min',
- value:0,
- min:0,
- max:1,
- step:1,
- start:function(event,ui){
- canvas.movieFrame = ui.value;
- canvas.movieIncrement = false;
- },
- slide:function(event,ui){
- canvas.movieFrame = ui.value;
- },
- stop:function(event,ui){
- canvas.movieFrame = ui.value;
- canvas.movieIncrement = true;
- }
- });
- $('.'+name+'-progressbar.ui-slider').css({
- width:'auto',
- height:height,
- background:color,
- margin:'8px'
- });
- $('.'+name+'-progressbar .ui-slider-handle').css({
- background:color,
- height:parseInt(height)+8
- });
- $('.'+name+'-progressbar .ui-slider-range').css({
- background:'red'
- });
-
- canvas.progressBar = $('.'+name+'-progressbar');
-}
+ canvas.timeLabel = timeText;
+}
\ No newline at end of file
Index: ../trunk-jpl/src/m/plot/plot_unit.js
===================================================================
--- ../trunk-jpl/src/m/plot/plot_unit.js (revision 20822)
+++ ../trunk-jpl/src/m/plot/plot_unit.js (revision 20823)
@@ -245,7 +245,7 @@
if (canvas["movieHandler"]) clearInterval(canvas["movieHandler"]);
canvas["movieHandler"] = setInterval(function () {
node["movieFrame"] = canvas["movieFrame"];
- if (canvas["moviePlay"]) {
+ if (canvas["moviePlay"] && canvas["movieIncrement"]) {
if (canvas["movieReverse"]) {
node["movieFrame"] = (((node["movieFrame"] - 1) % node["movieLength"]) + node["movieLength"]) % node["movieLength"]; //Handle negative modulus
}
@@ -253,15 +253,21 @@
node["movieFrame"] = (((node["movieFrame"] + 1) % node["movieLength"]) + node["movieLength"]) % node["movieLength"]; //Handle negative modulus
}
}
- if (canvas["timeLabel"]) canvas["timeLabel"].html(node["movieTimestamps"][node["movieFrame"]].toFixed(0) + " " + options.getfieldvalue("movietimeunit","yr"));
- if (canvas["progressBar"]) canvas["progressBar"].slider("value", node["movieFrame"]);
+ if (canvas["timeLabel"]) {
+ canvas["timeLabel"].html(node["movieTimestamps"][node["movieFrame"]].toFixed(0) + " " + options.getfieldvalue("movietimeunit","yr"));
+ }
+ if (canvas["progressBar"]) {
+ canvas["progressBar"].val(node["movieFrame"]);
+ canvas["progressBar"].slider('refresh');
+ }
node["buffers"] = initBuffers(gl,[node["arrays"][0],node["arrays"][1][node["movieFrame"]],node["arrays"][2]]);
canvas["movieFrame"] = node["movieFrame"];
}, node["movieInterval"]);
if (canvas["progressBar"]) {
canvas["movieFrame"] = 0;
- canvas["progressBar"].slider("value", 0);
- canvas["progressBar"].slider("option", {max: node["movieLength"]-1});
+ canvas["progressBar"].val(0);
+ canvas["progressBar"].attr('max', node["movieLength"]-1);
+ canvas["progressBar"].slider('refresh');
}
}
Index: ../trunk-jpl/src/m/solve/solve.js
===================================================================
--- ../trunk-jpl/src/m/solve/solve.js (revision 20822)
+++ ../trunk-jpl/src/m/solve/solve.js (revision 20823)
@@ -102,10 +102,16 @@
toolkitsstring= md.toolkits.ToolkitsFile(md.miscellaneous.name + '.toolkits'); // toolkits file
//callback function:
- function callbackfunction(){}; //default, do nothing if no callback requested.
- if (options.getfieldvalue('callback',false)){
- callbackfunction=options.getfieldvalue('callback');
+ function callbackfunction(){}; //default, do nothing if no callback function requested.
+ if (options.getfieldvalue('callbackfunction',false)){
+ callbackfunction=options.getfieldvalue('callbackfunction');
}
+
+ //callback id:
+ var callbackid = '.run-button'; //default, update .run-button elements with progress updates.
+ if (options.getfieldvalue('callbackid',false)){
+ callbackid=options.getfieldvalue('callbackid');
+ }
if (cluster.classname() == 'local'){ //{{{
@@ -130,7 +136,7 @@
else { //{{{
/*We are running somewhere else on a computational server. Send the buffer to that server and retrieve output: */
- cluster.UploadAndRun(md,callbackfunction,fid,toolkitsstring,solutionstring,md.miscellaneous.name,md.priv.runtimename);
+ cluster.UploadAndRun(md,callbackfunction,callbackid,fid,toolkitsstring,solutionstring,md.miscellaneous.name,md.priv.runtimename);
return md;