Skip to content
Browse files

Current state

  • Loading branch information...
0 parents commit 3e79bb742d7683c3c92c65df1fdee02141491679 @sbstjn sbstjn committed Feb 29, 2012
Showing with 6,867 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +3 −0 .gitmodules
  3. +96 −0 app.js
  4. +1 −0 duino
  5. +21 −0 examples/http_analogled.js
  6. +26 −0 examples/http_ledonoff.js
  7. +24 −0 libs/AnalogInput.Serial.js
  8. +55 −0 libs/AnalogInput.js
  9. +43 −0 libs/Board.Serial.js
  10. +121 −0 libs/Board.js
  11. +26 −0 libs/Button.Serial.js
  12. +3 −0 libs/Button.js
  13. 0 libs/Connection.Serial.js
  14. 0 libs/Connection.Socket.js
  15. +26 −0 libs/DigitalInput.Serial.js
  16. +53 −0 libs/DigitalInput.js
  17. +6 −0 libs/DigitalOutput.Serial.js
  18. +56 −0 libs/DigitalOutput.js
  19. +18 −0 libs/LED.js
  20. +9 −0 libs/No.js
  21. +24 −0 libs/NoObject.js
  22. +17 −0 libs/Noduino.Serial.js
  23. +11 −0 libs/Noduino.Socket.js
  24. +38 −0 libs/Noduino.js
  25. +7 −0 libs/Speaker.js
  26. BIN public/images/arduino.jpg
  27. BIN public/images/forkme.png
  28. BIN public/images/glyphicons-halflings.png
  29. BIN public/images/glyphicons_009_magic.png
  30. BIN public/images/glyphicons_155_show_thumbnails.png
  31. BIN public/images/glyphicons_214_resize_small.png
  32. BIN public/images/grid-18px-masked.png
  33. +23 −0 public/scripts/init.js
  34. +28 −0 public/scripts/prettify.js
  35. +28 −0 public/styles/bootstrap/accordion.less
  36. +70 −0 public/styles/bootstrap/alerts.less
  37. +22 −0 public/styles/bootstrap/breadcrumbs.less
  38. +148 −0 public/styles/bootstrap/button-groups.less
  39. +183 −0 public/styles/bootstrap/buttons.less
  40. +121 −0 public/styles/bootstrap/carousel.less
  41. +18 −0 public/styles/bootstrap/close.less
  42. +57 −0 public/styles/bootstrap/code.less
  43. +18 −0 public/styles/bootstrap/component-animations.less
  44. +130 −0 public/styles/bootstrap/dropdowns.less
  45. +522 −0 public/styles/bootstrap/forms.less
  46. +8 −0 public/styles/bootstrap/grid.less
  47. +20 −0 public/styles/bootstrap/hero-unit.less
  48. +632 −0 public/styles/bootstrap/init.css
  49. +33 −0 public/styles/bootstrap/init.less
  50. +32 −0 public/styles/bootstrap/labels.less
  51. +17 −0 public/styles/bootstrap/layouts.less
  52. +590 −0 public/styles/bootstrap/mixins.less
  53. +83 −0 public/styles/bootstrap/modals.less
  54. +299 −0 public/styles/bootstrap/navbar.less
  55. +353 −0 public/styles/bootstrap/navs.less
  56. +30 −0 public/styles/bootstrap/pager.less
  57. +55 −0 public/styles/bootstrap/pagination.less
  58. +49 −0 public/styles/bootstrap/popovers.less
  59. +95 −0 public/styles/bootstrap/progress-bars.less
  60. +126 −0 public/styles/bootstrap/reset.less
  61. +327 −0 public/styles/bootstrap/responsive.less
  62. +29 −0 public/styles/bootstrap/scaffolding.less
  63. +158 −0 public/styles/bootstrap/sprites.less
  64. +150 −0 public/styles/bootstrap/tables.less
  65. +35 −0 public/styles/bootstrap/thumbnails.less
  66. +35 −0 public/styles/bootstrap/tooltip.less
  67. +218 −0 public/styles/bootstrap/type.less
  68. +23 −0 public/styles/bootstrap/utilities.less
  69. +107 −0 public/styles/bootstrap/variables.less
  70. +17 −0 public/styles/bootstrap/wells.less
  71. +94 −0 public/styles/init.css
  72. +813 −0 public/styles/init.less
  73. +30 −0 public/styles/prettify.css
  74. +6 −0 public/styles/reset.less
  75. +8 −0 test.blinkLED.js
  76. +87 −0 test.check.js
  77. +87 −0 test.ledwalk.js
  78. +1 −0 views/home.jade
  79. +2 −0 views/includes/snippet.jade
  80. +165 −0 views/layout.jade
