diff --git a/.npmignore b/.npmignore
new file mode 100644
index 00000000..7bf00685
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,11 @@
+.git*
+build/
+.lock-wscript
+out/
+Makefile.gyp
+*.Makefile
+*.target.gyp.mk
+node_modules/
+img/
+test/
+*.node
diff --git a/example/index.html b/example/index.html
new file mode 100644
index 00000000..f08d0bcc
--- /dev/null
+++ b/example/index.html
@@ -0,0 +1,53 @@
+
+
tty.js
+
+
+tty.js
+
+
+
diff --git a/example/index.js b/example/index.js
new file mode 100644
index 00000000..04ca2140
--- /dev/null
+++ b/example/index.js
@@ -0,0 +1,93 @@
+/**
+ * tty.js
+ * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
+ */
+
+var http = require('http')
+ , express = require('express')
+ , io = require('socket.io')
+ , pty = require('pty.js');
+
+/**
+ * tty.js
+ */
+
+process.title = 'tty.js';
+
+/**
+ * Open Terminal
+ */
+
+var buff = []
+ , socket
+ , term;
+
+var term = pty.fork(process.env.SHELL || 'sh', [], {
+ name: 'xterm',
+ cols: 80,
+ rows: 24,
+ cwd: process.env.HOME
+});
+
+term.on('data', function(data) {
+ return !socket
+ ? buff.push(data)
+ : socket.emit('data', data);
+});
+
+console.log(''
+ + 'Created shell with pty master/slave'
+ + ' pair (master: %d, pid: %d)',
+ term.fd, term.pid);
+
+/**
+ * App & Server
+ */
+
+var app = express()
+ , server = http.createServer(app);
+
+app.use(function(req, res, next) {
+ var setHeader = res.setHeader;
+ res.setHeader = function(name) {
+ switch (name) {
+ case 'Cache-Control':
+ case 'Last-Modified':
+ case 'ETag':
+ return;
+ }
+ return setHeader.apply(res, arguments);
+ };
+ next();
+});
+
+app.use(express.static(__dirname));
+app.use(express.static(__dirname + '/../lib'));
+
+server.listen(8080);
+
+/**
+ * Sockets
+ */
+
+io = io.listen(server);
+
+io.configure(function() {
+ io.disable('log');
+});
+
+io.sockets.on('connection', function(sock) {
+ socket = sock;
+
+ socket.on('data', function(data) {
+ term.write(data);
+ });
+
+ socket.on('disconnect', function() {
+ socket = null;
+ });
+
+ while (buff.length) {
+ socket.emit('data', buff.shift());
+ }
+});
diff --git a/lib/index.js b/lib/index.js
index f837da1f..2f4e508f 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -1,6 +1,7 @@
/**
* term.js - an xterm emulator
- * Copyright (c) 2013, Christopher Jeffrey (https://github.com/chjj/term.js)
+ * Copyright (c) 2013, Christopher Jeffrey (MIT License)
+ * https://github.com/chjj/term.js
*/
function term(options) {
diff --git a/lib/term.js b/lib/term.js
index 6cd07ebd..073ee199 100644
--- a/lib/term.js
+++ b/lib/term.js
@@ -1,7 +1,7 @@
/**
* term.js - an xterm emulator
- *
- * Copyright (c) 2012-2013, Christopher Jeffrey (https://github.com/chjj/term.js)
+ * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
+ * https://github.com/chjj/term.js
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -262,6 +262,25 @@ Terminal.colors = [
'#eeeeec'
];
+Terminal.xtermColors = [
+ '#000000', // black
+ '#cd0000', // red3
+ '#00cd00', // green3
+ '#cdcd00', // yellow3
+ '#0000ee', // blue2
+ '#cd00cd', // magenta3
+ '#00cdcd', // cyan3
+ '#e5e5e5', // gray90
+ '#7f7f7f', // gray50
+ '#ff0000', // red
+ '#00ff00', // green
+ '#ffff00', // yellow
+ '#5c5cff', // rgb:5c/5c/ff
+ '#ff00ff', // magenta
+ '#00ffff', // cyan
+ '#ffffff' // white
+];
+
// Colors 16-255
// Much thanks to TooTallNate for writing this.
Terminal.colors = (function() {
@@ -326,14 +345,41 @@ Terminal.focus = null;
Terminal.prototype.focus = function() {
if (Terminal.focus === this) return;
+
if (Terminal.focus) {
- Terminal.focus.cursorState = 0;
- Terminal.focus.refresh(Terminal.focus.y, Terminal.focus.y);
- if (Terminal.focus.sendFocus) Terminal.focus.send('\x1b[O');
+ Terminal.focus.blur();
}
- Terminal.focus = this;
+
if (this.sendFocus) this.send('\x1b[I');
this.showCursor();
+
+ // try {
+ // this.element.focus();
+ // } catch (e) {
+ // ;
+ // }
+
+ // this.emit('focus');
+
+ Terminal.focus = this;
+};
+
+Terminal.prototype.blur = function() {
+ if (Terminal.focus !== this) return;
+
+ this.cursorState = 0;
+ this.refresh(this.y, this.y);
+ if (this.sendFocus) this.send('\x1b[O');
+
+ // try {
+ // this.element.blur();
+ // } catch (e) {
+ // ;
+ // }
+
+ // this.emit('blur');
+
+ Terminal.focus = null;
};
/**
@@ -341,17 +387,57 @@ Terminal.prototype.focus = function() {
*/
Terminal.bindKeys = function(document) {
- if (Terminal.focus) return;
+ Terminal._boundDocs = Terminal._boundDocs || [];
+
+ if (~indexOf(Terminal._boundDocs, document)) {
+ return;
+ }
+
+ Terminal._boundDocs.push(document);
// We could put an "if (Terminal.focus)" check
// here, but it shouldn't be necessary.
on(document, 'keydown', function(ev) {
- return Terminal.focus.keyDown(ev);
+ if (!Terminal.focus) return;
+ var target = ev.target || ev.srcElement;
+ // Should just be body, but we can
+ // check everything for good measure.
+ if (target === Terminal.focus.element
+ || target === Terminal.focus.context
+ || target === Terminal.focus.document
+ || target === Terminal.focus.document.body
+ || target === Terminal.focus.parent) {
+ return Terminal.focus.keyDown(ev);
+ }
}, true);
on(document, 'keypress', function(ev) {
- return Terminal.focus.keyPress(ev);
+ if (!Terminal.focus) return;
+ var target = ev.target || ev.srcElement;
+ // Should just be body, but we can
+ // check everything for good measure.
+ if (target === Terminal.focus.element
+ || target === Terminal.focus.context
+ || target === Terminal.focus.document
+ || target === Terminal.focus.document.body
+ || target === Terminal.focus.parent) {
+ return Terminal.focus.keyPress(ev);
+ }
}, true);
+
+ // If we click somewhere other than a
+ // terminal, unfocus the terminal.
+ on(document, 'mousedown', function(ev) {
+ if (!Terminal.focus) return;
+
+ var el = ev.target || ev.srcElement;
+
+ do {
+ if (el === Terminal.focus.element) return;
+ } while (el = el.parentNode);
+
+ Terminal.focus.blur();
+ });
};
/**
@@ -367,6 +453,9 @@ Terminal.prototype.open = function(parent) {
this.element = this.document.createElement('div');
this.element.className = 'terminal';
+ this.element.style.outline = 'none';
+ this.element.setAttribute('tabindex', 0);
+
this.children = [];
for (; i < this.rows; i++) {
@@ -385,6 +474,14 @@ Terminal.prototype.open = function(parent) {
this.startBlink();
+ on(this.element, 'focus', function() {
+ self.focus();
+ });
+
+ // on(this.element, 'blur', function() {
+ // self.blur();
+ // });
+
on(this.element, 'mousedown', function() {
self.focus();
});
@@ -434,7 +531,7 @@ Terminal.prototype.open = function(parent) {
this.element.style.backgroundColor = Terminal.defaultColors.bg;
this.element.style.color = Terminal.defaultColors.fg;
- //this.emit('open');
+ this.emit('open');
};
// XTerm mouse events
@@ -4231,6 +4328,14 @@ var String = this.String;
var setTimeout = this.setTimeout;
var setInterval = this.setInterval;
+function indexOf(obj, el) {
+ var i = obj.length;
+ while (i--) {
+ if (obj[i] === el) return i;
+ }
+ return -1;
+}
+
/**
* Expose
*/