An in-place browser-based configurator utility
- A web form with fields for configuration values - Reads and parses standard config files - Modifies configurations dynamically in-place
This commit is contained in:
parent
3490a19103
commit
ef18bfdd3f
5 changed files with 1116 additions and 0 deletions
27
Marlin/configurator/css/configurator.css
Normal file
27
Marlin/configurator/css/configurator.css
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/* configurator.css */
|
||||||
|
/* Styles for Marlin Configurator */
|
||||||
|
|
||||||
|
body { margin: 0; padding: 0; background: #458; color: #FFC; font-family: sans-serif; }
|
||||||
|
#main { float: left; width: 100%; margin-right: -100%; }
|
||||||
|
#main { padding: 0 4%; width: 92%; }
|
||||||
|
#main { font-family: monospace; }
|
||||||
|
.info { color: #AAF; }
|
||||||
|
.info span { color: #FFF; }
|
||||||
|
.info span span { color: #000; font-weight: bold; }
|
||||||
|
p { width: 80%; color: #FF0; }
|
||||||
|
#help strong { color: #0DD; }
|
||||||
|
img { display: none; }
|
||||||
|
label, input, select, textarea { display: block; float: left; margin: 1px 0; }
|
||||||
|
label.newline, textarea { clear: both; }
|
||||||
|
label { width: 130px; height: 1em; padding: 10px 480px 10px 1em; margin-right: -470px; text-align: right; }
|
||||||
|
input[type="text"], select, .jstepper { margin: 0.75em 0 0; }
|
||||||
|
input[type="checkbox"], input[type="radio"] { margin: 1em 0 0; }
|
||||||
|
#config_form { display: block; background: #DDD; padding: 20px; color: #000; }
|
||||||
|
/*#config_text, #config_adv_text { font-family: "Andale mono", monospace; clear: both; }*/
|
||||||
|
#config_text, #config_adv_text { height: 25em; overflow: auto; background-color: #FFF; color: #888; padding: 10px; }
|
||||||
|
input[type="checkbox"], input[type="radio"].enabler { margin-left: 1em; }
|
||||||
|
input:disabled { color: #BBB; }
|
||||||
|
.clear { clear: both; }
|
||||||
|
h1, h2, h3, h4, h5, h6 { clear: both; }
|
||||||
|
h2 { margin: 0; padding: 1em 0 0; }
|
||||||
|
.jstepper { display: block; }
|
52
Marlin/configurator/index.html
Normal file
52
Marlin/configurator/index.html
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Marlin Configurator</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
|
||||||
|
<script src="js/configurator.js"></script>
|
||||||
|
<script src="js/jcanvas.js"></script>
|
||||||
|
<script src="js/jstepper.js"></script>
|
||||||
|
<link rel="stylesheet" href="css/configurator.css" type="text/css" media="all" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="main">
|
||||||
|
<h1>Marlin Configurator 0.1a</h1>
|
||||||
|
<p>Enter values in the form, get a Marlin configuration.<br/>Will include a drop-down of known configurations.</p>
|
||||||
|
<ul id="help">
|
||||||
|
<li><strong>HELP</strong> - This is the help region</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<form id="config_form">
|
||||||
|
|
||||||
|
<!-- label>Serial Port:</label><input name="SERIAL_PORT" type="text" size="4" maxlength="2" value="99" / -->
|
||||||
|
|
||||||
|
<label>Serial Port:</label><select name="SERIAL_PORT"></select><div id="serial_stepper"></div>
|
||||||
|
|
||||||
|
<label>Baud Rate:</label><select name="BAUDRATE"></select>
|
||||||
|
|
||||||
|
<label>AT90USB BT IF:</label>
|
||||||
|
<input name="BTENABLED" type="checkbox" value="1" checked />
|
||||||
|
|
||||||
|
<label class="newline">Motherboard:</label><select name="MOTHERBOARD"></select>
|
||||||
|
|
||||||
|
<label class="newline">Custom Name:</label><input name="CUSTOM_MENDEL_NAME" class="switchable" type="text" size="14" maxlength="12" value="" />
|
||||||
|
|
||||||
|
<label class="newline">Machine UUID:</label><input name="MACHINE_UUID" class="switchable" type="text" size="38" maxlength="36" value="" />
|
||||||
|
|
||||||
|
<label class="newline">Extruders:</label><select name="EXTRUDERS"></select>
|
||||||
|
|
||||||
|
<label class="newline">Power Supply:</label><select name="POWER_SUPPLY"></select>
|
||||||
|
|
||||||
|
<label>PS Default Off:</label>
|
||||||
|
<input name="PS_DEFAULT_OFF" type="checkbox" value="1" checked />
|
||||||
|
|
||||||
|
<h2>Marlin/Configuration.h</h2>
|
||||||
|
<pre id="config_text" class="prettyprint linenums"></pre>
|
||||||
|
<h2>Marlin/Configuration_adv.h</h2>
|
||||||
|
<pre id="config_adv_text" class="prettyprint linenums"></pre>
|
||||||
|
|
||||||
|
<br class="clear" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
293
Marlin/configurator/js/configurator.js
Normal file
293
Marlin/configurator/js/configurator.js
Normal file
|
@ -0,0 +1,293 @@
|
||||||
|
/**
|
||||||
|
* configurator.js
|
||||||
|
*
|
||||||
|
* Marlin Configuration Utility
|
||||||
|
* - Web form for entering configuration options
|
||||||
|
* - A reprap calculator to calculate movement values
|
||||||
|
* - Uses HTML5 to generate downloadables in Javascript
|
||||||
|
* - Reads and parses standard configuration files from local folders
|
||||||
|
*
|
||||||
|
* Supporting functions
|
||||||
|
* - Parser to read Marlin Configuration.h and Configuration_adv.h files
|
||||||
|
* - Utilities to replace values in configuration files
|
||||||
|
*/
|
||||||
|
$(function(){
|
||||||
|
|
||||||
|
var marlin_config = '..';
|
||||||
|
|
||||||
|
// Extend String
|
||||||
|
String.prototype.lpad = function(len, chr) {
|
||||||
|
if (chr === undefined) { chr = ' '; }
|
||||||
|
var s = this+'', need = len - s.length;
|
||||||
|
if (need > 0) { s = new Array(need+1).join(chr) + s; }
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
|
||||||
|
String.prototype.prePad = function(len, chr) {
|
||||||
|
return len ? this.lpad(len, chr) : this;
|
||||||
|
};
|
||||||
|
|
||||||
|
String.prototype.zeroPad = function(len) {
|
||||||
|
return len ? this.prePad(len, '0') : this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* selectField.addOptions takes an array or keyed object
|
||||||
|
*/
|
||||||
|
$.fn.extend({
|
||||||
|
addOptions: function(arrObj) {
|
||||||
|
return this.each(function() {
|
||||||
|
var sel = $(this);
|
||||||
|
var isArr = Object.prototype.toString.call(arrObj) == "[object Array]";
|
||||||
|
$.each(arrObj, function(k, v) {
|
||||||
|
sel.append( $('<option>',{value:isArr?v:k}).text(v) );
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// The app is a singleton
|
||||||
|
var configuratorApp = (function(){
|
||||||
|
|
||||||
|
// private variables and functions go here
|
||||||
|
var self,
|
||||||
|
pi2 = Math.PI * 2,
|
||||||
|
$config = $('#config_text'),
|
||||||
|
$config_adv = $('#config_adv_text'),
|
||||||
|
boards_list = {},
|
||||||
|
therms_list = {};
|
||||||
|
|
||||||
|
// Return this anonymous object as configuratorApp
|
||||||
|
return {
|
||||||
|
my_public_var: 4,
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
self = this; // a 'this' for use when 'this' is something else
|
||||||
|
|
||||||
|
// Read boards.h
|
||||||
|
boards_list = {};
|
||||||
|
$.get(marlin_config + "/boards.h", function(txt) {
|
||||||
|
// Get all the boards and save them into an object
|
||||||
|
var r, findDef = new RegExp('[ \\t]*#define[ \\t]+(BOARD_[^ \\t]+)[ \\t]+(\\d+)[ \\t]*(//[ \\t]*)?(.+)?', 'mg');
|
||||||
|
while((r = findDef.exec(txt)) !== null) {
|
||||||
|
boards_list[r[1]] = r[2].prePad(r[2] < 100 ? (r[2] < 10 ? 5 : 4) : 0, ' ') + " — " + r[4].replace(/\).*/, ')');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Read Configuration.h
|
||||||
|
$.get(marlin_config+"/Configuration.h", function(txt) {
|
||||||
|
$config.text(txt);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Read Configuration.h
|
||||||
|
$.get(marlin_config+"/Configuration_adv.h", function(txt) {
|
||||||
|
$config_adv.text(txt);
|
||||||
|
self.setupConfigForm();
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
setupConfigForm: function() {
|
||||||
|
// Modify form fields and make the form responsive.
|
||||||
|
// As values change on the form, we could update the
|
||||||
|
// contents of text areas containing the configs, for
|
||||||
|
// example.
|
||||||
|
|
||||||
|
// while(!$config_adv.text() == null) {}
|
||||||
|
// while(!$config.text() == null) {}
|
||||||
|
|
||||||
|
// Go through all form items with names
|
||||||
|
$('#config_form').find('[name]').each(function() {
|
||||||
|
// Set its id to its name
|
||||||
|
var name = $(this).attr('name');
|
||||||
|
$(this).attr({id: name});
|
||||||
|
// Attach its label sibling
|
||||||
|
var $label = $(this).prev();
|
||||||
|
if ($label[0].tagName == 'LABEL') {
|
||||||
|
$label.attr('for',name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get all 'switchable' class items and add a checkbox
|
||||||
|
$('#config_form .switchable').each(function(){
|
||||||
|
$(this).after(
|
||||||
|
$('<input>',{type:'checkbox',value:'1',class:'enabler'}).prop('checked',true)
|
||||||
|
.attr('id',this.id + '-switch')
|
||||||
|
.change(self.handleSwitch)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For now I'm manually creating these references
|
||||||
|
* but I should be able to parse Configuration.h
|
||||||
|
* and iterate the #defines.
|
||||||
|
*
|
||||||
|
* For any #ifdef blocks I can create field groups
|
||||||
|
* which can be dimmed together when the option
|
||||||
|
* is disabled.
|
||||||
|
*
|
||||||
|
* Then we only need to specify exceptions to
|
||||||
|
* standard behavior, (which is to add a text field)
|
||||||
|
*/
|
||||||
|
$('#SERIAL_PORT').addOptions([0,1,2,3,4,5,6,7]);
|
||||||
|
this.initField('SERIAL_PORT');
|
||||||
|
|
||||||
|
$('#BAUDRATE').addOptions([2400,9600,19200,38400,57600,115200,250000]);
|
||||||
|
this.initField('BAUDRATE');
|
||||||
|
|
||||||
|
this.initField('BTENABLED');
|
||||||
|
|
||||||
|
$('#MOTHERBOARD').addOptions(boards_list);
|
||||||
|
this.initField('MOTHERBOARD');
|
||||||
|
|
||||||
|
this.initField('CUSTOM_MENDEL_NAME');
|
||||||
|
|
||||||
|
this.initField('MACHINE_UUID');
|
||||||
|
|
||||||
|
$('#EXTRUDERS').addOptions([1,2,3,4]);
|
||||||
|
this.initField('EXTRUDERS');
|
||||||
|
|
||||||
|
$('#POWER_SUPPLY').addOptions({'1':'ATX','2':'Xbox 360'});
|
||||||
|
this.initField('POWER_SUPPLY');
|
||||||
|
|
||||||
|
this.initField('PS_DEFAULT_OFF');
|
||||||
|
|
||||||
|
/*
|
||||||
|
$('#serial_stepper').jstepper({
|
||||||
|
min: 0,
|
||||||
|
max: 3,
|
||||||
|
val: $('#SERIAL_PORT').val(),
|
||||||
|
arrowWidth: '18px',
|
||||||
|
arrowHeight: '15px',
|
||||||
|
color: '#FFF',
|
||||||
|
acolor: '#F70',
|
||||||
|
hcolor: '#FF0',
|
||||||
|
id: 'select-me',
|
||||||
|
stepperClass: 'inner',
|
||||||
|
textStyle: {width:'1.5em',fontSize:'120%',textAlign:'center'},
|
||||||
|
// onChange: function(v) { },
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
// prettyPrint();
|
||||||
|
},
|
||||||
|
|
||||||
|
initField: function(name) {
|
||||||
|
var $elm = $('#'+name), isText = $elm.attr('type') == 'text';
|
||||||
|
this.setFieldFromDefine(name);
|
||||||
|
isText ? $elm.bind('input', this.handleChange) : $elm.change(this.handleChange)
|
||||||
|
},
|
||||||
|
|
||||||
|
handleChange: function(e) {
|
||||||
|
self.updateDefineForField(e.target);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleSwitch: function(e) {
|
||||||
|
var $elm = $(e.target), $prev = $elm.prev();
|
||||||
|
var on = $elm.prop('checked') || false;
|
||||||
|
$prev.attr('disabled', !on);
|
||||||
|
self.setDefineEnabled($prev[0], on);
|
||||||
|
},
|
||||||
|
|
||||||
|
setDefineEnabled: function(elm, val) {
|
||||||
|
var $elm = $(elm);
|
||||||
|
|
||||||
|
// console.log("Enable: " + elm.id + " = " + val);
|
||||||
|
|
||||||
|
var txt = $config.text();
|
||||||
|
|
||||||
|
var findDef = new RegExp('^[ \\t]*(//[ \\t]*)?(#define[ \\t]+' + elm.id + '([ \\t].*)?)$', 'm');
|
||||||
|
txt = txt.replace(findDef, val ? '$2': '//$2');
|
||||||
|
|
||||||
|
// Now set the text in the field
|
||||||
|
$config.text(txt);
|
||||||
|
},
|
||||||
|
|
||||||
|
updateDefineForField: function(elm) {
|
||||||
|
var $elm = $(elm),
|
||||||
|
isCheck = $elm.attr('type') == 'checkbox',
|
||||||
|
val = isCheck ? $elm.prop('checked') : $elm.val();
|
||||||
|
|
||||||
|
// console.log("Set: " + elm.id + " = " + val);
|
||||||
|
|
||||||
|
var txt = $config.text();
|
||||||
|
|
||||||
|
if (isCheck) {
|
||||||
|
var findDef = new RegExp('^([ \\t]*)(//[ \\t]*)?(#define[ \\t]+' + elm.id + '([ \\t].*)?)$', 'm');
|
||||||
|
txt = txt.replace(findDef, val ? '$1$3': '$1//$3');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Match the define name, 1 = "#define name ", 3=value, 4=comment
|
||||||
|
var findDef = new RegExp('^([ \\t]*(//)?[ \\t]*#define[ \\t]+' + elm.id + '[ \\t]+)(.*)([ \\t]*(//)?.*)$', 'm');
|
||||||
|
if ($elm.hasClass('quote')) val = '"' + val + '"'
|
||||||
|
txt = txt.replace(findDef, '$1!!REGEXP!!$4').replace('!!REGEXP!!', val);
|
||||||
|
}
|
||||||
|
// Now set the text in the field
|
||||||
|
$config.text(txt);
|
||||||
|
|
||||||
|
// $config.scrollTo(500);
|
||||||
|
},
|
||||||
|
|
||||||
|
setFieldFromDefine: function(name, adv) {
|
||||||
|
var $elm = $('#'+name), elm = $elm[0];
|
||||||
|
var isCheck = $elm.attr('type') == 'checkbox';
|
||||||
|
var val = this.defineValue(name, adv);
|
||||||
|
|
||||||
|
isCheck ? $elm.prop('checked', val) : $elm.val("" + val);
|
||||||
|
|
||||||
|
// If the item has a checkbox then set enabled state too
|
||||||
|
var $cb = $('#'+name+'-switch');
|
||||||
|
if ($cb.length) {
|
||||||
|
var on = self.defineIsEnabled(name,adv);
|
||||||
|
$elm.attr('disabled', !on);
|
||||||
|
$cb.prop('checked', on);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
defineValue: function(name, adv) {
|
||||||
|
var $elm = $('#'+name), elm = $elm[0];
|
||||||
|
var $c = adv ? $config_adv : $config;
|
||||||
|
if ($elm.attr('type') == 'checkbox') {
|
||||||
|
// maybe spaces, maybe comment, #define, spaces, name, maybe a comment
|
||||||
|
var findDef = new RegExp('^[ \\t]*(//[ \\t]*)?(#define[ \\t]+' + elm.id + '([ \\t]*(//)?.*)?)$', 'm');
|
||||||
|
var result = findDef.exec($c.text());
|
||||||
|
return (result ? result[1] == undefined || result[1].trim() != '//' : false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// maybe spaces, maybe comment, #define, spaces, name, one or more spaces, value, maybe a comment
|
||||||
|
var findDef = new RegExp('^([ \\t]*(//[ \\t]*)?#define[ \\t]+' + elm.id + '[ \\t]+)(.*)([ \\t]*(//)?.*)$', 'm');
|
||||||
|
var result = findDef.exec($c.text());
|
||||||
|
if (result !== null) {
|
||||||
|
var val = result[3];
|
||||||
|
if (val.search(/^".*"$/) >= 0) $elm.addClass('quote');
|
||||||
|
if ($elm.hasClass('quote')) val = val.replace(/^"(.*)"$/, '$1');
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
return 'fail';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
defineIsEnabled: function(name, adv) {
|
||||||
|
var $elm = $('#'+name);
|
||||||
|
var $c = adv ? $config_adv : $config;
|
||||||
|
var findDef = new RegExp('^[ \\t]*(//[ \\t]*)?(#define[ \\t]+' + name + '([ \\t]*(//)?.*)?)$', 'm');
|
||||||
|
var result = findDef.exec($c.text());
|
||||||
|
return (result ? result[1].trim() != '//' : false);
|
||||||
|
},
|
||||||
|
|
||||||
|
logOnce: function(o) {
|
||||||
|
if (typeof o.didLogThisObject === 'undefined') {
|
||||||
|
console.log(o);
|
||||||
|
o.didLogThisObject = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
EOF: null
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Typically the app would be in its own file, but this would be here
|
||||||
|
configuratorApp.init();
|
||||||
|
|
||||||
|
});
|
524
Marlin/configurator/js/jcanvas.js
Normal file
524
Marlin/configurator/js/jcanvas.js
Normal file
|
@ -0,0 +1,524 @@
|
||||||
|
/*!
|
||||||
|
jCanvas v2.2.1
|
||||||
|
Caleb Evans
|
||||||
|
2.2.1 revisions by Thinkyhead
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function($, document, Math, Number, undefined) {
|
||||||
|
|
||||||
|
// jC global object
|
||||||
|
var jC = {};
|
||||||
|
jC.originals = {
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
cornerRadius: 0,
|
||||||
|
fillStyle: 'transparent',
|
||||||
|
strokeStyle: 'transparent',
|
||||||
|
strokeWidth: 5,
|
||||||
|
strokeCap: 'butt',
|
||||||
|
strokeJoin: 'miter',
|
||||||
|
shadowX: 0,
|
||||||
|
shadowY: 0,
|
||||||
|
shadowBlur: 10,
|
||||||
|
shadowColor: 'transparent',
|
||||||
|
x: 0, y: 0,
|
||||||
|
x1: 0, y1: 0,
|
||||||
|
radius: 10,
|
||||||
|
start: 0,
|
||||||
|
end: 360,
|
||||||
|
ccw: false,
|
||||||
|
inDegrees: true,
|
||||||
|
fromCenter: true,
|
||||||
|
closed: false,
|
||||||
|
sides: 3,
|
||||||
|
angle: 0,
|
||||||
|
text: '',
|
||||||
|
font: 'normal 12pt sans-serif',
|
||||||
|
align: 'center',
|
||||||
|
baseline: 'middle',
|
||||||
|
source: '',
|
||||||
|
repeat: 'repeat'
|
||||||
|
};
|
||||||
|
// Duplicate original defaults
|
||||||
|
jC.defaults = $.extend({}, jC.originals);
|
||||||
|
|
||||||
|
// Set global properties
|
||||||
|
function setGlobals(context, map) {
|
||||||
|
context.fillStyle = map.fillStyle;
|
||||||
|
context.strokeStyle = map.strokeStyle;
|
||||||
|
context.lineWidth = map.strokeWidth;
|
||||||
|
context.lineCap = map.strokeCap;
|
||||||
|
context.lineJoin = map.strokeJoin;
|
||||||
|
context.shadowOffsetX = map.shadowX;
|
||||||
|
context.shadowOffsetY = map.shadowY;
|
||||||
|
context.shadowBlur = map.shadowBlur;
|
||||||
|
context.shadowColor = map.shadowColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close path if chosen
|
||||||
|
function closePath(context, map) {
|
||||||
|
if (map.closed === true) {
|
||||||
|
context.closePath();
|
||||||
|
context.fill();
|
||||||
|
context.stroke();
|
||||||
|
} else {
|
||||||
|
context.fill();
|
||||||
|
context.stroke();
|
||||||
|
context.closePath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Measure angles in degrees if chosen
|
||||||
|
function checkUnits(map) {
|
||||||
|
if (map.inDegrees === true) {
|
||||||
|
return Math.PI / 180;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set canvas defaults
|
||||||
|
$.fn.canvas = function(args) {
|
||||||
|
// Reset defaults if no value is passed
|
||||||
|
if (typeof args === 'undefined') {
|
||||||
|
jC.defaults = jC.originals;
|
||||||
|
} else {
|
||||||
|
jC.defaults = $.extend({}, jC.defaults, args);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load canvas
|
||||||
|
$.fn.loadCanvas = function(context) {
|
||||||
|
if (typeof context === 'undefined') {context = '2d';}
|
||||||
|
return this[0].getContext(context);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create gradient
|
||||||
|
$.fn.gradient = function(args) {
|
||||||
|
var ctx = this.loadCanvas(),
|
||||||
|
// Specify custom defaults
|
||||||
|
gDefaults = {
|
||||||
|
x1: 0, y1: 0,
|
||||||
|
x2: 0, y2: 0,
|
||||||
|
r1: 10, r2: 100
|
||||||
|
},
|
||||||
|
params = $.extend({}, gDefaults, args),
|
||||||
|
gradient, stops = 0, percent, i;
|
||||||
|
|
||||||
|
// Create radial gradient if chosen
|
||||||
|
if (typeof args.r1 === 'undefined' && typeof args.r2 === 'undefined') {
|
||||||
|
gradient = ctx.createLinearGradient(params.x1, params.y1, params.x2, params.y2);
|
||||||
|
} else {
|
||||||
|
gradient = ctx.createRadialGradient(params.x1, params.y1, params.r1, params.x2, params.y2, params.r2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count number of color stops
|
||||||
|
for (i=1; i<=Number.MAX_VALUE; i+=1) {
|
||||||
|
if (params['c' + i]) {
|
||||||
|
stops += 1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate color stop percentages if absent
|
||||||
|
for (i=1; i<=stops; i+=1) {
|
||||||
|
percent = Math.round((100 / (stops-1)) * (i-1)) / 100;
|
||||||
|
if (typeof params['s' + i] === 'undefined') {
|
||||||
|
params['s' + i] = percent;
|
||||||
|
}
|
||||||
|
gradient.addColorStop(params['s' + i], params['c' + i]);
|
||||||
|
}
|
||||||
|
return gradient;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create pattern
|
||||||
|
$.fn.pattern = function(args) {
|
||||||
|
var ctx = this.loadCanvas(),
|
||||||
|
params = $.extend({}, jC.defaults, args),
|
||||||
|
pattern,
|
||||||
|
img = document.createElement('img');
|
||||||
|
img.src = params.source;
|
||||||
|
|
||||||
|
// Create pattern
|
||||||
|
function create() {
|
||||||
|
if (img.complete === true) {
|
||||||
|
// Create pattern
|
||||||
|
pattern = ctx.createPattern(img, params.repeat);
|
||||||
|
} else {
|
||||||
|
throw "The pattern has not loaded yet";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
create();
|
||||||
|
} catch(error) {
|
||||||
|
img.onload = create;
|
||||||
|
}
|
||||||
|
return pattern;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Clear canvas
|
||||||
|
$.fn.clearCanvas = function(args) {
|
||||||
|
var ctx = this.loadCanvas(),
|
||||||
|
params = $.extend({}, jC.defaults, args);
|
||||||
|
|
||||||
|
// Draw from center if chosen
|
||||||
|
if (params.fromCenter === true) {
|
||||||
|
params.x -= params.width / 2;
|
||||||
|
params.y -= params.height / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear entire canvas if chosen
|
||||||
|
ctx.beginPath();
|
||||||
|
if (typeof args === 'undefined') {
|
||||||
|
ctx.clearRect(0, 0, this.width(), this.height());
|
||||||
|
} else {
|
||||||
|
ctx.clearRect(params.x, params.y, params.width, params.height);
|
||||||
|
}
|
||||||
|
ctx.closePath();
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Save canvas
|
||||||
|
$.fn.saveCanvas = function() {
|
||||||
|
var ctx = this.loadCanvas();
|
||||||
|
ctx.save();
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Restore canvas
|
||||||
|
$.fn.restoreCanvas = function() {
|
||||||
|
var ctx = this.loadCanvas();
|
||||||
|
ctx.restore();
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Scale canvas
|
||||||
|
$.fn.scaleCanvas = function(args) {
|
||||||
|
var ctx = this.loadCanvas(),
|
||||||
|
params = $.extend({}, jC.defaults, args);
|
||||||
|
ctx.save();
|
||||||
|
ctx.translate(params.x, params.y);
|
||||||
|
ctx.scale(params.width, params.height);
|
||||||
|
ctx.translate(-params.x, -params.y)
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Translate canvas
|
||||||
|
$.fn.translateCanvas = function(args) {
|
||||||
|
var ctx = this.loadCanvas(),
|
||||||
|
params = $.extend({}, jC.defaults, args);
|
||||||
|
ctx.save();
|
||||||
|
ctx.translate(params.x, params.y);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Rotate canvas
|
||||||
|
$.fn.rotateCanvas = function(args) {
|
||||||
|
var ctx = this.loadCanvas(),
|
||||||
|
params = $.extend({}, jC.defaults, args),
|
||||||
|
toRad = checkUnits(params);
|
||||||
|
|
||||||
|
ctx.save();
|
||||||
|
ctx.translate(params.x, params.y);
|
||||||
|
ctx.rotate(params.angle * toRad);
|
||||||
|
ctx.translate(-params.x, -params.y);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw rectangle
|
||||||
|
$.fn.drawRect = function(args) {
|
||||||
|
var ctx = this.loadCanvas(),
|
||||||
|
params = $.extend({}, jC.defaults, args),
|
||||||
|
toRad = checkUnits(params),
|
||||||
|
x1, y1, x2, y2, r;
|
||||||
|
setGlobals(ctx, params);
|
||||||
|
|
||||||
|
// Draw from center if chosen
|
||||||
|
if (params.fromCenter === true) {
|
||||||
|
params.x -= params.width / 2;
|
||||||
|
params.y -= params.height / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw rounded rectangle if chosen
|
||||||
|
if (params.cornerRadius > 0) {
|
||||||
|
x1 = params.x;
|
||||||
|
y1 = params.y;
|
||||||
|
x2 = params.x + params.width;
|
||||||
|
y2 = params.y + params.height;
|
||||||
|
r = params.cornerRadius;
|
||||||
|
if ((x2 - x1) - (2 * r) < 0) {
|
||||||
|
r = (x2 - x1) / 2;
|
||||||
|
}
|
||||||
|
if ((y2 - y1) - (2 * r) < 0) {
|
||||||
|
r = (y2 - y1) / 2;
|
||||||
|
}
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(x1+r,y1);
|
||||||
|
ctx.lineTo(x2-r,y1);
|
||||||
|
ctx.arc(x2-r, y1+r, r, 270*toRad, 360*toRad, false);
|
||||||
|
ctx.lineTo(x2,y2-r);
|
||||||
|
ctx.arc(x2-r, y2-r, r, 0, 90*toRad, false);
|
||||||
|
ctx.lineTo(x1+r,y2);
|
||||||
|
ctx.arc(x1+r, y2-r, r, 90*toRad, 180*toRad, false);
|
||||||
|
ctx.lineTo(x1,y1+r);
|
||||||
|
ctx.arc(x1+r, y1+r, r, 180*toRad, 270*toRad, false);
|
||||||
|
ctx.fill();
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.closePath();
|
||||||
|
} else {
|
||||||
|
ctx.fillRect(params.x, params.y, params.width, params.height);
|
||||||
|
ctx.strokeRect(params.x, params.y, params.width, params.height);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw arc
|
||||||
|
$.fn.drawArc = function(args) {
|
||||||
|
var ctx = this.loadCanvas(),
|
||||||
|
params = $.extend({}, jC.defaults, args),
|
||||||
|
toRad = checkUnits(params);
|
||||||
|
setGlobals(ctx, params);
|
||||||
|
|
||||||
|
// Draw from center if chosen
|
||||||
|
if (params.fromCenter === false) {
|
||||||
|
params.x += params.radius;
|
||||||
|
params.y += params.radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(params.x, params.y, params.radius, (params.start*toRad)-(Math.PI/2), (params.end*toRad)-(Math.PI/2), params.ccw);
|
||||||
|
// Close path if chosen
|
||||||
|
closePath(ctx, params);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw ellipse
|
||||||
|
$.fn.drawEllipse = function(args) {
|
||||||
|
var ctx = this.loadCanvas(),
|
||||||
|
params = $.extend({}, jC.defaults, args),
|
||||||
|
controlW = params.width * (4/3);
|
||||||
|
setGlobals(ctx, params);
|
||||||
|
|
||||||
|
// Draw from center if chosen
|
||||||
|
if (params.fromCenter === false) {
|
||||||
|
params.x += params.width / 2;
|
||||||
|
params.y += params.height / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment coordinates to prevent negative values
|
||||||
|
params.x += 1e-10;
|
||||||
|
params.y += 1e-10;
|
||||||
|
|
||||||
|
// Create ellipse
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(params.x, params.y-params.height/2);
|
||||||
|
ctx.bezierCurveTo(params.x-controlW/2,params.y-params.height/2,
|
||||||
|
params.x-controlW/2,params.y+params.height/2,
|
||||||
|
params.x,params.y+params.height/2);
|
||||||
|
ctx.bezierCurveTo(params.x+controlW/2,params.y+params.height/2,
|
||||||
|
params.x+controlW/2,params.y-params.height/2,
|
||||||
|
params.x,params.y-params.height/2);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.fill();
|
||||||
|
ctx.stroke();
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw line
|
||||||
|
$.fn.drawLine = function(args) {
|
||||||
|
var ctx = this.loadCanvas(),
|
||||||
|
params = $.extend({}, jC.defaults, args),
|
||||||
|
max = Number.MAX_VALUE, l,
|
||||||
|
lx, ly;
|
||||||
|
setGlobals(ctx, params);
|
||||||
|
|
||||||
|
// Draw each point
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(params.x1, params.y1);
|
||||||
|
for (l=2; l<max; l+=1) {
|
||||||
|
lx = params['x' + l];
|
||||||
|
ly = params['y' + l];
|
||||||
|
// Stop loop when all points are drawn
|
||||||
|
if (typeof lx === 'undefined' || typeof ly === 'undefined') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ctx.lineTo(lx, ly);
|
||||||
|
}
|
||||||
|
// Close path if chosen
|
||||||
|
closePath(ctx, params);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw quadratic curve
|
||||||
|
$.fn.drawQuad = function(args) {
|
||||||
|
var ctx = this.loadCanvas(),
|
||||||
|
params = $.extend({}, jC.defaults, args),
|
||||||
|
max = Number.MAX_VALUE, l,
|
||||||
|
lx, ly, lcx, lcy;
|
||||||
|
setGlobals(ctx, params);
|
||||||
|
|
||||||
|
// Draw each point
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(params.x1, params.y1);
|
||||||
|
for (l=2; l<max; l+=1) {
|
||||||
|
lx = params['x' + l];
|
||||||
|
if (typeof lx === 'undefined') break;
|
||||||
|
ly = params['y' + l];
|
||||||
|
if (typeof ly === 'undefined') break;
|
||||||
|
lcx = params['cx' + (l-1)];
|
||||||
|
if (typeof lcx === 'undefined') break;
|
||||||
|
lcy = params['cy' + (l-1)];
|
||||||
|
if (typeof lcy === 'undefined') break;
|
||||||
|
ctx.quadraticCurveTo(lcx, lcy, lx, ly);
|
||||||
|
}
|
||||||
|
// Close path if chosen
|
||||||
|
closePath(ctx, params);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw Bezier curve
|
||||||
|
$.fn.drawBezier = function(args) {
|
||||||
|
var ctx = this.loadCanvas(),
|
||||||
|
params = $.extend({}, jC.defaults, args),
|
||||||
|
max = Number.MAX_VALUE,
|
||||||
|
l=2, lc=1, lx, ly, lcx1, lcy1, lcx2, lcy2, i;
|
||||||
|
setGlobals(ctx, params);
|
||||||
|
|
||||||
|
// Draw each point
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(params.x1, params.y1);
|
||||||
|
for (i=2; i<max; i+=1) {
|
||||||
|
lx = params['x' + l];
|
||||||
|
if (typeof lx === 'undefined') break;
|
||||||
|
ly = params['y' + l];
|
||||||
|
if (typeof ly === 'undefined') break;
|
||||||
|
lcx1 = params['cx' + lc];
|
||||||
|
if (typeof lcx1 === 'undefined') break;
|
||||||
|
lcy1 = params['cy' + lc];
|
||||||
|
if (typeof lcy1 === 'undefined') break;
|
||||||
|
lcx2 = params['cx' + (lc+1)];
|
||||||
|
if (typeof lcx2 === 'undefined') break;
|
||||||
|
lcy2 = params['cy' + (lc+1)];
|
||||||
|
if (typeof lcy2 === 'undefined') break;
|
||||||
|
ctx.bezierCurveTo(lcx1, lcy1, lcx2, lcy2, lx, ly);
|
||||||
|
l += 1;
|
||||||
|
lc += 2;
|
||||||
|
}
|
||||||
|
// Close path if chosen
|
||||||
|
closePath(ctx, params);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw text
|
||||||
|
$.fn.drawText = function(args) {
|
||||||
|
var ctx = this.loadCanvas(),
|
||||||
|
params = $.extend({}, jC.defaults, args);
|
||||||
|
setGlobals(ctx, params);
|
||||||
|
|
||||||
|
// Set text-specific properties
|
||||||
|
ctx.textBaseline = params.baseline;
|
||||||
|
ctx.textAlign = params.align;
|
||||||
|
ctx.font = params.font;
|
||||||
|
|
||||||
|
ctx.strokeText(params.text, params.x, params.y);
|
||||||
|
ctx.fillText(params.text, params.x, params.y);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw image
|
||||||
|
$.fn.drawImage = function(args) {
|
||||||
|
var ctx = this.loadCanvas(),
|
||||||
|
params = $.extend({}, jC.defaults, args),
|
||||||
|
// Define image source
|
||||||
|
img = document.createElement('img');
|
||||||
|
img.src = params.source;
|
||||||
|
setGlobals(ctx, params);
|
||||||
|
|
||||||
|
// Draw image function
|
||||||
|
function draw() {
|
||||||
|
if (img.complete) {
|
||||||
|
|
||||||
|
var scaleFac = img.width / img.height;
|
||||||
|
|
||||||
|
// If width/height are specified
|
||||||
|
if (typeof args.width !== 'undefined' && typeof args.height !== 'undefined') {
|
||||||
|
img.width = args.width;
|
||||||
|
img.height = args.height;
|
||||||
|
// If width is specified
|
||||||
|
} else if (typeof args.width !== 'undefined' && typeof args.height === 'undefined') {
|
||||||
|
img.width = args.width;
|
||||||
|
img.height = img.width / scaleFac;
|
||||||
|
// If height is specified
|
||||||
|
} else if (typeof args.width === 'undefined' && typeof args.height !== 'undefined') {
|
||||||
|
img.height = args.height;
|
||||||
|
img.width = img.height * scaleFac;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw from center if chosen
|
||||||
|
if (params.fromCenter === true) {
|
||||||
|
params.x -= img.width / 2;
|
||||||
|
params.y -= img.height / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw image
|
||||||
|
ctx.drawImage(img, params.x, params.y, img.width, img.height);
|
||||||
|
} else {
|
||||||
|
throw "The image has not loaded yet.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function dodraw() {
|
||||||
|
// console.log("dodraw...");
|
||||||
|
try {
|
||||||
|
// console.log("dodraw...try...");
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
catch(error) {
|
||||||
|
// console.log("dodraw...catch: " + error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw image if already loaded
|
||||||
|
// console.log("--------------------");
|
||||||
|
// console.log("drawImage " + img.src);
|
||||||
|
try {
|
||||||
|
// console.log("try...");
|
||||||
|
draw();
|
||||||
|
} catch(error) {
|
||||||
|
// console.log("catch: " + error);
|
||||||
|
img.onload = dodraw;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw polygon
|
||||||
|
$.fn.drawPolygon = function(args) {
|
||||||
|
var ctx = this.loadCanvas(),
|
||||||
|
params = $.extend({}, jC.defaults, args),
|
||||||
|
theta, dtheta, x, y,
|
||||||
|
toRad = checkUnits(params), i;
|
||||||
|
setGlobals(ctx, params);
|
||||||
|
|
||||||
|
if (params.sides >= 3) {
|
||||||
|
// Calculate points and draw
|
||||||
|
theta = (Math.PI/2) + (Math.PI/params.sides) + (params.angle*toRad);
|
||||||
|
dtheta = (Math.PI*2) / params.sides;
|
||||||
|
for (i=0; i<params.sides; i+=1) {
|
||||||
|
x = params.x + (params.radius * Math.cos(theta)) + 1e-10;
|
||||||
|
y = params.y + (params.radius * Math.sin(theta)) + 1e-10;
|
||||||
|
if (params.fromCenter === false) {
|
||||||
|
x += params.radius;
|
||||||
|
y += params.radius;
|
||||||
|
}
|
||||||
|
ctx.lineTo(x, y);
|
||||||
|
theta += dtheta;
|
||||||
|
}
|
||||||
|
closePath(ctx, params);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
return window.jCanvas = jC;
|
||||||
|
}(jQuery, document, Math, Number));
|
220
Marlin/configurator/js/jstepper.js
Normal file
220
Marlin/configurator/js/jstepper.js
Normal file
|
@ -0,0 +1,220 @@
|
||||||
|
/*!
|
||||||
|
* jQuery "stepper" Plugin
|
||||||
|
* version 0.0.1
|
||||||
|
* @requires jQuery v1.3.2 or later
|
||||||
|
* @requires jCanvas
|
||||||
|
*
|
||||||
|
* Authored 2011-06-11 Scott Lahteine (thinkyhead.com)
|
||||||
|
*
|
||||||
|
* A very simple numerical stepper.
|
||||||
|
* TODO: place arrows based on div size, make 50/50 width
|
||||||
|
*
|
||||||
|
* Usage example:
|
||||||
|
*
|
||||||
|
* $('#mydiv').jstepper({
|
||||||
|
* min: 1,
|
||||||
|
* max: 4,
|
||||||
|
* val: 1,
|
||||||
|
* arrowWidth: 15,
|
||||||
|
* arrowHeight: '22px',
|
||||||
|
* color: '#FFF',
|
||||||
|
* acolor: '#F70',
|
||||||
|
* hcolor: '#FF0',
|
||||||
|
* id: 'select-me',
|
||||||
|
* stepperClass: 'inner',
|
||||||
|
* textStyle: {width:'1.5em',fontSize:'20px',textAlign:'center'},
|
||||||
|
* onChange: function(v) { },
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
;(function($) {
|
||||||
|
var un = 'undefined';
|
||||||
|
|
||||||
|
$.jstepperArrows = [
|
||||||
|
{ name:'prev', poly:[[1.0,0],[0,0.5],[1.0,1.0]] },
|
||||||
|
{ name:'next', poly:[[0,0],[1.0,0.5],[0,1.0]] }
|
||||||
|
];
|
||||||
|
|
||||||
|
$.fn.jstepper = function(args) {
|
||||||
|
|
||||||
|
return this.each(function() {
|
||||||
|
|
||||||
|
var defaults = {
|
||||||
|
min: 1,
|
||||||
|
max: null,
|
||||||
|
val: null,
|
||||||
|
active: true,
|
||||||
|
placeholder: null,
|
||||||
|
arrowWidth: 0,
|
||||||
|
arrowHeight: 0,
|
||||||
|
color: '#FFF',
|
||||||
|
hcolor: '#FF0',
|
||||||
|
acolor: '#F80',
|
||||||
|
id: '',
|
||||||
|
stepperClass: '',
|
||||||
|
textStyle: '',
|
||||||
|
onChange: (function(v){ if (typeof console.log !== 'undefined') console.log("val="+v); })
|
||||||
|
};
|
||||||
|
|
||||||
|
args = $.extend(defaults, args || {});
|
||||||
|
|
||||||
|
var min = args.min * 1,
|
||||||
|
max = (args.max !== null) ? args.max * 1 : min,
|
||||||
|
span = max - min + 1,
|
||||||
|
val = (args.val !== null) ? args.val * 1 : min,
|
||||||
|
active = !args.disabled,
|
||||||
|
placeholder = args.placeholder,
|
||||||
|
arrowWidth = 1 * args.arrowWidth.toString().replace(/px/,''),
|
||||||
|
arrowHeight = 1 * args.arrowHeight.toString().replace(/px/,''),
|
||||||
|
color = args.color,
|
||||||
|
hcolor = args.hcolor,
|
||||||
|
acolor = args.acolor,
|
||||||
|
$prev = $('<a href="#prev" style="cursor:w-resize;"><canvas/></a>'),
|
||||||
|
$marq = $('<div class="number"/>').css({float:'left',textAlign:'center'}),
|
||||||
|
$next = $('<a href="#next" style="cursor:e-resize;"><canvas/></a>'),
|
||||||
|
arrow = [ $prev.find('canvas')[0], $next.find('canvas')[0] ],
|
||||||
|
$stepper = $('<span class="jstepper"/>').append($prev).append($marq).append($next).append('<div style="clear:both;"/>'),
|
||||||
|
onChange = args.onChange;
|
||||||
|
|
||||||
|
if (args.id) $stepper[0].id = args.id;
|
||||||
|
if (args.stepperClass) $stepper.addClass(args.stepperClass);
|
||||||
|
if (args.textStyle) $marq.css(args.textStyle);
|
||||||
|
|
||||||
|
// replace a span, but embed elsewhere
|
||||||
|
if (this.tagName == 'SPAN') {
|
||||||
|
var previd = this.id;
|
||||||
|
$(this).replaceWith($stepper);
|
||||||
|
if (previd) $stepper.attr('id',previd);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$(this).append($stepper);
|
||||||
|
}
|
||||||
|
|
||||||
|
// hook to call functions on this object
|
||||||
|
$stepper[0].ui = {
|
||||||
|
|
||||||
|
refresh: function() {
|
||||||
|
this.updateNumber();
|
||||||
|
this._drawArrow(0, 1);
|
||||||
|
this._drawArrow(1, 1);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
_drawArrow: function(i,state) {
|
||||||
|
var $elm = $(arrow[i]),
|
||||||
|
desc = $.jstepperArrows[i],
|
||||||
|
fillStyle = (state == 2) ? hcolor : (state == 3) ? acolor : color,
|
||||||
|
draw = { fillStyle: fillStyle },
|
||||||
|
w = $elm.width(), h = $elm.height();
|
||||||
|
|
||||||
|
if (w <= 0) w = $elm.attr('width');
|
||||||
|
if (h <= 0) h = $elm.attr('height');
|
||||||
|
|
||||||
|
$.each(desc.poly,function(i,v){
|
||||||
|
++i;
|
||||||
|
draw['x'+i] = v[0] * w;
|
||||||
|
draw['y'+i] = v[1] * h;
|
||||||
|
});
|
||||||
|
$elm.restoreCanvas().clearCanvas().drawLine(draw);
|
||||||
|
},
|
||||||
|
|
||||||
|
updateNumber: function() {
|
||||||
|
$marq.html((active || placeholder === null) ? val.toString() : placeholder);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
_doclick: function(i) {
|
||||||
|
this.add(i ? 1 : -1);
|
||||||
|
this._drawArrow(i, 3);
|
||||||
|
var self = this;
|
||||||
|
setTimeout(function(){ self._drawArrow(i, 2); }, 50);
|
||||||
|
},
|
||||||
|
|
||||||
|
add: function(x) {
|
||||||
|
val = (((val - min) + x + span) % span) + min;
|
||||||
|
this.updateNumber();
|
||||||
|
this.didChange(val);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
min: function(v) {
|
||||||
|
if (typeof v === un) return min;
|
||||||
|
this.setRange(v,max);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
max: function(v) {
|
||||||
|
if (typeof v === un) return max;
|
||||||
|
this.setRange(min,v);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
val: function(v) {
|
||||||
|
if (typeof v === un) return val;
|
||||||
|
val = (((v - min) + span) % span) + min;
|
||||||
|
this.updateNumber();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
setRange: function(lo, hi, ini) {
|
||||||
|
if (lo > hi) hi = (lo += hi -= lo) - hi;
|
||||||
|
min = lo; max = hi; span = hi - lo + 1;
|
||||||
|
if (typeof ini !== un) val = ini;
|
||||||
|
if (val < min) val = min;
|
||||||
|
if (val > max) val = max;
|
||||||
|
this.updateNumber();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
active: function(a) {
|
||||||
|
if (typeof a === un) return active;
|
||||||
|
(active = a) ? $marq.removeClass('inactive') : $marq.addClass('inactive');
|
||||||
|
this.updateNumber();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
disable: function() { this.active(false); return this; },
|
||||||
|
enable: function() { this.active(true); return this; },
|
||||||
|
|
||||||
|
clearPlaceholder: function() {
|
||||||
|
this.setPlaceholder(null);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
setPlaceholder: function(p) {
|
||||||
|
placeholder = p;
|
||||||
|
if (!active) this.updateNumber();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
didChange: onChange
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// set hover and click for each arrow
|
||||||
|
$.each($.jstepperArrows, function(i,desc) {
|
||||||
|
var $elm = $(arrow[i]),
|
||||||
|
w = arrowWidth ? arrowWidth : $elm.width() ? $elm.width() : 15,
|
||||||
|
h = arrowHeight ? arrowHeight : $elm.height() ? $elm.height() : 24;
|
||||||
|
$elm[0]._index = i;
|
||||||
|
$elm
|
||||||
|
.css({float:'left'})
|
||||||
|
.attr({width:w,height:h,'class':desc.name})
|
||||||
|
.hover(
|
||||||
|
function(e) { $stepper[0].ui._drawArrow(e.target._index, 2); },
|
||||||
|
function(e) { $stepper[0].ui._drawArrow(e.target._index, 1); }
|
||||||
|
)
|
||||||
|
.click(function(e){
|
||||||
|
$stepper[0].ui._doclick(e.target._index);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// init the visuals first time
|
||||||
|
$stepper[0].ui.refresh();
|
||||||
|
|
||||||
|
}); // this.each
|
||||||
|
|
||||||
|
}; // $.fn.jstepper
|
||||||
|
|
||||||
|
})( jQuery );
|
||||||
|
|
Reference in a new issue