1 .gitignore
@@ -0,0 +1 @@
+.DS_Store
3 .gitmodules
@@ -0,0 +1,3 @@
+[submodule "duino"]
+ path = duino
+ url = git@github.com:semu/duino.git
96 app.js
@@ -0,0 +1,96 @@
+var kickstart = require('kickstart').withConfig({'name': 'localhost', 'port': 8080, 'path': __dirname});
+var Noduino = new require('./libs/Noduino')({'debug': true});
+var Socket = function(options) { this.io = null; this.sockets = {}; this.arduinos = []; this.checkSocket(); };
+Socket.prototype.checkSocket = function() { if (this.io == null) { this.io = require('socket.io'); } };
+Socket.prototype.bootstrap = function() {
+ var that = this;
+ this.io.sockets.on('connection', function(socket) {
+ that.sockets[socket.id] = socket;
+
+ /**
+ * Handle incoming requests for connect to an arduino board
+ */
+ that.sockets[socket.id].on('board.connect', function(data) {
+ if (!data) {
+ var data = {}; }
+ if (!data.id) {
+ data.id = 0; }
+
+ if (that.arduinos[data.id]) {
+ return socket.emit('response', {'msg': 'board.connect', 'response': 'ready' }); }
+ Noduino.connect({'type': 'serial'}, function(err, board) {
+ that.arduinos[data.id] = board;
+ socket.emit('response', {'msg': 'board.connect', 'response': (!err ? 'ready' : 'failed') });
+ });
+ });
+ });
+};
+Socket.prototype.listen = function(port) { this.io = this.io.listen(port); this.bootstrap(); };
+
+var NoduinoServer = new Socket();
+NoduinoServer.listen(8090);
+
+var srv = kickstart.srv();
+
+srv.all('/', function(req, res) {
+ var examples = {
+ 'basics': [ '> ls /dev | grep usb',
+ 'crw-rw-rw- 1 root wheel 18, 17 24 Feb 22:54 cu.usbmodem1d11',
+ 'crw-rw-rw- 1 root wheel 18, 16 24 Feb 22:00 tty.usbmodem1d11'].join('\n'),
+ 'node': [ '> npm install',
+ '> node app.js',
+ 'Listening on http://localhost:8080'].join('\n'),
+ 'toggleLED': ["var Noduino = new require('./libs/Noduino')({'debug': true});",
+ "Noduino.connect({'type': 'socket'}, function(err, board) {",
+ " if (err) { return console.log(err); }",
+ " board.withLED({pin: 13}, function(err, LED) {",
+ " if (err) { return console.log(err); }",
+ "",
+ " LED.blink(250);",
+ " });",
+ "});"].join('\n'),
+ 'connect': [ "var Noduino = new require('./libs/Noduino')({'debug': true});",
+ "Noduino.connect({'type': 'socket'}, function(err, board) {",
+ " if (err) { return console.log(err); }",
+ " ",
+ " console.log('Connected to board');",
+ "});"].join('\n'),
+ 'listenButton': [ "var Noduino = new require('./libs/Noduino')({'debug': true});",
+ "Noduino.connect({'type': 'socket'}, function(err, board) {",
+ " if (err) { return console.log(err); }",
+ " ",
+ " board.withButton({pin: 9}, function(err, Button)) {",
+ " Button.on(cnst.HIGH, function(mode) {",
+ " console.log('pushed!');",
+ " });",
+ " Button.on(cnst.LOW, function(mode) {",
+ " console.log('released!');",
+ " });",
+ " })",
+ "});"].join('\n'),
+ 'analogRead': [ 'noduino.connect(function(err, board) {',
+ ' if (err) { return console.log(\'failed to connect!\'); }',
+ ' console.log(\'connected\');',
+ '});'].join('\n'),
+ 'digitalRead': [ 'noduino.connect(function(err, board) {',
+ ' board.registerPin({pin: 9}, function(err, pin) {',
+ ' pin.digitalRead(function(err, value) {',
+ ' console.log(\'received value: \' + value);',
+ ' });',
+ ' })',
+ '});'].join('\n'),
+ 'digitalWrite': [ 'noduino.connect(function(err, board) {',
+ ' board.registerPin({pin: 9}, function(err, pin) {',
+ ' pin.digitalWrite(const.HIGH, function(err, value) {',
+ ' console.log(\'set pin to value: \' + value);',
+ ' });',
+ ' })',
+ '});'].join('\n')
+
+
+ }
+ res.render('home', {title: 'noduino', 'examples': examples});
+});
+
+var router = kickstart.listen();
+console.log("Listening on http://%s:%d", kickstart.conf().name, router.address().port);
1 duino
@@ -0,0 +1 @@
+Subproject commit 2cdb2b085a22d9de661e5e61e9c781fb248d0ce4
21 examples/http_analogled.js
@@ -0,0 +1,21 @@
+var arduino = require('./duino/');
+
+var board = new arduino.Board({debug: true});
+var aled = new arduino.Led({board: board, pin: 9});
+
+board.on('ready', function(){
+ var app = require('express').createServer();
+
+ app.get('/', function(req, res){
+ res.send('<!DOCTYPE html><html><head><script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script><script>$(document).ready(function(e){console.log("a");$("#range").change(function(e) { console.log($("#range").val()); $.ajax( "/fade/" + $("#range").val()); })});</script></head><body><input type="range" class="range" id="range" name="rangeEl" value="1" min="0" max="255" step="1"></body></html>');
+ });
+
+ app.get('/fade/:level', function(req, res){
+ aled.brightLevel(req.param('level'));
+ res.send('set to: ' + req.param('level'));
+ });
+
+ app.listen(8080);
+
+ console.log('Listening on http://127.0.0.1:8080');
+});
26 examples/http_ledonoff.js
@@ -0,0 +1,26 @@
+var arduino = require('../duino/');
+
+var board = new arduino.Board({debug: true});
+var led = new arduino.Led({board: board});
+
+board.on('ready', function(){
+ var app = require('express').createServer();
+
+ app.get('/', function(req, res){
+ res.send('<a href="/on">ON</a> <a href="/off">OFF</a>');
+ });
+
+ app.get('/on', function(req, res){
+ led.on();
+ res.redirect('/');
+ });
+
+ app.get('/off', function(req, res){
+ led.off();
+ res.redirect('/');
+ });
+
+ app.listen(8080);
+
+ console.log('Listening on http://127.0.0.1:8080');
+});
24 libs/AnalogInput.Serial.js
@@ -0,0 +1,24 @@
+function AnalogInputSerial(options) {
+ if (false === (this instanceof AnalogInputSerial)) {
+ return new AnalogInputSerial(options); }
+}
+
+AnalogInputSerial.prototype.watchInput = function(AnalogInput) {
+ setInterval(function () {
+ AnalogInput.board.board.analogRead(AnalogInput.pin);
+ }, 50);
+
+ AnalogInput.board.board.on('data', function(m) {
+ m = m.split('::');
+ var eventPin = m[0]*1;
+ if (m[0].indexOf('A') > -1) {
+ eventPin = m[0]; }
+
+ var event = {pin: eventPin, 'state': m[1]*1};
+ if (event.pin == AnalogInput.pin) {
+ AnalogInput.set(event.state);
+ }
+ });
+}
+
+module.exports = AnalogInputSerial;
55 libs/AnalogInput.js
@@ -0,0 +1,55 @@
+// var NuObject = require('./NuObject')
+
+function AnalogInput(options) {
+ if (false === (this instanceof AnalogInput)) {
+ return new AnalogInput(options); }
+ this.pin = options.pin;
+ this.board = options.board;
+ this.events = {};
+ this.value = null;
+
+ if (options.type) {
+ this.setType(options.type);
+ this.watchInput();
+ }
+}
+
+AnalogInput.prototype.watchInput = function() {
+ this.c.watchInput(this);
+}
+
+AnalogInput.prototype.on = function(event, callback) {
+ if (!this.events[event]) {
+ this.events[event] = []; }
+ this.events[event].push(callback);
+};
+
+AnalogInput.prototype.set = function(value, callback) {
+ var tmp = this.value - value;
+ if (tmp > -2 && tmp < 2) {
+ return; }
+ if (this.value != value) {
+ this.value = value;
+ this.emit('change');
+ }
+};
+
+AnalogInput.prototype.emit = function(event, callback) {
+ if (!this.events[event]) {
+ return; }
+ for (var i = 0; i < this.events[event].length; i++) {
+ this.events[event][i](this);
+ }
+};
+
+AnalogInput.prototype.setType = function(type) {
+ this.type = type;
+
+ switch (type) {
+ case 'serial': var Connection = require('./AnalogInput.Serial'); this.c = new Connection(this.options); break;
+ case 'socket': var Connection = require('./AnalogInput.Socket'); this.c = new Connection(this.options); break;
+ default: throw new Error('Unknown connection type: ' + type); break;
+ }
+}
+
+module.exports = AnalogInput;
43 libs/Board.Serial.js
@@ -0,0 +1,43 @@
+var cnst = {
+ 'LED': 0x31,
+ 'BOTTON': 0x32,
+ 'HIGH': 'on',
+ 'LOW': 'off',
+ MODE_OUT: 'out',
+ MODE_IN: 'in'
+
+};
+
+function BoardSerial(options) {
+ if (false === (this instanceof BoardSerial)) {
+ return new BoardSerial(options); }
+ this.options = options;
+ this.board = options.board;
+};
+
+BoardSerial.prototype.withDigitalOutput = function(Board, pin, next) {
+ Board.board.pinMode(pin, cnst.MODE_OUT);
+ next(null, pin);
+};
+
+BoardSerial.prototype.withLED = function(Board, pin, next) {
+ Board.board.pinMode(pin, cnst.MODE_OUT);
+ next(null, pin);
+};
+
+BoardSerial.prototype.withAnalogInput = function(Board, pin, next) {
+ Board.board.pinMode(pin, cnst.MODE_IN);
+ next(null, pin);
+}
+
+BoardSerial.prototype.withButton = function(Board, pin, next) {
+ Board.board.pinMode(pin, cnst.MODE_IN);
+ next(null, pin);
+};
+
+BoardSerial.prototype.digitalWrite = function(Board, pin, mode, next) {
+ Board.board.digitalWrite(pin, mode, next);
+};
+
+
+module.exports = BoardSerial;
121 libs/Board.js
@@ -0,0 +1,121 @@
+var cnst = {
+ 'LED': 0x31,
+ 'DIGITAL_OUT': 0x31,
+ 'BOTTON': 0x32,
+ 'ANALOG_IN': 0x33,
+ 'HIGH': 'on',
+ 'LOW': 'off',
+};
+
+var LEDObj = require('./LED.js');
+var ButtonObj = require('./Button.js');
+var AnalogInputObj = require('./AnalogInput.js');
+var DigitalOutObj = require('./DigitalOutput.js');
+var SpeakerObj = require('./Speaker.js');
+
+function Board(options) {
+ if (false === (this instanceof Board)) {
+ return new Board(options); }
+ this.options = options;
+ this.board = options.board;
+ this.pinMapping = {};
+ this.setType(options.type);
+};
+
+Board.prototype.HIGH = '255';
+Board.prototype.LOW = '000';
+
+Board.prototype.setBoard = function(board) {
+ this.board = board;
+};
+
+Board.prototype.pinType = function(pin) {
+ return this.pinMapping[pin];
+}
+
+Board.prototype.pinAvailable = function(pin) {
+ return (this.pinMapping[pin]);
+};
+
+Board.prototype.digitalWrite = function(pin, mode, next) {
+ this.c.digitalWrite(this, pin, mode, function(err) {
+ if (err) { return next(err); }
+ });
+};
+
+Board.prototype.withLED = function(options, next) {
+ if (this.pinAvailable(options.pin)) {
+ return next(new Error('PIN already in use')); }
+
+ this.pinMapping[options.pin] = cnst.LED;
+ var that = this;
+ this.c.withLED(that, options.pin, function(err, pin) {
+ if (err) { return next(err); }
+
+ next(null, new LEDObj({"board": that, "pin": pin, "type": that.type}));
+ });
+};
+
+Board.prototype.withSpeaker = function(options, next) {
+ if (this.pinAvailable(options.pin)) {
+ return next(new Error('PIN already in use')); }
+
+ this.pinMapping[options.pin] = cnst.DIGITAL_OUT;
+ var that = this;
+ this.c.withDigitalOutput(that, options.pin, function(err, pin) {
+ if (err) { return next(err); }
+
+ next(null, new SpeakerObj({"board": that, "pin": pin, "type": that.type}));
+ });
+};
+
+Board.prototype.withDigitalOutput = function(options, next) {
+ if (this.pinAvailable(options.pin)) {
+ return next(new Error('PIN already in use')); }
+
+ this.pinMapping[options.pin] = cnst.DIGITAL_OUT;
+ var that = this;
+ this.c.withDigitalOutput(that, options.pin, function(err, pin) {
+ if (err) { return next(err); }
+
+ next(null, new DigitalOutObj({"board": that, "pin": pin, "type": that.type}));
+ });
+};
+
+Board.prototype.withButton = function(options, next) {
+ if (this.pinAvailable(options.pin)) {
+ return next(new Error('PIN already in use')); }
+
+ this.pinMapping[options.pin] = cnst.BUTTON;
+ var that = this;
+ this.c.withButton(that, options.pin, function(err, pin) {
+ if (err) { return next(err); }
+
+ next(null, new ButtonObj({"board": that, "pin": pin, "type": that.type}));
+ });
+};
+
+Board.prototype.withAnalogInput = function(options, next) {
+ if (this.pinAvailable(options.pin)) {
+ return next(new Error('PIN already in use')); }
+
+ this.pinMapping[options.pin] = cnst.ANALOG_IN;
+ var that = this;
+ this.c.withAnalogInput(that, options.pin, function(err, pin) {
+ if (err) { return next(err); }
+
+ next(null, new AnalogInputObj({"board": that, "pin": pin, "type": that.type}));
+ });
+}
+
+Board.prototype.setType = function(type) {
+ this.type = type;
+
+ switch (type) {
+ case 'serial': var Connection = require('./Board.Serial'); this.c = new Connection(this.options); break;
+ case 'socket': var Connection = require('./Board.Socket'); this.c = new Connection(this.options); break;
+ default: throw new Error('Unknown connection type: ' + type); break;
+ }
+}
+
+module.exports = Board;
26 libs/Button.Serial.js
@@ -0,0 +1,26 @@
+function ButtonSerial(options) {
+ if (false === (this instanceof ButtonSerial)) {
+ return new ButtonSerial(options); }
+}
+
+ButtonSerial.prototype.watchButton = function(Button) {
+ setInterval(function () {
+ Button.board.board.digitalRead(Button.pin);
+ }, 50);
+
+ Button.board.board.on('data', function(m) {
+ m = m.split('::');
+ var event = {pin: m[0]*1, 'state': m[1]*1};
+
+ if (event.pin == Button.pin) {
+ if (event.state == 0 && Button.pushed) {
+ Button.release();
+ }
+ if (event.state == 1 && !Button.pushed) {
+ Button.push();
+ }
+ }
+ });
+}
+
+module.exports = ButtonSerial;
3 libs/Button.js
@@ -0,0 +1,3 @@
+var Button = require('./DigitalInput');
+
+module.exports = Button;
0 libs/Connection.Serial.js
No changes.
0 libs/Connection.Socket.js
No changes.
26 libs/DigitalInput.Serial.js
@@ -0,0 +1,26 @@
+function DigitalInputSerial(options) {
+ if (false === (this instanceof DigitalInputSerial)) {
+ return new DigitalInputSerial(options); }
+}
+
+DigitalInputSerial.prototype.watchButton = function(Button) {
+ setInterval(function () {
+ Button.board.board.digitalRead(Button.pin);
+ }, 50);
+
+ Button.board.board.on('data', function(m) {
+ m = m.split('::');
+ var event = {pin: m[0]*1, 'state': m[1]*1};
+
+ if (event.pin == Button.pin) {
+ if (event.state == 0 && Button.pushed) {
+ Button.release();
+ }
+ if (event.state == 1 && !Button.pushed) {
+ Button.push();
+ }
+ }
+ });
+}
+
+module.exports = DigitalInputSerial;
53 libs/DigitalInput.js
@@ -0,0 +1,53 @@
+function DigitalInput(options) {
+ if (false === (this instanceof DigitalInput)) {
+ return new DigitalInput(options); }
+ this.pin = options.pin;
+ this.board = options.board;
+ this.pushed = false;
+ this.events = {};
+
+ if (options.type) {
+ this.setType(options.type);
+ this.watchButton();
+ }
+}
+
+DigitalInput.prototype.watchButton = function() {
+ this.c.watchButton(this);
+}
+
+DigitalInput.prototype.push = function(callback) {
+ this.pushed = true;
+ this.emit('push');
+};
+
+DigitalInput.prototype.release = function(callback) {
+ this.pushed = false;
+ this.emit('release');
+};
+
+DigitalInput.prototype.on = function(event, callback) {
+ if (!this.events[event]) {
+ this.events[event] = []; }
+ this.events[event].push(callback);
+};
+
+DigitalInput.prototype.emit = function(event, callback) {
+ if (!this.events[event]) {
+ return; }
+ for (var i = 0; i < this.events[event].length; i++) {
+ this.events[event][i]();
+ }
+};
+
+DigitalInput.prototype.setType = function(type) {
+ this.type = type;
+
+ switch (type) {
+ case 'serial': var Connection = require('./DigitalInput.Serial'); this.c = new Connection(this.options); break;
+ case 'socket': var Connection = require('./DigitalInput.Socket'); this.c = new Connection(this.options); break;
+ default: throw new Error('Unknown connection type: ' + type); break;
+ }
+}
+
+module.exports = DigitalInput;
6 libs/DigitalOutput.Serial.js
@@ -0,0 +1,6 @@
+function DigitalOutputSerial(options) {
+ if (false === (this instanceof DigitalOutputSerial)) {
+ return new DigitalOutputSerial(options); }
+};
+
+module.exports = DigitalOutputSerial;
56 libs/DigitalOutput.js
@@ -0,0 +1,56 @@
+function DigitalOutput(options) {
+ if (false === (this instanceof DigitalOutput)) {
+ return new DigitalOutput(options); }
+
+ this.pin = options.pin;
+ this.board = options.board;
+ this.mode = this.board.LOW;
+ this.events = {};
+
+ if (options.type) {
+ this.setType(options.type); }
+};
+
+DigitalOutput.prototype.setOn = function(callback) {
+ if (!this.active) {
+ this.active = true;
+ this.set(this.board.HIGH, callback);
+ this.emit('on');
+ }
+};
+
+DigitalOutput.prototype.setOff = function(callback) {
+ if (this.active) {
+ this.active = false;
+ this.set(this.board.LOW, callback);
+ this.emit('off');
+ }
+};
+
+DigitalOutput.prototype.set = function(mode, callback) {
+ this.mode = mode;
+ this.board.digitalWrite(this.pin, mode, callback);
+};
+
+DigitalOutput.prototype.on = function(event, callback) {
+ if (!this.events[event]) {
+ this.events[event] = []; }
+ this.events[event].push(callback);
+};
+
+DigitalOutput.prototype.emit = function(event, callback) {
+ if (!this.events[event]) {
+ return; }
+ for (var i = 0; i < this.events[event].length; i++) {
+ this.events[event][i](this); }
+};
+
+DigitalOutput.prototype.setType = function(type) {
+ switch (type) {
+ case 'serial': var Connection = require('./DigitalOutput.Serial'); this.c = new Connection(this.options); break;
+ case 'socket': var Connection = require('./DigitalOutput.Socket'); this.c = new Connection(this.options); break;
+ default: throw new Error('Unknown connection type: ' + type); break;
+ }
+};
+
+module.exports = DigitalOutput;
18 libs/LED.js
@@ -0,0 +1,18 @@
+var LED = require('./DigitalOutput');
+
+LED.prototype.toggle = function(callback) {
+ if (this.mode == this.board.LOW) {
+ return this.set(this.board.HIGH, callback); }
+ this.set(this.board.LOW, callback);
+};
+
+LED.prototype.blink = function(interval) {
+ if (interval*1 < 25) {
+ interval = 50; }
+ var that = this;
+ setInterval(function(){
+ that.toggle();
+ }, interval);
+};
+
+module.exports = LED;
9 libs/No.js
@@ -0,0 +1,9 @@
+var No = function() {
+
+};
+
+No.prototype.DigitalOut = require('./DigitalOutput');
+No.prototype.LED = require('./LED');
+No.prototype.Speaker = require('./LED');
+
+export.modules = No;
24 libs/NoObject.js
@@ -0,0 +1,24 @@
+var NoObject = function(name) {
+ this.name = name;
+ this.events = {};
+}
+
+NoObject.prototype.withName = function(name) {
+ return new NoObject(name);
+};
+
+NoObject.prototype.on = function(event, callback) {
+ if (!this.events[event]) {
+ this.events[event] = []; }
+ this.events[event].push(callback);
+};
+
+NoObject.prototype.emit = function(event, callback) {
+ if (!this.events[event]) {
+ return; }
+ for (var i = 0; i < this.events[event].length; i++) {
+ this.events[event][i]();
+ }
+};
+
+module.exports = NoObject;
17 libs/Noduino.Serial.js
@@ -0,0 +1,17 @@
+function SerialNoduino (options) {
+ if (false === (this instanceof SerialNoduino)) {
+ return new SerialNoduino(options); }
+ this.options = options;
+};
+
+SerialNoduino.prototype.connect = function(options, next) {
+ var Board = require('../duino/lib/board.js');
+ new Board({'debug': this.options.debug || false}, function(err, board) {
+ if (err) { return next(new Error('Unable to connect')); }
+
+ board.on('ready', function(){
+ next(null, board); });
+ });
+}
+
+module.exports = SerialNoduino;
11 libs/Noduino.Socket.js
@@ -0,0 +1,11 @@
+function SerialNoduino (options) {
+ if (false === (this instanceof SerialNoduino)) {
+ return new SerialNoduino();
+ }
+};
+
+SerialNoduino.prototype.connect = function(options, callback) {
+ callback(null, {'board': '11'});
+}
+
+module.exports = SerialNoduino;
38 libs/Noduino.js
@@ -0,0 +1,38 @@
+var objBoard = require('./Board.js');
+
+/**
+ * Create Noduini object for handling general access
+ * @param object options
+ */
+function Noduino(options) {
+ if (false === (this instanceof Noduino)) {
+ return new Noduino(options); }
+ this.options = options;
+ this.type = options.type;
+ this.setType(options.type);
+};
+
+Noduino.prototype.setType = function(type) {
+ this.type = type;
+
+ switch (type) {
+ case 'serial': var Connection = require('./Noduino.Serial'); this.c = new Connection(this.options); break;
+ case 'socket': var Connection = require('./Noduino.Socket'); this.c = new Connection(this.options); break;
+ default: throw new Error('Unknown connection type: ' + type); break;
+ }
+}
+
+Noduino.prototype.connect = function(options, callback) {
+ if (!callback) {
+ callback = options; options = {}; }
+ var that = this;
+ return this.c.connect(options, function(err, board) {
+ if (err) { return callback(err); }
+
+ options.type = that.type;
+ options.board = board;
+ callback(null, new objBoard(options));
+ });
+}
+
+module.exports = Noduino;
7 libs/Speaker.js
@@ -0,0 +1,7 @@
+var Speaker = require('./DigitalOutput');
+
+Speaker.prototype.isMuted = function() {
+ return !this.active;
+};
+
+module.exports = Speaker;
BIN public/images/arduino.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN public/images/forkme.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN public/images/glyphicons-halflings.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN public/images/glyphicons_009_magic.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN public/images/glyphicons_155_show_thumbnails.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN public/images/glyphicons_214_resize_small.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN public/images/grid-18px-masked.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 public/scripts/init.js
@@ -0,0 +1,23 @@
+/* init.js */
+var socket = null;
+var Noduino = function(options) { if (!this.socket) { this.socket = io.connect(options.host); } this.callbacks = {}; var that = this; this.socket.on('response', function(data) { var err = data, board = {}; switch(data.msg) { case 'board.connect': if (data.response == 'ready') {err=null;} that.callbacks[data.msg](err, board); break;} }) };
+Noduino.prototype.connect = function(options, callback) { if (!callback) { callback = options; } this.callbacks['board.connect'] = callback; this.socket.emit('board.connect'); };
+
+$(document).ready(function(e) {
+ $('#buttonConnect').click(function(e) {
+ e.preventDefault();
+
+ var noduino = new Noduino({host: 'http://localhost:8090'});
+ $('#exampleConnection .alert').addClass('hide');
+ $('#exampleConnection .alert-info').removeClass('hide');
+ $('#exampleConnection .alert-info').html('Trying to connect to your Arduino…');
+ noduino.connect(function(err, board) {
+ $('#exampleConnection .alert').addClass('hide');
+ if (err) {
+ $('#exampleConnection .alert-error').removeClass('hide'); }
+ else {
+ $('#exampleConnection .alert-success').removeClass('hide'); }
+ });
+ });
+
+});
28 public/scripts/prettify.js
@@ -0,0 +1,28 @@
+var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
+(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
+[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c<
+f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&&
+(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r=
+{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length,
+t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===
+"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),
+l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
+q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/,
+q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g,
+"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a),
+a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}
+for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value",
+m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m=
+a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue=
+j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
+"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],
+H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
+J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+
+I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),
+["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",
+/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),
+["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",
+hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b=
+!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,
+250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",
+PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();
28 public/styles/bootstrap/accordion.less
@@ -0,0 +1,28 @@
+// ACCORDION
+// ---------
+
+
+// Parent container
+.accordion {
+ margin-bottom: @baseLineHeight;
+}
+
+// Group == heading + body
+.accordion-group {
+ margin-bottom: 2px;
+ border: 1px solid #e5e5e5;
+ .border-radius(4px);
+}
+.accordion-heading {
+ border-bottom: 0;
+}
+.accordion-heading .accordion-toggle {
+ display: block;
+ padding: 8px 15px;
+}
+
+// Inner needs the styles because you can't animate properly with any styles on the element
+.accordion-inner {
+ padding: 9px 15px;
+ border-top: 1px solid #e5e5e5;
+}
70 public/styles/bootstrap/alerts.less
@@ -0,0 +1,70 @@
+// ALERT STYLES
+// ------------
+
+// Base alert styles
+.alert {
+ padding: 8px 35px 8px 14px;
+ margin-bottom: @baseLineHeight;
+ text-shadow: 0 1px 0 rgba(255,255,255,.5);
+ background-color: @warningBackground;
+ border: 1px solid @warningBorder;
+ .border-radius(4px);
+}
+.alert,
+.alert-heading {
+ color: @warningText;
+}
+
+// Adjust close link position
+.alert .close {
+ position: relative;
+ top: -2px;
+ right: -21px;
+ line-height: 18px;
+}
+
+// Alternate styles
+// ----------------
+
+.alert-success {
+ background-color: @successBackground;
+ border-color: @successBorder;
+}
+.alert-success,
+.alert-success .alert-heading {
+ color: @successText;
+}
+.alert-danger,
+.alert-error {
+ background-color: @errorBackground;
+ border-color: @errorBorder;
+}
+.alert-danger,
+.alert-error,
+.alert-danger .alert-heading,
+.alert-error .alert-heading {
+ color: @errorText;
+}
+.alert-info {
+ background-color: @infoBackground;
+ border-color: @infoBorder;
+}
+.alert-info,
+.alert-info .alert-heading {
+ color: @infoText;
+}
+
+
+// Block alerts
+// ------------------------
+.alert-block {
+ padding-top: 14px;
+ padding-bottom: 14px;
+}
+.alert-block > p,
+.alert-block > ul {
+ margin-bottom: 0;
+}
+.alert-block p + p {
+ margin-top: 5px;
+}
22 public/styles/bootstrap/breadcrumbs.less
@@ -0,0 +1,22 @@
+// BREADCRUMBS
+// -----------
+
+.breadcrumb {
+ padding: 7px 14px;
+ margin: 0 0 @baseLineHeight;
+ #gradient > .vertical(@white, #f5f5f5);
+ border: 1px solid #ddd;
+ .border-radius(3px);
+ .box-shadow(inset 0 1px 0 @white);
+ li {
+ display: inline-block;
+ text-shadow: 0 1px 0 @white;
+ }
+ .divider {
+ padding: 0 5px;
+ color: @grayLight;
+ }
+ .active a {
+ color: @grayDark;
+ }
+}
148 public/styles/bootstrap/button-groups.less
@@ -0,0 +1,148 @@
+// BUTTON GROUPS
+// -------------
+
+
+// Make the div behave like a button
+.btn-group {
+ position: relative;
+ .clearfix(); // clears the floated buttons
+ .ie7-restore-left-whitespace();
+}
+
+// Space out series of button groups
+.btn-group + .btn-group {
+ margin-left: 5px;
+}
+
+// Optional: Group multiple button groups together for a toolbar
+.btn-toolbar {
+ margin-top: @baseLineHeight / 2;
+ margin-bottom: @baseLineHeight / 2;
+ .btn-group {
+ display: inline-block;
+ .ie7-inline-block();
+ }
+}
+
+// Float them, remove border radius, then re-add to first and last elements
+.btn-group .btn {
+ position: relative;
+ float: left;
+ margin-left: -1px;
+ .border-radius(0);
+}
+// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match
+.btn-group .btn:first-child {
+ margin-left: 0;
+ -webkit-border-top-left-radius: 4px;
+ -moz-border-radius-topleft: 4px;
+ border-top-left-radius: 4px;
+ -webkit-border-bottom-left-radius: 4px;
+ -moz-border-radius-bottomleft: 4px;
+ border-bottom-left-radius: 4px;
+}
+.btn-group .btn:last-child,
+.btn-group .dropdown-toggle {
+ -webkit-border-top-right-radius: 4px;
+ -moz-border-radius-topright: 4px;
+ border-top-right-radius: 4px;
+ -webkit-border-bottom-right-radius: 4px;
+ -moz-border-radius-bottomright: 4px;
+ border-bottom-right-radius: 4px;
+}
+// Reset corners for large buttons
+.btn-group .btn.large:first-child {
+ margin-left: 0;
+ -webkit-border-top-left-radius: 6px;
+ -moz-border-radius-topleft: 6px;
+ border-top-left-radius: 6px;
+ -webkit-border-bottom-left-radius: 6px;
+ -moz-border-radius-bottomleft: 6px;
+ border-bottom-left-radius: 6px;
+}
+.btn-group .btn.large:last-child,
+.btn-group .large.dropdown-toggle {
+ -webkit-border-top-right-radius: 6px;
+ -moz-border-radius-topright: 6px;
+ border-top-right-radius: 6px;
+ -webkit-border-bottom-right-radius: 6px;
+ -moz-border-radius-bottomright: 6px;
+ border-bottom-right-radius: 6px;
+}
+
+// On hover/focus/active, bring the proper btn to front
+.btn-group .btn:hover,
+.btn-group .btn:focus,
+.btn-group .btn:active,
+.btn-group .btn.active {
+ z-index: 2;
+}
+
+// On active and open, don't show outline
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+ outline: 0;
+}
+
+
+
+// Split button dropdowns
+// ----------------------
+
+// Give the line between buttons some depth
+.btn-group .dropdown-toggle {
+ padding-left: 8px;
+ padding-right: 8px;
+ @shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
+ .box-shadow(@shadow);
+ *padding-top: 5px;
+ *padding-bottom: 5px;
+}
+
+.btn-group.open {
+ // IE7's z-index only goes to the nearest positioned ancestor, which would
+ // make the menu appear below buttons that appeared later on the page
+ *z-index: @zindexDropdown;
+
+ // Reposition menu on open and round all corners
+ .dropdown-menu {
+ display: block;
+ margin-top: 1px;
+ .border-radius(5px);
+ }
+
+ .dropdown-toggle {
+ background-image: none;
+ @shadow: inset 0 1px 6px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);
+ .box-shadow(@shadow);
+ }
+}
+
+// Reposition the caret
+.btn .caret {
+ margin-top: 7px;
+ margin-left: 0;
+}
+.btn:hover .caret,
+.open.btn-group .caret {
+ .opacity(100);
+}
+
+
+// Account for other colors
+.btn-primary,
+.btn-danger,
+.btn-info,
+.btn-success,
+.btn-inverse {
+ .caret {
+ border-top-color: @white;
+ .opacity(75);
+ }
+}
+
+// Small button dropdowns
+.btn-small .caret {
+ margin-top: 4px;
+}
+
183 public/styles/bootstrap/buttons.less
@@ -0,0 +1,183 @@
+// BUTTON STYLES
+// -------------
+
+
+// Base styles
+// --------------------------------------------------
+
+// Core
+.btn {
+ display: inline-block;
+ padding: 4px 10px 4px;
+ margin-bottom: 0; // For input.btn
+ font-size: @baseFontSize;
+ line-height: @baseLineHeight;
+ color: @grayDark;
+ text-align: center;
+ text-shadow: 0 1px 1px rgba(255,255,255,.75);
+ vertical-align: middle;
+ .buttonBackground(@white, darken(@white, 10%));
+ border: 1px solid #ccc;
+ border-bottom-color: #bbb;
+ .border-radius(4px);
+ @shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
+ .box-shadow(@shadow);
+ cursor: pointer;
+
+ // Give IE7 some love
+ .reset-filter();
+ .ie7-restore-left-whitespace();
+}
+
+// Hover state
+.btn:hover {
+ color: @grayDark;
+ text-decoration: none;
+ background-color: darken(@white, 10%);
+ background-position: 0 -15px;
+
+ // transition is only when going to hover, otherwise the background
+ // behind the gradient (there for IE<=9 fallback) gets mismatched
+ .transition(background-position .1s linear);
+}
+
+// Focus state for keyboard and accessibility
+.btn:focus {
+ .tab-focus();
+}
+
+// Active state
+.btn.active,
+.btn:active {
+ background-image: none;
+ @shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);
+ .box-shadow(@shadow);
+ background-color: darken(@white, 10%);
+ background-color: darken(@white, 15%) e("\9");
+ outline: 0;
+}
+
+// Disabled state
+.btn.disabled,
+.btn[disabled] {
+ cursor: default;
+ background-image: none;
+ background-color: darken(@white, 10%);
+ .opacity(65);
+ .box-shadow(none);
+}
+
+
+// Button Sizes
+// --------------------------------------------------
+
+// Large
+.btn-large {
+ padding: 9px 14px;
+ font-size: @baseFontSize + 2px;
+ line-height: normal;
+ .border-radius(5px);
+}
+.btn-large [class^="icon-"] {
+ margin-top: 1px;
+}
+
+// Small
+.btn-small {
+ padding: 5px 9px;
+ font-size: @baseFontSize - 2px;
+ line-height: @baseLineHeight - 2px;
+}
+.btn-small [class^="icon-"] {
+ margin-top: -1px;
+}
+
+// Mini
+.btn-mini {
+ padding: 2px 6px;
+ font-size: @baseFontSize - 2px;
+ line-height: @baseLineHeight - 4px;
+}
+
+
+// Alternate buttons
+// --------------------------------------------------
+
+// Set text color
+// -------------------------
+.btn-primary,
+.btn-primary:hover,
+.btn-warning,
+.btn-warning:hover,
+.btn-danger,
+.btn-danger:hover,
+.btn-success,
+.btn-success:hover,
+.btn-info,
+.btn-info:hover,
+.btn-inverse,
+.btn-inverse:hover {
+ text-shadow: 0 -1px 0 rgba(0,0,0,.25);
+ color: @white;
+}
+// Provide *some* extra contrast for those who can get it
+.btn-primary.active,
+.btn-warning.active,
+.btn-danger.active,
+.btn-success.active,
+.btn-info.active,
+.btn-dark.active {
+ color: rgba(255,255,255,.75);
+}
+
+// Set the backgrounds
+// -------------------------
+.btn-primary {
+ .buttonBackground(@primaryButtonBackground, spin(@primaryButtonBackground, 20));
+}
+// Warning appears are orange
+.btn-warning {
+ .buttonBackground(lighten(@orange, 15%), @orange);
+}
+// Danger and error appear as red
+.btn-danger {
+ .buttonBackground(#ee5f5b, #bd362f);
+}
+// Success appears as green
+.btn-success {
+ .buttonBackground(#62c462, #51a351);
+}
+// Info appears as a neutral blue
+.btn-info {
+ .buttonBackground(#5bc0de, #2f96b4);
+}
+// Inverse appears as dark gray
+.btn-inverse {
+ .buttonBackground(#454545, #262626);
+}
+
+
+// Cross-browser Jank
+// --------------------------------------------------
+
+button.btn,
+input[type="submit"].btn {
+
+ // Firefox 3.6 only I believe
+ &::-moz-focus-inner {
+ padding: 0;
+ border: 0;
+ }
+
+ // IE7 has some default padding on button controls
+ *padding-top: 2px;
+ *padding-bottom: 2px;
+ &.large {
+ *padding-top: 7px;
+ *padding-bottom: 7px;
+ }
+ &.small {
+ *padding-top: 3px;
+ *padding-bottom: 3px;
+ }
+}
121 public/styles/bootstrap/carousel.less
@@ -0,0 +1,121 @@
+// CAROUSEL
+// --------
+
+.carousel {
+ position: relative;
+ margin-bottom: @baseLineHeight;
+ line-height: 1;
+}
+
+.carousel-inner {
+ overflow: hidden;
+ width: 100%;
+ position: relative;
+}
+
+.carousel {
+
+ .item {
+ display: none;
+ position: relative;
+ .transition(.6s ease-in-out left);
+ }
+
+ // Account for jankitude on images
+ .item > img {
+ display: block;
+ line-height: 1;
+ }
+
+ .active,
+ .next,
+ .prev { display: block; }
+
+ .active {
+ left: 0;
+ }
+
+ .next,
+ .prev {
+ position: absolute;
+ top: 0;
+ width: 100%;
+ }
+
+ .next {
+ left: 100%;
+ }
+ .prev {
+ left: -100%;
+ }
+ .next.left,
+ .prev.right {
+ left: 0;
+ }
+
+ .active.left {
+ left: -100%;
+ }
+ .active.right {
+ left: 100%;
+ }
+
+}
+
+// Left/right controls for nav
+// ---------------------------
+
+.carousel-control {
+ position: absolute;
+ top: 40%;
+ left: 15px;
+ width: 40px;
+ height: 40px;
+ margin-top: -20px;
+ font-size: 60px;
+ font-weight: 100;
+ line-height: 30px;
+ color: @white;
+ text-align: center;
+ background: @grayDarker;
+ border: 3px solid @white;
+ .border-radius(23px);
+ .opacity(50);
+
+ // we can't have this transition here
+ // because webkit cancels the carousel
+ // animation if you trip this while
+ // in the middle of another animation
+ // ;_;
+ // .transition(opacity .2s linear);
+
+ // Reposition the right one
+ &.right {
+ left: auto;
+ right: 15px;
+ }
+
+ // Hover state
+ &:hover {
+ color: @white;
+ text-decoration: none;
+ .opacity(90);
+ }
+}
+
+// Caption for text below images
+// -----------------------------
+
+.carousel-caption {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ padding: 10px 15px 5px;
+ background: @grayDark;
+ background: rgba(0,0,0,.75);
+}
+.carousel-caption h4,
+.carousel-caption p {
+ color: @white;
+}
18 public/styles/bootstrap/close.less
@@ -0,0 +1,18 @@
+// CLOSE ICONS
+// -----------
+
+.close {
+ float: right;
+ font-size: 20px;
+ font-weight: bold;
+ line-height: @baseLineHeight;
+ color: @black;
+ text-shadow: 0 1px 0 rgba(255,255,255,1);
+ .opacity(20);
+ &:hover {
+ color: @black;
+ text-decoration: none;
+ .opacity(40);
+ cursor: pointer;
+ }
+}
57 public/styles/bootstrap/code.less
@@ -0,0 +1,57 @@
+// Code.less
+// Code typography styles for the <code> and <pre> elements
+// --------------------------------------------------------
+
+// Inline and block code styles
+code,
+pre {
+ padding: 0 3px 2px;
+ #font > #family > .monospace;
+ font-size: @baseFontSize - 1;
+ color: @grayDark;
+ .border-radius(3px);
+}
+
+// Inline code
+code {
+ padding: 3px 4px;
+ color: #d14;
+ background-color: #f7f7f9;
+ border: 1px solid #e1e1e8;
+}
+
+// Blocks of code
+pre {
+ display: block;
+ padding: (@baseLineHeight - 1) / 2;
+ margin: 0 0 @baseLineHeight / 2;
+ font-size: 12px;
+ line-height: @baseLineHeight;
+ background-color: #f5f5f5;
+ border: 1px solid #ccc; // fallback for IE7-8
+ border: 1px solid rgba(0,0,0,.15);
+ .border-radius(4px);
+ white-space: pre;
+ white-space: pre-wrap;
+ word-break: break-all;
+ word-wrap: break-word;
+
+ // Make prettyprint styles more spaced out for readability
+ &.prettyprint {
+ margin-bottom: @baseLineHeight;
+ }
+
+ // Account for some code outputs that place code tags in pre tags
+ code {
+ padding: 0;
+ color: inherit;
+ background-color: transparent;
+ border: 0;
+ }
+}
+
+// Enable scrollable blocks of code
+.pre-scrollable {
+ max-height: 340px;
+ overflow-y: scroll;
+}
18 public/styles/bootstrap/component-animations.less
@@ -0,0 +1,18 @@
+// COMPONENT ANIMATIONS
+// --------------------
+
+.fade {
+ .transition(opacity .15s linear);
+ opacity: 0;
+ &.in {
+ opacity: 1;
+ }
+}
+
+.collapse {
+ .transition(height .35s ease);
+ position:relative;
+ overflow:hidden;
+ height: 0;
+ &.in { height: auto; }
+}
130 public/styles/bootstrap/dropdowns.less
@@ -0,0 +1,130 @@
+// DROPDOWN MENUS
+// --------------
+
+// Use the .menu class on any <li> element within the topbar or ul.tabs and you'll get some superfancy dropdowns
+.dropdown {
+ position: relative;
+}
+.dropdown-toggle {
+ // The caret makes the toggle a bit too tall in IE7
+ *margin-bottom: -3px;
+}
+.dropdown-toggle:active,
+.open .dropdown-toggle {
+ outline: 0;
+}
+// Dropdown arrow/caret
+.caret {
+ display: inline-block;
+ width: 0;
+ height: 0;
+ text-indent: -99999px;
+ // IE7 won't do the border trick if there's a text indent, but it doesn't
+ // do the content that text-indent is hiding, either, so we're ok.
+ *text-indent: 0;
+ vertical-align: top;
+ border-left: 4px solid transparent;
+ border-right: 4px solid transparent;
+ border-top: 4px solid @black;
+ .opacity(30);
+ content: "\2193";
+}
+.dropdown .caret {
+ margin-top: 8px;
+ margin-left: 2px;
+}
+.dropdown:hover .caret,
+.open.dropdown .caret {
+ .opacity(100);
+}
+// The dropdown menu (ul)
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: @zindexDropdown;
+ float: left;
+ display: none; // none by default, but block on "open" of the menu
+ min-width: 160px;
+ _width: 160px;
+ padding: 4px 0;
+ margin: 0; // override default ul
+ list-style: none;
+ background-color: @white;
+ border-color: #ccc;
+ border-color: rgba(0,0,0,.2);
+ border-style: solid;
+ border-width: 1px;
+ .border-radius(0 0 5px 5px);
+ .box-shadow(0 5px 10px rgba(0,0,0,.2));
+ -webkit-background-clip: padding-box;
+ -moz-background-clip: padding;
+ background-clip: padding-box;
+ *border-right-width: 2px;
+ *border-bottom-width: 2px;
+
+ // Allow for dropdowns to go bottom up (aka, dropup-menu)
+ &.bottom-up {
+ top: auto;
+ bottom: 100%;
+ margin-bottom: 2px;
+ }
+
+ // Dividers (basically an hr) within the dropdown
+ .divider {
+ height: 1px;
+ margin: 5px 1px;
+ overflow: hidden;
+ background-color: #e5e5e5;
+ border-bottom: 1px solid @white;
+
+ // IE7 needs a set width since we gave a height. Restricting just
+ // to IE7 to keep the 1px left/right space in other browsers.
+ // It is unclear where IE is getting the extra space that we need
+ // to negative-margin away, but so it goes.
+ *width: 100%;
+ *margin: -5px 0 5px;
+ }
+
+ // Links within the dropdown menu
+ a {
+ display: block;
+ padding: 3px 15px;
+ clear: both;
+ font-weight: normal;
+ line-height: @baseLineHeight;
+ color: @gray;
+ white-space: nowrap;
+ }
+}
+
+// Hover state
+.dropdown-menu li > a:hover,
+.dropdown-menu .active > a,
+.dropdown-menu .active > a:hover {
+ color: @white;
+ text-decoration: none;
+ background-color: @linkColor;
+}
+
+// Open state for the dropdown
+.dropdown.open {
+ // IE7's z-index only goes to the nearest positioned ancestor, which would
+ // make the menu appear below buttons that appeared later on the page
+ *z-index: @zindexDropdown;
+
+ .dropdown-toggle {
+ color: @white;
+ background: #ccc;
+ background: rgba(0,0,0,.3);
+ }
+ .dropdown-menu {
+ display: block;
+ }
+}
+
+// Typeahead
+.typeahead {
+ margin-top: 2px; // give it some space to breathe
+ .border-radius(4px);
+}
522 public/styles/bootstrap/forms.less
@@ -0,0 +1,522 @@
+// Forms.less
+// Base styles for various input types, form layouts, and states
+// -------------------------------------------------------------
+
+
+// GENERAL STYLES
+// --------------
+
+// Make all forms have space below them
+form {
+ margin: 0 0 @baseLineHeight;
+}
+
+fieldset {
+ padding: 0;
+ margin: 0;
+ border: 0;
+}
+
+// Groups of fields with labels on top (legends)
+legend {
+ display: block;
+ width: 100%;
+ padding: 0;
+ margin-bottom: @baseLineHeight * 1.5;
+ font-size: @baseFontSize * 1.5;
+ line-height: @baseLineHeight * 2;
+ color: @grayDark;
+ border: 0;
+ border-bottom: 1px solid #eee;
+
+ // Small
+ small {
+ font-size: @baseLineHeight * .75;
+ color: @grayLight;
+ }
+}
+
+// Set font for forms
+label,
+input,
+button,
+select,
+textarea {
+ #font > .shorthand(@baseFontSize,normal,@baseLineHeight); // Set size, weight, line-height here
+}
+input,
+button,
+select,
+textarea {
+ #font > #family > .sans-serif(); // And only set font-family here for those that need it (note the missing label element)
+}
+
+// Identify controls by their labels
+label {
+ display: block;
+ margin-bottom: 5px;
+ color: @grayDark;
+}
+
+// Inputs, Textareas, Selects
+input,
+textarea,
+select,
+.uneditable-input {
+ display: inline-block;
+ width: 210px;
+ height: @baseLineHeight;
+ padding: 4px;
+ margin-bottom: 9px;
+ font-size: @baseFontSize;
+ line-height: @baseLineHeight;
+ color: @gray;
+ border: 1px solid #ccc;
+ .border-radius(3px);
+}
+.uneditable-textarea {
+ width: auto;
+ height: auto;
+}
+
+// Inputs within a label
+label input,
+label textarea,
+label select {
+ display: block;
+}
+
+// Mini reset for unique input types
+input[type="image"],
+input[type="checkbox"],
+input[type="radio"] {
+ width: auto;
+ height: auto;
+ padding: 0;
+ margin: 3px 0;
+ *margin-top: 0; /* IE7 */
+ line-height: normal;
+ cursor: pointer;
+ .border-radius(0);
+ border: 0 \9; /* IE9 and down */
+}
+input[type="image"] {
+ border: 0;
+}
+
+// Reset the file input to browser defaults
+input[type="file"] {
+ width: auto;
+ padding: initial;
+ line-height: initial;
+ border: initial;
+ background-color: @white;
+ background-color: initial;
+ .box-shadow(none);
+}
+
+// Help out input buttons
+input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+ width: auto;
+ height: auto;
+}
+
+// Set the height of select and file controls to match text inputs
+select,
+input[type="file"] {
+ height: 28px; /* In IE7, the height of the select element cannot be changed by height, only font-size */
+ *margin-top: 4px; /* For IE7, add top margin to align select with labels */
+ line-height: 28px;
+}
+
+// Reset line-height for IE
+input[type="file"] {
+ line-height: 18px \9;
+}
+
+// Chrome on Linux and Mobile Safari need background-color
+select {
+ width: 220px; // default input width + 10px of padding that doesn't get applied
+ background-color: @white;
+}
+
+// Make multiple select elements height not fixed
+select[multiple],
+select[size] {
+ height: auto;
+}
+
+// Remove shadow from image inputs
+input[type="image"] {
+ .box-shadow(none);
+}
+
+// Make textarea height behave
+textarea {
+ height: auto;
+}
+
+// Hidden inputs
+input[type="hidden"] {
+ display: none;
+}
+
+
+
+// CHECKBOXES & RADIOS
+// -------------------
+
+// Indent the labels to position radios/checkboxes as hanging
+.radio,
+.checkbox {
+ padding-left: 18px;
+}
+.radio input[type="radio"],
+.checkbox input[type="checkbox"] {
+ float: left;
+ margin-left: -18px;
+}
+
+// Move the options list down to align with labels
+.controls > .radio:first-child,
+.controls > .checkbox:first-child {
+ padding-top: 5px; // has to be padding because margin collaspes
+}
+
+// Radios and checkboxes on same line
+// TODO v3: Convert .inline to .control-inline
+.radio.inline,
+.checkbox.inline {
+ display: inline-block;
+ padding-top: 5px;
+ margin-bottom: 0;
+ vertical-align: middle;
+}
+.radio.inline + .radio.inline,
+.checkbox.inline + .checkbox.inline {
+ margin-left: 10px; // space out consecutive inline controls
+}
+
+
+
+// FOCUS STATE
+// -----------
+
+input,
+textarea {
+ .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));
+ @transition: border linear .2s, box-shadow linear .2s;
+ .transition(@transition);
+}
+input:focus,
+textarea:focus {
+ border-color: rgba(82,168,236,.8);
+ @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);
+ .box-shadow(@shadow);
+ outline: 0;
+ outline: thin dotted \9; /* IE6-9 */
+}
+input[type="file"]:focus,
+input[type="radio"]:focus,
+input[type="checkbox"]:focus,
+select:focus {
+ .box-shadow(none); // override for file inputs
+ .tab-focus();
+}
+
+
+
+// INPUT SIZES
+// -----------
+
+// General classes for quick sizes
+.input-mini { width: 60px; }
+.input-small { width: 90px; }
+.input-medium { width: 150px; }
+.input-large { width: 210px; }
+.input-xlarge { width: 270px; }
+.input-xxlarge { width: 530px; }
+
+// Grid style input sizes
+input[class*="span"],
+select[class*="span"],
+textarea[class*="span"],
+.uneditable-input {
+ float: none;
+ margin-left: 0;
+}
+
+
+
+// GRID SIZING FOR INPUTS
+// ----------------------
+
+#inputGridSystem > .generate(@gridColumns, @gridColumnWidth, @gridGutterWidth);
+
+
+
+
+// DISABLED STATE
+// --------------
+
+// Disabled and read-only inputs
+input[disabled],
+select[disabled],
+textarea[disabled],
+input[readonly],
+select[readonly],
+textarea[readonly] {
+ background-color: #f5f5f5;
+ border-color: #ddd;
+ cursor: not-allowed;
+}
+
+
+
+
+// FORM FIELD FEEDBACK STATES
+// --------------------------
+
+// Warning
+.control-group.warning {
+ .formFieldState(@warningText, @warningText, @warningBackground);
+}
+// Error
+.control-group.error {
+ .formFieldState(@errorText, @errorText, @errorBackground);
+}
+// Success
+.control-group.success {
+ .formFieldState(@successText, @successText, @successBackground);
+}
+
+// HTML5 invalid states
+// Shares styles with the .control-group.error above
+input:focus:required:invalid,
+textarea:focus:required:invalid,
+select:focus:required:invalid {
+ color: #b94a48;
+ border-color: #ee5f5b;
+ &:focus {
+ border-color: darken(#ee5f5b, 10%);
+ .box-shadow(0 0 6px lighten(#ee5f5b, 20%));
+ }
+}
+
+
+
+// FORM ACTIONS
+// ------------
+
+.form-actions {
+ padding: (@baseLineHeight - 1) 20px @baseLineHeight;
+ margin-top: @baseLineHeight;
+ margin-bottom: @baseLineHeight;
+ background-color: #f5f5f5;
+ border-top: 1px solid #ddd;
+}
+
+// For text that needs to appear as an input but should not be an input