summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/codeq/console.js159
1 files changed, 73 insertions, 86 deletions
diff --git a/js/codeq/console.js b/js/codeq/console.js
index ebf09cc..20f3a90 100644
--- a/js/codeq/console.js
+++ b/js/codeq/console.js
@@ -176,70 +176,27 @@
currentHistoryIndex = -1,
instanceNumber = instanceCounter++, // unique instace number, to be used with stuff tied to this instance, e.g.: jqElt events, life-cycle debug output
- renderSpan = function (lineDescriptor, startCol, length) {
+ renderLine = function (lineDescriptor) {
var jqLine = lineDescriptor.jqLine,
content = lineDescriptor.content,
- classes = lineDescriptor.classNames,
- endCol = startCol + length,
- N = classes ? classes.length : 0,
+ classes = lineDescriptor.classNames || [],
+ cursor = currentRow == lineDescriptor.row ? currentCol : null,
+ startCol = 0,
i = 0,
spans = [], // what to render, items are of the form {'content': string, 'cssClass': string}
- entry, classSpan, jq, span, s, prefixDelta, suffixDelta, e;
- // seek out the first css class
- while (i < N) {
- entry = classes[i];
- if (((entry.start + entry.length) > startCol) && (entry.start < endCol)) break;
- i++;
- }
- if (i < N) {
- // render the first span
- e = entry.start + entry.length; // end column of this css class
- prefixDelta = entry.start < startCol ? startCol - entry.start : 0;
- suffixDelta = e > endCol ? e - endCol : 0;
- classSpan = entry.length - prefixDelta - suffixDelta;
- span = {'content': content.substr(startCol, classSpan), 'cssClass': entry.name};
- spans.push(span);
- startCol += classSpan;
- i++;
- // render the rest
- while ((startCol < endCol) && (i < N)) {
- entry = classes[i];
- e = entry.start + entry.length; // end column of this css class
- prefixDelta = entry.start < startCol ? startCol - entry.start : 0;
- suffixDelta = e > endCol ? e - endCol : 0;
- classSpan = entry.length - prefixDelta - suffixDelta;
- s = content.substr(startCol, classSpan);
- if (entry.name === span.cssClass) {
- span.content += s; // join content where the class is the same
+ entry, jq, e, beforeCursor, afterCursor, name,
+ addOrMergeSpan = function (content, className) {
+ if (spans.length > 0 && className === spans[spans.length-1].cssClass) {
+ // join content to previous span where the class is the same
+ spans[spans.length-1].content += content;
}
else {
- span = {'content': s, 'cssClass': entry.name};
- spans.push(span);
+ // add a new span for a new class
+ spans.push({'content': content, 'cssClass': className});
}
- startCol += classSpan;
- i++;
- }
- }
- // render any leftover
- if (startCol < endCol) {
- entry = makeClassDescriptor('', startCol, endCol - startCol);
- spans.push({'content': content.substring(startCol, endCol), 'cssClass': ''});
- }
- // render spans
- for (i = 0; i < spans.length; i++) {
- span = spans[i];
- jq = $('<span class="cq-con-text ' + span.cssClass + '"></span>');
- jqLine.append(jq);
- jq.text(span.content);
- }
- return entry; // return the last entry used
- },
-
- renderLine = function (lineDescriptor) {
- var jqLine = lineDescriptor.jqLine,
- content = lineDescriptor.content,
- jqCursor, classDescriptor;
+ };
+ // get or create line
if (!jqLine) {
jqLine = $('<pre class="cq-con-line"></pre>');
if (lineDescriptor.row == 0) {
@@ -258,33 +215,47 @@
jqLine.empty();
}
- if (currentRow == lineDescriptor.row) {
- // mark the cursor in the current line
- if (currentCol >= content.length) {
- // cursor after the last character
- renderSpan(lineDescriptor, 0, content.length);
- jqCursor = $('<span class="cq-con-cursor">&nbsp;</span>');
- jqLine.append(jqCursor);
- }
- else if (currentCol <= 0) {
- // cursor at the first character
- classDescriptor = lineDescriptor.classNames[0] || makeClassDescriptor('', 0, content.length);
- jqCursor = $('<span class="cq-con-cursor ' + classDescriptor.name + '"></span>');
- jqLine.append(jqCursor);
- jqCursor.text(content.charAt(0));
- renderSpan(lineDescriptor, 1, content.length - 1);
+ // create spans
+ while (startCol < content.length) {
+ entry = i < classes.length ? classes[i]
+ : makeClassDescriptor('', startCol, content.length - startCol);
+ e = entry.start + entry.length; // end column of this css class
+ if (cursor !== null && cursor >= entry.start && cursor < e) {
+ // cursor is in this span
+ beforeCursor = content.substr(startCol, cursor - startCol);
+ if (beforeCursor) {
+ addOrMergeSpan(beforeCursor, entry.name);
+ }
+
+ spans.push({'content': content.charAt(cursor), 'cssClass': 'cq-con-cursor ' + entry.name});
+ afterCursor = content.substr(cursor + 1, e - cursor - 1);
+ if (afterCursor) {
+ spans.push({'content': afterCursor, 'cssClass': entry.name});
+ }
}
else {
- // cursor somewhere in between
- classDescriptor = renderSpan(lineDescriptor, 0, currentCol);
- jqCursor = $('<span class="cq-con-cursor ' + classDescriptor.name + '"></span>');
- jqLine.append(jqCursor);
- jqCursor.text(content.charAt(currentCol));
- renderSpan(lineDescriptor, currentCol + 1, content.length - currentCol - 1);
+ // cursor is not in this span
+ addOrMergeSpan(content.substr(startCol, entry.length), entry.name);
}
+ startCol += entry.length;
+ i++;
}
- else {
- renderSpan(lineDescriptor, 0, content.length);
+ // add a fake space if cursor is at end of line
+ if (cursor !== null && cursor >= content.length) {
+ name = entry ? entry.name : '';
+ spans.push({'content': ' ', 'cssClass': 'cq-con-cursor ' + name});
+ }
+
+ // render spans
+ for (i = 0; i < spans.length; i++) {
+ jq = $('<span class="cq-con-text ' + spans[i].cssClass + '"></span>');
+ jqLine.append(jq);
+ jq.text(spans[i].content);
+ }
+
+ // (re-)render cursor if it is in the current line
+ if (cursor !== null) {
+ renderCursor();
}
},
@@ -891,8 +862,27 @@
clipboardPasteInProgress = false, // whether the previous keydown was a CTRL+V or shift+insert
aKeyIsDown = false, // whether a key is currently pressed: if it's not and there is input, then we got a paste via mouse
+
cursorBlinkRate = (options && options.cursorBlinkRate) || 750, // default: 750 ms
blinkTimer = null,
+ renderCursor = function () {
+ if (blinkTimer) {
+ clearInterval(blinkTimer);
+ blinkTimer = null;
+ }
+ if (jqInput.is(':focus')) {
+ jqContent.find('.cq-con-cursor').addClass('inverted');
+ if ((typeof cursorBlinkRate === 'number') && (cursorBlinkRate >= 50)) { // have some sense of sanity
+ blinkTimer = setInterval(function () {
+ jqContent.find('.cq-con-cursor').toggleClass('inverted');
+ }, cursorBlinkRate);
+ }
+ }
+ else {
+ jqContent.find('.cq-con-cursor').removeClass('inverted');
+ }
+ },
+
i, j, a, b, c;
// copy default key handlers
@@ -956,6 +946,10 @@
aKeyIsDown = false;
});
+ jqInput.on('blur focus', function () {
+ renderCursor();
+ });
+
if ('oninput' in jqInput[0]) {
// the element supports input events, use them in preference to keypress events
jqInput.on('input', function (evt) {
@@ -982,13 +976,6 @@
});
}
- // start the cursor blinking if so instructed
- if ((typeof cursorBlinkRate === 'number') && (cursorBlinkRate >= 50)) { // have some sense of sanity
- blinkTimer = setInterval(function () {
- jqContent.find('.cq-con-cursor').toggleClass('inverted');
- }, cursorBlinkRate);
- }
-
// emit greeting if provided
if (options && options.greeting) {
lines.push({content: options.greeting, className: 'greeting'});