separation of rows and cli, more refactoring for new world, copying images from skywriter
|
|
@ -446,7 +446,8 @@ Requisition.prototype = {
|
||||||
* Helper to call canon.exec
|
* Helper to call canon.exec
|
||||||
*/
|
*/
|
||||||
exec: function() {
|
exec: function() {
|
||||||
canon.exec(this.command, this.getArgs());
|
// TODO: have a toString rather than hack this.input
|
||||||
|
canon.exec(this.command, this.getArgs(), this.input.typed);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
exports.Requisition = Requisition;
|
exports.Requisition = Requisition;
|
||||||
|
|
@ -492,8 +493,8 @@ oop.inherits(CliRequisition, Requisition);
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
CliRequisition.prototype.update = function(input) {
|
CliRequisition.prototype.update = function(input) {
|
||||||
// TODO: We only store this so getHints can work. Find a better way.
|
|
||||||
this.input = input;
|
this.input = input;
|
||||||
|
// TODO: We only store this so getHints can work. Find a better way.
|
||||||
this.localHints = [];
|
this.localHints = [];
|
||||||
|
|
||||||
if (util.none(input.typed)) {
|
if (util.none(input.typed)) {
|
||||||
|
|
|
||||||
BIN
plugins/cockpit/lib/ui/images/closer.png
Normal file
|
After Width: | Height: | Size: 669 B |
BIN
plugins/cockpit/lib/ui/images/dot_clear.gif
Normal file
|
After Width: | Height: | Size: 42 B |
BIN
plugins/cockpit/lib/ui/images/minus.png
Normal file
|
After Width: | Height: | Size: 604 B |
BIN
plugins/cockpit/lib/ui/images/pinaction.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
plugins/cockpit/lib/ui/images/pinin.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
plugins/cockpit/lib/ui/images/pinout.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
plugins/cockpit/lib/ui/images/pins.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
plugins/cockpit/lib/ui/images/plus.png
Normal file
|
After Width: | Height: | Size: 635 B |
BIN
plugins/cockpit/lib/ui/images/throbber.gif
Normal file
|
After Width: | Height: | Size: 11 KiB |
|
|
@ -38,6 +38,29 @@
|
||||||
border: none; outline: none;
|
border: none; outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cptOutput {
|
||||||
|
border: 1px solid #AAA;
|
||||||
|
-moz-border-radius-topleft: 10px;
|
||||||
|
-moz-border-radius-topright: 10px;
|
||||||
|
border-top-left-radius: 4px; border-top-right-radius: 4px;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0 15px;
|
||||||
|
background: #DDD; color: #000;
|
||||||
|
font-family: consolas, courier, monospace;
|
||||||
|
font-size: 90%;
|
||||||
|
overflow: hidden;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.cptHints article {
|
.cptHints article {
|
||||||
margin-left: 25px;
|
margin-left: 25px;
|
||||||
|
|
@ -96,14 +119,6 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Layout */
|
|
||||||
.cptOutput {
|
|
||||||
background: @bg; color: @text;
|
|
||||||
font-family: @fonts; font-size: 90%;
|
|
||||||
overflow: hidden;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The input area */
|
/* The input area */
|
||||||
.cptInput {
|
.cptInput {
|
||||||
border-top: 1px solid @border_bg;
|
border-top: 1px solid @border_bg;
|
||||||
|
|
@ -140,42 +155,3 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.cptRowIn {
|
|
||||||
display: box; display: -moz-box; display: -webkit-box;
|
|
||||||
box-orient: horizontal; -moz-box-orient: horizontal; -webkit-box-orient: horizontal;
|
|
||||||
box-align: center; -moz-box-align: center; -webkit-box-align: center;
|
|
||||||
color: @text;
|
|
||||||
background-color: @input_bg;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.cptRowIn > * { padding-left: 2px; padding-right: 2px; }
|
|
||||||
.cptRowIn > img { cursor: pointer; }
|
|
||||||
.cptHover { display: none; }
|
|
||||||
.cptRowIn:hover > .cptHover { display: block; }
|
|
||||||
.cptRowIn:hover > .cptHover.cptHidden { display: none; }
|
|
||||||
.cptOutTyped {
|
|
||||||
box-flex: 1; -moz-box-flex: 1; -webkit-box-flex: 1;
|
|
||||||
font-weight: bold; color: @hi_text; font-size: 120%;
|
|
||||||
}
|
|
||||||
.cptRowOutput { padding-left: 10px; line-height: 1.2em; }
|
|
||||||
.cptRowOutput strong,
|
|
||||||
.cptRowOutput b,
|
|
||||||
.cptRowOutput th,
|
|
||||||
.cptRowOutput h1,
|
|
||||||
.cptRowOutput h2,
|
|
||||||
.cptRowOutput h3 { color: @hi_text; }
|
|
||||||
.cptRowOutput a { font-weight: bold; color: @link_text; text-decoration: none; }
|
|
||||||
.cptRowOutput a: hover { text-decoration: underline; cursor: pointer; }
|
|
||||||
.cptRowOutput input[type=password],
|
|
||||||
.cptRowOutput input[type=text],
|
|
||||||
.cptRowOutput textarea {
|
|
||||||
color: @hi_text; font-size: 120%;
|
|
||||||
background: transparent; padding: 3px;
|
|
||||||
border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px;
|
|
||||||
}
|
|
||||||
.cptRowOutput table,
|
|
||||||
.cptRowOutput td,
|
|
||||||
.cptRowOutput th { border: 0; padding: 0 2px; }
|
|
||||||
.cptRowOutput .right { text-align: right; }
|
|
||||||
|
|
|
||||||
|
|
@ -37,18 +37,18 @@
|
||||||
|
|
||||||
define(function(require, exports, module) {
|
define(function(require, exports, module) {
|
||||||
|
|
||||||
|
|
||||||
var editorCss = require("text!cockpit/ui/plain.css");
|
var editorCss = require("text!cockpit/ui/plain.css");
|
||||||
var dom = require("pilot/dom").dom;
|
var dom = require("pilot/dom").dom;
|
||||||
dom.importCssString(editorCss);
|
dom.importCssString(editorCss);
|
||||||
|
|
||||||
var CliRequisition = require('cockpit/cli').CliRequisition;
|
|
||||||
var Hint = require('cockpit/cli').Hint;
|
|
||||||
var keyutil = require('pilot/keyboard/keyutil');
|
|
||||||
|
|
||||||
var plainRow = require("text!cockpit/ui/plainRow.html");
|
|
||||||
var Templater = require("pilot/domtemplate").Templater;
|
|
||||||
var canon = require("pilot/canon");
|
var canon = require("pilot/canon");
|
||||||
var Status = require('pilot/types').Status;
|
var Status = require('pilot/types').Status;
|
||||||
|
var keyutil = require('pilot/keyboard/keyutil');
|
||||||
|
|
||||||
|
var CliRequisition = require('cockpit/cli').CliRequisition;
|
||||||
|
var Hint = require('cockpit/cli').Hint;
|
||||||
|
var RequestView = require('cockpit/ui/requestView').RequestView;
|
||||||
|
|
||||||
var NO_HINT = new Hint(Status.VALID, '', 0, 0);
|
var NO_HINT = new Hint(Status.VALID, '', 0, 0);
|
||||||
|
|
||||||
|
|
@ -61,19 +61,19 @@ var NO_HINT = new Hint(Status.VALID, '', 0, 0);
|
||||||
* 2. Attach a set of events so the command line works
|
* 2. Attach a set of events so the command line works
|
||||||
*/
|
*/
|
||||||
exports.startup = function(data, reason) {
|
exports.startup = function(data, reason) {
|
||||||
var plainUi = new PlainUi(data);
|
var plainUi = new CliView(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to handle the simplest UI implementation
|
* A class to handle the simplest UI implementation
|
||||||
*/
|
*/
|
||||||
function PlainUi(data) {
|
function CliView(data) {
|
||||||
this.doc = document;
|
this.doc = document;
|
||||||
this.win = this.doc.defaultView;
|
this.win = this.doc.defaultView;
|
||||||
|
|
||||||
// TODO: we should have a better way to specify command lines???
|
// TODO: we should have a better way to specify command lines???
|
||||||
this.input = this.doc.getElementById('cockpit');
|
this.element = this.doc.getElementById('cockpit');
|
||||||
if (!this.input) {
|
if (!this.element) {
|
||||||
console.log('No element with an id of cockpit. Bailing on plain cli');
|
console.log('No element with an id of cockpit. Bailing on plain cli');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -90,26 +90,22 @@ function PlainUi(data) {
|
||||||
|
|
||||||
this.createElements();
|
this.createElements();
|
||||||
}
|
}
|
||||||
PlainUi.prototype = {
|
CliView.prototype = {
|
||||||
/**
|
/**
|
||||||
* Create divs for templates, completion, hints and output
|
* Create divs for completion, hints and output
|
||||||
*/
|
*/
|
||||||
createElements: function() {
|
createElements: function() {
|
||||||
this.templates = this.doc.createElement('div');
|
|
||||||
this.templates.innerHTML = plainRow;
|
|
||||||
this.row = this.templates.firstChild;
|
|
||||||
|
|
||||||
this.completer = this.doc.createElement('div');
|
this.completer = this.doc.createElement('div');
|
||||||
this.completer.className = 'cptCompletion VALID';
|
this.completer.className = 'cptCompletion VALID';
|
||||||
this.input.parentNode.insertBefore(this.completer, this.input);
|
this.element.parentNode.insertBefore(this.completer, this.element);
|
||||||
|
|
||||||
this.hinter = this.doc.createElement('div');
|
this.hinter = this.doc.createElement('div');
|
||||||
this.hinter.className = 'cptHints';
|
this.hinter.className = 'cptHints';
|
||||||
this.input.parentNode.insertBefore(this.hinter, this.input);
|
this.element.parentNode.insertBefore(this.hinter, this.element);
|
||||||
|
|
||||||
this.output = this.doc.createElement('div');
|
this.output = this.doc.createElement('div');
|
||||||
this.output.className = 'cptOutput';
|
this.output.className = 'cptOutput';
|
||||||
this.input.parentNode.insertBefore(this.output, this.input);
|
this.element.parentNode.insertBefore(this.output, this.element);
|
||||||
|
|
||||||
this.win.addEventListener('resize', this.resizer.bind(this), false);
|
this.win.addEventListener('resize', this.resizer.bind(this), false);
|
||||||
this.resizer();
|
this.resizer();
|
||||||
|
|
@ -119,9 +115,9 @@ PlainUi.prototype = {
|
||||||
this.showHint.addEventListener('change', this.hintShower.bind(this));
|
this.showHint.addEventListener('change', this.hintShower.bind(this));
|
||||||
this.hintShower();
|
this.hintShower();
|
||||||
|
|
||||||
keyutil.addKeyDownListener(this.input, this.onKeyDown.bind(this));
|
keyutil.addKeyDownListener(this.element, this.onKeyDown.bind(this));
|
||||||
this.input.addEventListener('mouseup', this.onMouseUp.bind(this), false);
|
this.element.addEventListener('mouseup', this.onMouseUp.bind(this), false);
|
||||||
this.input.addEventListener('keyup', this.onKeyUp.bind(this), true);
|
this.element.addEventListener('keyup', this.onKeyUp.bind(this), true);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -131,15 +127,15 @@ PlainUi.prototype = {
|
||||||
resizer: function() {
|
resizer: function() {
|
||||||
var top, height, left, width;
|
var top, height, left, width;
|
||||||
|
|
||||||
if (this.input.getClientRects) {
|
if (this.element.getClientRects) {
|
||||||
var rect = this.input.getClientRects()[0];
|
var rect = this.element.getClientRects()[0];
|
||||||
top = rect.top;
|
top = rect.top;
|
||||||
height = rect.height;
|
height = rect.height;
|
||||||
left = rect.left;
|
left = rect.left;
|
||||||
width = rect.width;
|
width = rect.width;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var style = this.win.getComputedStyle(this.input, null);
|
var style = this.win.getComputedStyle(this.element, null);
|
||||||
top = parseInt(style.getPropertyValue('top'), 10);
|
top = parseInt(style.getPropertyValue('top'), 10);
|
||||||
height = parseInt(style.getPropertyValue('height'), 10);
|
height = parseInt(style.getPropertyValue('height'), 10);
|
||||||
left = parseInt(style.getPropertyValue('left'), 10);
|
left = parseInt(style.getPropertyValue('left'), 10);
|
||||||
|
|
@ -156,25 +152,42 @@ PlainUi.prototype = {
|
||||||
|
|
||||||
this.output.style.bottom = (this.win.innerHeight - top) + 'px';
|
this.output.style.bottom = (this.win.innerHeight - top) + 'px';
|
||||||
this.output.style.left = left + 'px';
|
this.output.style.left = left + 'px';
|
||||||
this.output.style.width = width + 'px';
|
this.output.style.width = (width - 60) + 'px';
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the display of executed commands
|
* Update the display of executed commands
|
||||||
*/
|
*/
|
||||||
showOutput: function(ev) {
|
showOutput: function(ev) {
|
||||||
|
var requestOutput = new RequestView(ev.request, this);
|
||||||
|
|
||||||
|
/*
|
||||||
// TODO: be less brutal in how we update this
|
// TODO: be less brutal in how we update this
|
||||||
this.output.innerHTML = '';
|
this.output.innerHTML = '';
|
||||||
|
|
||||||
|
new RequestView(ev.request, this);
|
||||||
ev.requests.forEach(function(request) {
|
ev.requests.forEach(function(request) {
|
||||||
request.outputs.forEach(function(out) {
|
// this.duration.innerHTML = this.request.duration ?
|
||||||
if (typeof out === 'string') {
|
// 'completed in ' + (this.request.duration / 1000) + ' sec ' :
|
||||||
this.output.appendChild(this.doc.createTextNode(out));
|
// '';
|
||||||
|
// this.typed.innerHTML = this.request.typed;
|
||||||
|
|
||||||
|
request.outputs.forEach(function(output) {
|
||||||
|
var node;
|
||||||
|
if (typeof output == 'string') {
|
||||||
|
node = document.createElement('p');
|
||||||
|
node.innerHTML = output;
|
||||||
} else {
|
} else {
|
||||||
this.output.appendChild(out);
|
node = output;
|
||||||
}
|
}
|
||||||
|
this.output.appendChild(node);
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
|
// this.cliView.scrollToBottom();
|
||||||
|
// util.setClass(this.output, 'cmd_error', this.request.error);
|
||||||
|
// this.throb.style.display = this.request.completed ? 'none' : 'block';
|
||||||
}, this);
|
}, this);
|
||||||
|
*/
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -219,27 +232,26 @@ PlainUi.prototype = {
|
||||||
|
|
||||||
if (ev.keyCode === keyutil.KeyHelper.KEY.RETURN) {
|
if (ev.keyCode === keyutil.KeyHelper.KEY.RETURN) {
|
||||||
if (this.worstHint && this.worstHint.status !== Status.VALID) {
|
if (this.worstHint && this.worstHint.status !== Status.VALID) {
|
||||||
this.input.selectionStart = this.worstHint.start;
|
this.element.selectionStart = this.worstHint.start;
|
||||||
this.input.selectionEnd = this.worstHint.end;
|
this.element.selectionEnd = this.worstHint.end;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.cli.exec();
|
this.cli.exec();
|
||||||
this.input.value = '';
|
this.element.value = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ev.keyCode === keyutil.KeyHelper.KEY.TAB) {
|
if (ev.keyCode === keyutil.KeyHelper.KEY.TAB && this.shownHint &&
|
||||||
if (this.shownHint && this.shownHint.predictions && this.shownHint.predictions.length > 0) {
|
this.shownHint.predictions && this.shownHint.predictions.length > 0) {
|
||||||
var prefix = this.input.value.substring(0, this.shownHint.start);
|
var prefix = this.element.value.substring(0, this.shownHint.start);
|
||||||
var suffix = this.input.value.substring(this.shownHint.end);
|
var suffix = this.element.value.substring(this.shownHint.end);
|
||||||
var insert = this.shownHint.predictions[0];
|
var insert = this.shownHint.predictions[0];
|
||||||
insert = typeof insert === 'string' ? insert : insert.name;
|
insert = typeof insert === 'string' ? insert : insert.name;
|
||||||
this.input.value = prefix + insert + suffix;
|
this.element.value = prefix + insert + suffix;
|
||||||
// Fix the cursor.
|
// Fix the cursor.
|
||||||
var insertEnd = (prefix + insert).length;
|
var insertEnd = (prefix + insert).length;
|
||||||
this.input.selectionStart = insertEnd;
|
this.element.selectionStart = insertEnd;
|
||||||
this.input.selectionEnd = insertEnd;
|
this.element.selectionEnd = insertEnd;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.update();
|
this.update();
|
||||||
|
|
@ -260,10 +272,10 @@ PlainUi.prototype = {
|
||||||
*/
|
*/
|
||||||
update: function() {
|
update: function() {
|
||||||
this.cli.update({
|
this.cli.update({
|
||||||
typed: this.input.value,
|
typed: this.element.value,
|
||||||
cursor: {
|
cursor: {
|
||||||
start: this.input.selectionStart,
|
start: this.element.selectionStart,
|
||||||
end: this.input.selectionEnd
|
end: this.element.selectionEnd
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -288,10 +300,10 @@ PlainUi.prototype = {
|
||||||
|
|
||||||
// Create a marked up version of the input
|
// Create a marked up version of the input
|
||||||
var highlightedInput = '';
|
var highlightedInput = '';
|
||||||
if (this.input.value.length > 0) {
|
if (this.element.value.length > 0) {
|
||||||
// 'scores' is an array which tells us what chars are errors
|
// 'scores' is an array which tells us what chars are errors
|
||||||
// Initialize with everything VALID
|
// Initialize with everything VALID
|
||||||
var scores = this.input.value.split('').map(function(char) {
|
var scores = this.element.value.split('').map(function(char) {
|
||||||
return Status.VALID;
|
return Status.VALID;
|
||||||
});
|
});
|
||||||
// For all chars in all hints, check and upgrade the score
|
// For all chars in all hints, check and upgrade the score
|
||||||
|
|
@ -310,9 +322,9 @@ PlainUi.prototype = {
|
||||||
highlightedInput += '<span class=' + scores[i].toString() + '>';
|
highlightedInput += '<span class=' + scores[i].toString() + '>';
|
||||||
lastStatus = scores[i];
|
lastStatus = scores[i];
|
||||||
}
|
}
|
||||||
highlightedInput += this.input.value[i];
|
highlightedInput += this.element.value[i];
|
||||||
i++;
|
i++;
|
||||||
if (i === this.input.value.length) {
|
if (i === this.element.value.length) {
|
||||||
highlightedInput += '</span>';
|
highlightedInput += '</span>';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -351,7 +363,7 @@ PlainUi.prototype = {
|
||||||
// dom.addCssClass(input, status.toString());
|
// dom.addCssClass(input, status.toString());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
exports.PlainUi = PlainUi;
|
exports.CliView = CliView;
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<!-- The input area, with fixed height -->
|
|
||||||
<div id=cptInput class=cptInput>
|
|
||||||
<!-- The prompt -->
|
|
||||||
<div class="cptPrompt cptGt"><span class="cptBrackets">{ }</span> ></div>
|
|
||||||
<!-- Where you type commands -->
|
|
||||||
<div class="cptKbd cptStack">
|
|
||||||
<div class=cptCompletion save="${cliInputView._completer}"></div>
|
|
||||||
<input class=cptCliInput save="${cliInputView._inputer}"/>
|
|
||||||
</div>
|
|
||||||
<!-- Help as you type -->
|
|
||||||
<div id=cptHints class=cptHints>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class=cptRow>
|
|
||||||
<!-- The div for the input (i.e. what was typed) -->
|
|
||||||
<div class="cptRowIn" save="${actions.rowin}"
|
|
||||||
onclick="${actions.copyToInput}"
|
|
||||||
ondblclick="${actions.executeRequest}">
|
|
||||||
|
|
||||||
<!-- What the user actually typed -->
|
|
||||||
<div class="cptGt">> </div>
|
|
||||||
<div class="cptOutTyped" save="${actions.typed}"></div>
|
|
||||||
|
|
||||||
<!-- The extra details that appear on hover -->
|
|
||||||
<div class=cptHover save="${actions.duration}"></div>
|
|
||||||
<img class=cptHover onclick="${actions.hideOutput}" save="${actions.hide}"
|
|
||||||
alt="Hide command output" _src="${imagePath}/minus.png"/>
|
|
||||||
<img class="cptHover cptHidden" onclick="${actions.showOutput}" save="${actions.show}"
|
|
||||||
alt="Show command output" _src="${imagePath}/plus.png"/>
|
|
||||||
<img class=cptHover onclick="${actions.remove}"
|
|
||||||
alt="Remove this command from the history" _src="${imagePath}/closer.png"/>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- The div for the command output -->
|
|
||||||
<div class="cptRowOut" save="${actions.rowout}">
|
|
||||||
<div class="cptRowOutput" save="${actions.output}"></div>
|
|
||||||
<img src="${imagePath}/throbber.gif" save="${actions.throb}"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
38
plugins/cockpit/lib/ui/requestView.css
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
.cptRowIn {
|
||||||
|
display: box; display: -moz-box; display: -webkit-box;
|
||||||
|
box-orient: horizontal; -moz-box-orient: horizontal; -webkit-box-orient: horizontal;
|
||||||
|
box-align: center; -moz-box-align: center; -webkit-box-align: center;
|
||||||
|
color: #333;
|
||||||
|
background-color: @input_bg;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.cptRowIn > * { padding-left: 2px; padding-right: 2px; }
|
||||||
|
.cptRowIn > img { cursor: pointer; }
|
||||||
|
.cptHover { display: none; }
|
||||||
|
.cptRowIn:hover > .cptHover { display: block; }
|
||||||
|
.cptRowIn:hover > .cptHover.cptHidden { display: none; }
|
||||||
|
.cptOutTyped {
|
||||||
|
box-flex: 1; -moz-box-flex: 1; -webkit-box-flex: 1;
|
||||||
|
font-weight: bold; color: #000; font-size: 120%;
|
||||||
|
}
|
||||||
|
.cptRowOutput { padding-left: 10px; line-height: 1.2em; }
|
||||||
|
.cptRowOutput strong,
|
||||||
|
.cptRowOutput b,
|
||||||
|
.cptRowOutput th,
|
||||||
|
.cptRowOutput h1,
|
||||||
|
.cptRowOutput h2,
|
||||||
|
.cptRowOutput h3 { color: #000; }
|
||||||
|
.cptRowOutput a { font-weight: bold; color: #666; text-decoration: none; }
|
||||||
|
.cptRowOutput a: hover { text-decoration: underline; cursor: pointer; }
|
||||||
|
.cptRowOutput input[type=password],
|
||||||
|
.cptRowOutput input[type=text],
|
||||||
|
.cptRowOutput textarea {
|
||||||
|
color: #000; font-size: 120%;
|
||||||
|
background: transparent; padding: 3px;
|
||||||
|
border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px;
|
||||||
|
}
|
||||||
|
.cptRowOutput table,
|
||||||
|
.cptRowOutput td,
|
||||||
|
.cptRowOutput th { border: 0; padding: 0 2px; }
|
||||||
|
.cptRowOutput .right { text-align: right; }
|
||||||
28
plugins/cockpit/lib/ui/requestView.html
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
|
||||||
|
<div class=cptRow>
|
||||||
|
<!-- The div for the input (i.e. what was typed) -->
|
||||||
|
<div class="cptRowIn" save="${rowin}"
|
||||||
|
onclick="${copyToInput}"
|
||||||
|
ondblclick="${executeRequest}">
|
||||||
|
|
||||||
|
<!-- What the user actually typed -->
|
||||||
|
<div class="cptGt">> </div>
|
||||||
|
<div class="cptOutTyped">${request.typed}</div>
|
||||||
|
|
||||||
|
<!-- The extra details that appear on hover -->
|
||||||
|
<div class=cptHover save="${duration}"></div>
|
||||||
|
<img class=cptHover onclick="${hideOutput}" save="${hide}"
|
||||||
|
alt="Hide command output" _src="${imagePath}/minus.png"/>
|
||||||
|
<img class="cptHover cptHidden" onclick="${showOutput}" save="${show}"
|
||||||
|
alt="Show command output" _src="${imagePath}/plus.png"/>
|
||||||
|
<img class=cptHover onclick="${remove}"
|
||||||
|
alt="Remove this command from the history" _src="${imagePath}/closer.png"/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- The div for the command output -->
|
||||||
|
<div class="cptRowOut" save="${rowout}">
|
||||||
|
<div class="cptRowOutput" save="${output}"></div>
|
||||||
|
<img _src="${imagePath}/throbber.gif" save="${throb}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
152
plugins/cockpit/lib/ui/requestView.js
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Skywriter.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Mozilla.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Joe Walker (jwalker@mozilla.com)
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
define(function(require, exports, module) {
|
||||||
|
|
||||||
|
|
||||||
|
var util = require('pilot/util');
|
||||||
|
|
||||||
|
var editorCss = require("text!cockpit/ui/requestView.css");
|
||||||
|
var dom = require("pilot/dom").dom;
|
||||||
|
dom.importCssString(editorCss);
|
||||||
|
|
||||||
|
var plainRow = require("text!cockpit/ui/requestView.html");
|
||||||
|
var Templater = require("pilot/domtemplate").Templater;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pull the HTML into the DOM, but don't add it to the document
|
||||||
|
*/
|
||||||
|
var templates = document.createElement('div');
|
||||||
|
templates.innerHTML = plainRow;
|
||||||
|
var row = templates.querySelector('.cptRow');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a row to the CLI output display
|
||||||
|
*/
|
||||||
|
function RequestView(request, cliView) {
|
||||||
|
this.request = request;
|
||||||
|
this.cliView = cliView;
|
||||||
|
|
||||||
|
this.imagePath = '/plugins/ace/pluging/cockpit/ui';
|
||||||
|
|
||||||
|
// Elements attached to this by the templater. For info only
|
||||||
|
this.rowin = null;
|
||||||
|
this.rowout = null;
|
||||||
|
this.output = null;
|
||||||
|
this.hide = null;
|
||||||
|
this.show = null;
|
||||||
|
this.duration = null;
|
||||||
|
this.throb = null;
|
||||||
|
|
||||||
|
new Templater().processNode(row.cloneNode(true), this);
|
||||||
|
|
||||||
|
this.cliView.output.appendChild(this.rowin);
|
||||||
|
this.cliView.output.appendChild(this.rowout);
|
||||||
|
|
||||||
|
this.request.addEventListener('output', this.onRequestChange.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
RequestView.prototype = {
|
||||||
|
/**
|
||||||
|
* A single click on an invocation line in the console copies the command to
|
||||||
|
* the command line
|
||||||
|
*/
|
||||||
|
copyToInput: function() {
|
||||||
|
this.cliView.input.value = this.request.typed;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A double click on an invocation line in the console executes the command
|
||||||
|
*/
|
||||||
|
executeRequest: function(ev) {
|
||||||
|
this.cliView.cli.update({
|
||||||
|
typed: this.request.typed,
|
||||||
|
cursor: { start:0, end:0 }
|
||||||
|
});
|
||||||
|
this.cliView.cli.exec();
|
||||||
|
},
|
||||||
|
|
||||||
|
hideOutput: function(ev) {
|
||||||
|
this.output.style.display = 'none';
|
||||||
|
util.addClass(this.hide, 'cmd_hidden');
|
||||||
|
util.removeClass(this.show, 'cmd_hidden');
|
||||||
|
|
||||||
|
ev.stopPropagation();
|
||||||
|
},
|
||||||
|
|
||||||
|
showOutput: function(ev) {
|
||||||
|
this.output.style.display = 'block';
|
||||||
|
util.removeClass(this.hide, 'cmd_hidden');
|
||||||
|
util.addClass(this.show, 'cmd_hidden');
|
||||||
|
|
||||||
|
ev.stopPropagation();
|
||||||
|
},
|
||||||
|
|
||||||
|
remove: function(ev) {
|
||||||
|
this.cliView.output.removeChild(this.rowin);
|
||||||
|
this.cliView.output.removeChild(this.rowout);
|
||||||
|
ev.stopPropagation();
|
||||||
|
},
|
||||||
|
|
||||||
|
onRequestChange: function(ev) {
|
||||||
|
this.duration.innerHTML = this.request.duration ?
|
||||||
|
'completed in ' + (this.request.duration / 1000) + ' sec ' :
|
||||||
|
'';
|
||||||
|
|
||||||
|
this.output.innerHTML = '';
|
||||||
|
this.request.outputs.forEach(function(output) {
|
||||||
|
var node;
|
||||||
|
if (typeof output == 'string') {
|
||||||
|
node = document.createElement('p');
|
||||||
|
node.innerHTML = output;
|
||||||
|
} else {
|
||||||
|
node = output;
|
||||||
|
}
|
||||||
|
this.output.appendChild(node);
|
||||||
|
}, this);
|
||||||
|
// TODO: Fix this
|
||||||
|
// this.cliView.scrollToBottom();
|
||||||
|
|
||||||
|
util.setClass(this.output, 'cmd_error', this.request.error);
|
||||||
|
|
||||||
|
this.throb.style.display = this.request.completed ? 'none' : 'block';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.RequestView = RequestView;
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -160,7 +160,8 @@ function getCommandNames() {
|
||||||
* everything it needs to about the command params
|
* everything it needs to about the command params
|
||||||
* @param command Either a command, or the name of one
|
* @param command Either a command, or the name of one
|
||||||
*/
|
*/
|
||||||
function exec(command, args) {
|
function exec(command, args, typed) {
|
||||||
|
// TODO: Use requisition.toString rather than 'typed'
|
||||||
if (typeof command === 'string') {
|
if (typeof command === 'string') {
|
||||||
command = commands[command];
|
command = commands[command];
|
||||||
}
|
}
|
||||||
|
|
@ -171,7 +172,12 @@ function exec(command, args) {
|
||||||
|
|
||||||
// TODO: Ugg. really?
|
// TODO: Ugg. really?
|
||||||
env.selection = env.editor.getSelection();
|
env.selection = env.editor.getSelection();
|
||||||
var request = new Request();
|
|
||||||
|
var request = new Request({
|
||||||
|
command: command,
|
||||||
|
args: args,
|
||||||
|
typed: typed
|
||||||
|
});
|
||||||
command.exec(env, args || {}, request);
|
command.exec(env, args || {}, request);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
@ -216,21 +222,6 @@ var requests = [];
|
||||||
*/
|
*/
|
||||||
var maxRequestLength = 100;
|
var maxRequestLength = 100;
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by Request instances when some output (or a cell to async() happens)
|
|
||||||
*/
|
|
||||||
function addRequestOutput(request) {
|
|
||||||
requests.push(request);
|
|
||||||
// This could probably be optimized with some maths, but 99.99% of the
|
|
||||||
// time we will only be off by one, and I'm feeling lazy.
|
|
||||||
while (requests.length > maxRequestLength) {
|
|
||||||
requests.shiftObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
exports._dispatchEvent('output', { requests: requests });
|
|
||||||
};
|
|
||||||
exports.addRequestOutput = addRequestOutput;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To create an invocation, you need to do something like this (all the ctor
|
* To create an invocation, you need to do something like this (all the ctor
|
||||||
* args are optional):
|
* args are optional):
|
||||||
|
|
@ -249,7 +240,6 @@ function Request(options) {
|
||||||
|
|
||||||
// Will be used in the keyboard case and the cli case
|
// Will be used in the keyboard case and the cli case
|
||||||
this.command = options.command;
|
this.command = options.command;
|
||||||
this.commandExt = options.commandExt;
|
|
||||||
|
|
||||||
// Will be used only in the cli case
|
// Will be used only in the cli case
|
||||||
this.args = options.args;
|
this.args = options.args;
|
||||||
|
|
@ -274,7 +264,14 @@ Request.prototype._beginOutput = function() {
|
||||||
this._begunOutput = true;
|
this._begunOutput = true;
|
||||||
this.outputs = [];
|
this.outputs = [];
|
||||||
|
|
||||||
exports.addRequestOutput(this);
|
requests.push(this);
|
||||||
|
// This could probably be optimized with some maths, but 99.99% of the
|
||||||
|
// time we will only be off by one, and I'm feeling lazy.
|
||||||
|
while (requests.length > maxRequestLength) {
|
||||||
|
requests.shiftObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
exports._dispatchEvent('output', { requests: requests, request: this });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -311,7 +308,7 @@ Request.prototype.output = function(content) {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.outputs.push(content);
|
this.outputs.push(content);
|
||||||
this._dispatchEvent('changed', {});
|
this._dispatchEvent('output', {});
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
@ -329,7 +326,7 @@ Request.prototype.done = function(content) {
|
||||||
this.output(content);
|
this.output(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._dispatchEvent('changed', {});
|
this._dispatchEvent('output', {});
|
||||||
};
|
};
|
||||||
exports.Request = Request;
|
exports.Request = Request;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,19 +59,15 @@ var setCommandSpec = {
|
||||||
var html;
|
var html;
|
||||||
if (!args.setting) {
|
if (!args.setting) {
|
||||||
// 'set' by itself lists all the settings
|
// 'set' by itself lists all the settings
|
||||||
var settingsList = env.settings._list();
|
var names = env.settings.getSettingNames();
|
||||||
html = '';
|
html = '';
|
||||||
// first sort the settingsList based on the name
|
// first sort the settingsList based on the name
|
||||||
settingsList.sort(function(a, b) {
|
names.sort(function(name1, name2) {
|
||||||
if (a.name < b.name) {
|
return name1.localeCompare(name2);
|
||||||
return -1;
|
|
||||||
} else if (a.name == b.name) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
settingsList.forEach(function(setting) {
|
|
||||||
|
names.forEach(function(name) {
|
||||||
|
var setting = env.settings.getSetting(name);
|
||||||
var url = 'https://wiki.mozilla.org/Labs/Skywriter/Settings#' +
|
var url = 'https://wiki.mozilla.org/Labs/Skywriter/Settings#' +
|
||||||
setting.name;
|
setting.name;
|
||||||
html += '<a class="setting" href="' + url +
|
html += '<a class="setting" href="' + url +
|
||||||
|
|
|
||||||
|
|
@ -398,9 +398,7 @@ Templater.prototype.logError = function(message) {
|
||||||
console.log(message);
|
console.log(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.exports) {
|
|
||||||
exports.Templater = Templater;
|
exports.Templater = Templater;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||