-
Astor Bizard authored
Added interface theme selection (with custom colors option). Evaluation summary now uses details/summary html instead of js.
Astor Bizard authoredAdded interface theme selection (with custom colors option). Evaluation summary now uses details/summary html instead of js.
vplterminal.js 9.37 KiB
// This file is part of VPL for Moodle - http://vpl.dis.ulpgc.es/
//
// VPL for Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// VPL for Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with VPL for Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Terminal control
*
* @package mod_vpl
* @copyright 2014 Juan Carlos Rodríguez-del-Pino
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Juan Carlos Rodríguez-del-Pino <jcrodriguez@dis.ulpgc.es>
*/
/* globals Terminal */
define([ 'jquery', 'jqueryui', 'mod_vpl/vplutil', 'mod_vpl/vplclipboard' ],
function($, jqui, VPLUtil, VPLClipboard) {
if ( typeof VPLTerminal !== 'undefined' ) {
return VPLTerminal;
}
var VPLTerminal = function(dialogId, terminalId, str) {
var self = this;
var ws = null;
var onCloseAction = function() {
};
var title = '';
var message = '';
var tdialog = $('#' + dialogId);
var titleText = '';
var clipboard = null;
var cliboardMaxsize = 64000;
var clipboardData = '';
var terminal;
var terminalTag = $('#' + terminalId);
this.updateTitle = function() {
var text = title;
if (message !== '') {
text += ' (' + message + ')';
}
titleText.text(str('console') + ": " + text);
};
this.setTitle = function(t) {
title = t;
this.updateTitle();
};
this.setMessage = function(t) {
message = t;
this.updateTitle();
};
function receiveClipboard(data) {
clipboardData += data;
if (clipboardData.length > cliboardMaxsize) {
var from = clipboardData.length - cliboardMaxsize / 2;
clipboardData = clipboardData.substr(from);
}
}
function pasteClipboard() {
if (ws && ws.readyState == ws.OPEN) {
ws.send(clipboard.getEntry2());
}
}
function updateClipboard() {
clipboard.setEntry1(clipboardData);
}
function openClipboard() {
updateClipboard();
clipboard.show();
}
this.write = function(text) {
terminal.write(text);
return text;
};
this.connect = function(server, onClose) {
onCloseAction = onClose;
if ("WebSocket" in window) {
terminal.reset();
terminal.startBlink();
self.show();
if (ws) {
ws.close();
}
clipboardData = '';
self.setMessage('');
self.setTitle(str('connecting'));
ws = new WebSocket(server);
ws.writeBuffer = '';
ws.writeIt = function() {
terminal.write(ws.writeBuffer);
receiveClipboard(ws.writeBuffer);
ws.writeBuffer = '';
};
ws.onmessage = function(event) {
if (ws.writeBuffer.length > 0) {
ws.writeBuffer += event.data;
} else {
ws.writeBuffer = event.data;
setTimeout(ws.writeIt, 0);
}
};
ws.onopen = function() {
self.setMessage('');
self.setTitle(str('connected'));
};
ws.onclose = function() {
self.setTitle(str('connection_closed'));
terminal.blur();
terminal.stopBlink();
onClose();
ws.stopOutput = true;
};
} else {
terminal.write('WebSocket not available: Upgrade your browser');
}
};
this.writeLocal = function(text) {
ws.onmessage({
data : text
});
return text;
};
this.setDataCallback = function(call) {
ws.onData = call;
};
this.closeLocal = function() {
if (ws) {
ws.writeIt();
ws.close();
terminal.stopBlink();
self.setTitle(str('connection_closed'));
}
};
this.connectLocal = function(onClose, onData) {
onCloseAction = onClose;
terminal.reset();
terminal.startBlink();
self.show();
if (ws) {
ws.close();
}
clipboardData = '';
self.setMessage('');
self.setTitle(str('running'));
ws = {};
ws.onData = onData;
ws.writeBuffer = '';
ws.readBuffer = '';
ws.readyState = 1;
ws.OPEN = 1;
ws.close = function() {
ws = false;
};
ws.onmessage = function(event) {
ws.writeBuffer = event.data;
ws.writeIt();
};
ws.writeIt = function() {
if (ws) {
terminal.write(ws.writeBuffer);
receiveClipboard(ws.writeBuffer);
ws.writeBuffer = '';
}
};
ws.send = function(text) {
// Process backspace.
if (text == '\u007f') {
if (ws.readBuffer.length > 0) {
self.writeLocal('\b \b');
ws.readBuffer = ws.readBuffer.substr(0, ws.readBuffer.length - 1);
}
} else {
self.writeLocal(text);
ws.readBuffer += text;
}
var pos = ws.readBuffer.indexOf("\r");
if (pos != -1) {
var data = ws.readBuffer.substr(0, pos);
ws.readBuffer = ws.readBuffer.substr(pos + 1);
ws.onData(data);
}
};
};
this.isOpen = function() {
return tdialog.dialog("isOpen") === true;
};
this.isConnected = function() {
return ws && ws.readyState != ws.CLOSED;
};
this.disconnect = function() {
if (ws && ws.readyState == ws.OPEN) {
onCloseAction();
if (ws) {
ws.close();
}
terminal.stopBlink();
}
};
var HTMLUpdateClipboard = VPLUtil.genIcon('copy', 'sw') + ' ' + str('copy');
var HTMLPaste = VPLUtil.genIcon('paste', 'sw') + ' ' + str('paste');
clipboard = new VPLClipboard('vpl_dialog_terminal_clipboard', HTMLUpdateClipboard, function() {
updateClipboard();
document.execCommand('copy');
}, HTMLPaste, pasteClipboard);
this.closeDialog = function() {
clipboard.hide();
self.disconnect();
};
tdialog.dialog({
closeOnEscape : false,
autoOpen : false,
width : 'auto',
height : 'auto',
resizable : true,
focus : function() {
terminal.focus();
},
dialogClass : 'vpl_ide vpl_vnc ' + $('#vplide').attr('class').match(/(^| )(vpl_theme_[^ ]*)/)[2],
create : function() {
titleText = VPLUtil.setTitleBar(tdialog, 'console', 'console', [ 'clipboard', 'keyboard' ], [ openClipboard,
function() {
terminal.focus();
} ]);
},
close : function() {
self.closeDialog();
},
resizeStart : function() {
var cur = tdialog.find('pre').width();
var curin = tdialog.find('pre div').width();
if (cur <= curin) {
tdialog.find('pre').width(curin);
}
}
});
tdialog.css("padding", "1px");
this.show = function() {
tdialog.dialog('open');
terminal.focus();
};
this.init = function() {
if ( typeof Terminal === 'undefined' ) {
VPLUtil.loadScript(['../../vpl/editor/xterm/term.js'], function() {self.init();});
return;
}
terminal = new Terminal({
cols : 80,
rows : 24,
useStyle : true,
screenKeys : true
});
terminal.on('data', function(data) {
if (ws && ws.readyState == ws.OPEN) {
ws.send(data);
}
});
terminal.open(terminalTag[0]);
terminal.reset();
terminal.stopBlink();
};
this.init();
};
window.VPLTerminal = VPLTerminal;
return VPLTerminal;
});