Created
July 29, 2013 20:41
-
-
Save lavelle/6107625 to your computer and use it in GitHub Desktop.
jQuery console diff
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/jquery.console.js b/../doppio/vendor/jquery.console.js | |
index 10e893e..7db1f1c 100644 | |
--- a/jquery.console.js | |
+++ b/../doppio/vendor/jquery.console.js | |
@@ -38,9 +38,12 @@ | |
// Google Chrome 5.0.375.55 (Mac) | |
(function($){ | |
- var isWebkit = !!~navigator.userAgent.indexOf(' AppleWebKit/'); | |
- | |
$.fn.console = function(config){ | |
+ if (config === undefined) config = {}; | |
+ | |
+ // External exports object | |
+ var extern = {}; | |
+ | |
//////////////////////////////////////////////////////////////////////// | |
// Constants | |
// Some are enums, data types, others just for optimisation | |
@@ -55,6 +58,8 @@ | |
40: nextHistory, | |
// backspace | |
8: backDelete, | |
+ // tab | |
+ 9: tabComplete, | |
// delete | |
46: forwardDelete, | |
// end | |
@@ -63,18 +68,16 @@ | |
36: moveToStart, | |
// return | |
13: commandTrigger, | |
- // tab | |
- 18: doNothing, | |
- // tab | |
- 9: doComplete | |
+ // alt | |
+ 18: doNothing | |
}; | |
var ctrlCodes = { | |
// C-a | |
65: moveToStart, | |
- // C-e | |
- 69: moveToEnd, | |
// C-d | |
68: forwardDelete, | |
+ // C-e | |
+ 69: moveToEnd, | |
// C-n | |
78: nextHistory, | |
// C-p | |
@@ -86,9 +89,6 @@ | |
// C-k | |
75: deleteUntilEnd | |
}; | |
- if(config.ctrlCodes) { | |
- $.extend(ctrlCodes, config.ctrlCodes); | |
- } | |
var altCodes = { | |
// M-f | |
70: moveToNextWord, | |
@@ -102,23 +102,33 @@ | |
//////////////////////////////////////////////////////////////////////// | |
// Globals | |
var container = $(this); | |
- var inner = $('<div class="jquery-console-inner"></div>'); | |
+ var inner = $('<pre class="jquery-console-inner"></pre>'); | |
// erjiang: changed this from a text input to a textarea so we | |
// can get pasted newlines | |
var typer = $('<textarea class="jquery-console-typer"></textarea>'); | |
// Prompt | |
var promptBox; | |
var prompt; | |
- var promptLabel = config && config.promptLabel? config.promptLabel : "> "; | |
- var continuedPromptLabel = config && config.continuedPromptLabel? | |
+ extern.promptLabel = config.promptLabel ? config.promptLabel : "> "; | |
+ extern.continuedPromptLabel = config.continuedPromptLabel ? | |
config.continuedPromptLabel : "> "; | |
var column = 0; | |
var promptText = ''; | |
var restoreText = ''; | |
var continuedText = ''; | |
+ | |
// Prompt history stack | |
var history = []; | |
var ringn = 0; | |
+ if (window.localStorage && window.localStorage.history) { | |
+ try { | |
+ history = JSON.parse(localStorage.history); | |
+ } | |
+ catch (e) { | |
+ console.error('Previous history is not a valid JSON object.'); | |
+ } | |
+ } | |
+ | |
// For reasons unknown to The Sword of Michael himself, Opera | |
// triggers and sends a key character when you hit various | |
// keys like PgUp, End, etc. So there is no way of knowing | |
@@ -131,9 +141,8 @@ | |
var acceptInput = true; | |
// When this value is true, the command has been canceled | |
var cancelCommand = false; | |
- | |
- // External exports object | |
- var extern = {}; | |
+ extern.commandHandle = config.commandHandle; | |
+ var lastMsg = null; | |
//////////////////////////////////////////////////////////////////////// | |
// Main entry point | |
@@ -208,19 +217,32 @@ | |
//////////////////////////////////////////////////////////////////////// | |
// Make a new prompt box | |
function newPromptBox() { | |
+ if (typeof extern.onreprompt === 'function') | |
+ extern.onreprompt(); | |
column = 0; | |
promptText = ''; | |
ringn = 0; // Reset the position of the history ring | |
enableInput(); | |
promptBox = $('<div class="jquery-console-prompt-box"></div>'); | |
var label = $('<span class="jquery-console-prompt-label"></span>'); | |
- var labelText = extern.continuedPrompt? continuedPromptLabel : promptLabel; | |
+ var labelText = extern.continuedPrompt ? extern.continuedPromptLabel : | |
+ extern.promptLabel; | |
+ if (lastMsg) { | |
+ var text = lastMsg.text(); | |
+ if (_.last(text) !== '\n') { | |
+ var lines = text.split('\n'); | |
+ labelText = _.last(lines) + labelText; | |
+ lines.length--; | |
+ lastMsg.text(lines.join('\n')); | |
+ } | |
+ } | |
promptBox.append(label.text(labelText).show()); | |
label.html(label.html().replace(' ',' ')); | |
prompt = $('<span class="jquery-console-prompt"></span>'); | |
promptBox.append(prompt); | |
inner.append(promptBox); | |
updatePromptDisplay(); | |
+ lastMsg = null; | |
}; | |
//////////////////////////////////////////////////////////////////////// | |
@@ -228,11 +250,7 @@ | |
container.click(function(){ | |
inner.addClass('jquery-console-focus'); | |
inner.removeClass('jquery-console-nofocus'); | |
- if (isWebkit) { | |
- typer.focusWithoutScrolling(); | |
- } else { | |
- typer.css('position', 'fixed').focus(); | |
- } | |
+ typer.focus(); | |
scrollToBottom(); | |
return false; | |
}); | |
@@ -295,28 +313,24 @@ | |
if (isIgnorableKey(e)) { | |
return false; | |
} | |
- // C-v: don't insert on paste event | |
- if ((e.ctrlKey || e.metaKey) && String.fromCharCode(keyCode).toLowerCase() == 'v') { | |
+ // // C-v: don't insert on paste event | |
+ if (e.ctrlKey && String.fromCharCode(keyCode).toLowerCase() == 'v') { | |
return true; | |
} | |
if (acceptInput && cancelKeyPress != keyCode && keyCode >= 32){ | |
if (cancelKeyPress) return false; | |
- if ( | |
- typeof config.charInsertTrigger == 'undefined' || ( | |
- typeof config.charInsertTrigger == 'function' && | |
- config.charInsertTrigger(keyCode,promptText) | |
- ) | |
- ){ | |
+ if (typeof config.charInsertTrigger == 'undefined' || | |
+ (typeof config.charInsertTrigger == 'function' && | |
+ config.charInsertTrigger(keyCode,promptText))) | |
typer.consoleInsert(keyCode); | |
} | |
- } | |
- if (isWebkit) return false; | |
+ if ($.browser.webkit || $.browser.opera) return false; | |
}); | |
function isIgnorableKey(e) { | |
// for now just filter alt+tab that we receive on some platforms when | |
// user switches windows (goes away from the browser) | |
- return ((e.keyCode == keyCodes.tab || e.keyCode == 192) && e.altKey); | |
+ return ((e.keyCode == 9 || e.keyCode == 192) && e.altKey); | |
}; | |
//////////////////////////////////////////////////////////////////////// | |
@@ -355,6 +369,9 @@ | |
// Add something to the history ring | |
function addToHistory(line){ | |
history.push(line); | |
+ if (window.localStorage) { | |
+ localStorage.history = JSON.stringify(history); | |
+ } | |
restoreText = ''; | |
}; | |
@@ -377,9 +394,12 @@ | |
}; | |
function forwardDelete() { | |
- if (deleteCharAtPos()){ | |
- updatePromptDisplay(); | |
+ if (promptText.length == 0) { | |
+ if (extern.commandHandle) | |
+ extern.commandHandle('\0'); | |
} | |
+ else if (deleteCharAtPos()) | |
+ updatePromptDisplay(); | |
}; | |
function deleteUntilEnd() { | |
@@ -392,18 +412,14 @@ | |
// A word is defined within this context as a series of alphanumeric | |
// characters. | |
// Delete up to the next alphanumeric character | |
- while( | |
- column < promptText.length && | |
- !isCharAlphanumeric(promptText[column]) | |
- ) { | |
+ while(column < promptText.length && | |
+ !isCharAlphanumeric(promptText[column])) { | |
deleteCharAtPos(); | |
updatePromptDisplay(); | |
} | |
// Then, delete until the next non-alphanumeric character | |
- while( | |
- column < promptText.length && | |
- isCharAlphanumeric(promptText[column]) | |
- ) { | |
+ while(column < promptText.length && | |
+ isCharAlphanumeric(promptText[column])) { | |
deleteCharAtPos(); | |
updatePromptDisplay(); | |
} | |
@@ -429,12 +445,7 @@ | |
// Scroll to the bottom of the view | |
function scrollToBottom() { | |
- var version = jQuery.fn.jquery.split('.'); | |
- var major = parseInt(version[0]); | |
- var minor = parseInt(version[1]); | |
- | |
- // check if we're using jquery > 1.6 | |
- if ((major == 1 && minor > 6) || major > 1) { | |
+ if (jQuery.fn.jquery > "1.6") { | |
inner.prop({ scrollTop: inner.prop("scrollHeight") }); | |
} | |
else { | |
@@ -451,7 +462,7 @@ | |
//////////////////////////////////////////////////////////////////////// | |
// Handle a command | |
function handleCommand() { | |
- if (typeof config.commandHandle == 'function') { | |
+ if (typeof extern.commandHandle == 'function') { | |
disableInput(); | |
addToHistory(promptText); | |
var text = promptText; | |
@@ -461,20 +472,19 @@ | |
else continuedText = promptText; | |
} else continuedText = undefined; | |
if (continuedText) text = continuedText; | |
- var ret = config.commandHandle(text,function(msgs){ | |
- commandResult(msgs); | |
- }); | |
+ var ret = extern.commandHandle(text); | |
if (extern.continuedPrompt && !continuedText) | |
continuedText = promptText; | |
- if (typeof ret == 'boolean') { | |
+ if (ret === null) { | |
+ // assume that we don't want to reprompt | |
+ return; | |
+ } else if (typeof ret == 'boolean') { | |
if (ret) { | |
// Command succeeded without a result. | |
commandResult(); | |
} else { | |
- commandResult( | |
- 'Command failed.', | |
- "jquery-console-message-error" | |
- ); | |
+ commandResult('Command failed.', | |
+ "jquery-console-message-error"); | |
} | |
} else if (typeof ret == "string") { | |
commandResult(ret,"jquery-console-message-success"); | |
@@ -490,39 +500,64 @@ | |
// Disable input | |
function disableInput() { | |
acceptInput = false; | |
+ $('span.jquery-console-cursor').addClass('jquery-console-cursor-busy'); | |
+ $('#consoleUnderlay').addClass('consoleUnderlayBusy'); | |
}; | |
// Enable input | |
function enableInput() { | |
acceptInput = true; | |
+ $('span.jquery-console-cursor').removeClass('jquery-console-cursor-busy'); | |
+ $('#consoleUnderlay').removeClass('consoleUnderlayBusy'); | |
} | |
+ var type2css = { | |
+ success: 'jquery-console-message-success', | |
+ error: 'jquery-console-message-error' | |
+ }; | |
+ | |
//////////////////////////////////////////////////////////////////////// | |
// Reset the prompt in invalid command | |
- function commandResult(msg,className) { | |
+ function commandResult(msg,className,noreprompt) { | |
column = -1; | |
updatePromptDisplay(); | |
if (typeof msg == 'string') { | |
- message(msg,className); | |
+ message(msg,className,noreprompt); | |
} else if ($.isArray(msg)) { | |
- for (var x in msg) { | |
- var ret = msg[x]; | |
- message(ret.msg,ret.className); | |
- } | |
+ message(msg[0],type2css[msg[1]]); | |
} else { // Assume it's a DOM node or jQuery object. | |
inner.append(msg); | |
} | |
+ if (!noreprompt) { | |
newPromptBox(); | |
+ } | |
}; | |
+ extern.message = function (msg, type, noreprompt) { | |
+ commandResult(msg, type2css[type], noreprompt); | |
+ } | |
+ extern.reprompt = function() { commandResult(); } | |
+ | |
//////////////////////////////////////////////////////////////////////// | |
// Display a message | |
- function message(msg,className) { | |
- var mesg = $('<div class="jquery-console-message"></div>'); | |
+ function message(msg,className,noreprompt) { | |
+ if (!noreprompt) { | |
+ mesg = $('<div class="jquery-console-message"></div>'); | |
if (className) mesg.addClass(className); | |
- mesg.filledText(msg).hide(); | |
+ mesg.text(msg) | |
+ mesg.hide(); | |
inner.append(mesg); | |
mesg.show(); | |
+ } | |
+ else { | |
+ if (!lastMsg) | |
+ lastMsg = $('<div class="jquery-console-message"></div>'); | |
+ lastMsg.text(lastMsg.text() + msg) | |
+ lastMsg.hide(); | |
+ inner.append(lastMsg); | |
+ lastMsg.show(); | |
+ } | |
+ scrollToBottom(); | |
}; | |
//////////////////////////////////////////////////////////////////////// | |
@@ -577,31 +612,27 @@ | |
}; | |
function moveToNextWord() { | |
- while( | |
- column < promptText.length && | |
+ while(column < promptText.length && | |
!isCharAlphanumeric(promptText[column]) && | |
- moveForward() | |
- ) {} | |
- while( | |
- column < promptText.length && | |
+ moveForward()) { | |
+ } | |
+ while(column < promptText.length && | |
isCharAlphanumeric(promptText[column]) && | |
- moveForward() | |
- ) {} | |
+ moveForward()) { | |
+ } | |
}; | |
function moveToPreviousWord() { | |
// Move backward until we find the first alphanumeric | |
- while( | |
- column -1 >= 0 && | |
+ while(column -1 >= 0 && | |
!isCharAlphanumeric(promptText[column-1]) && | |
- moveBackward() | |
- ) {} | |
+ moveBackward()) { | |
+ } | |
// Move until we find the first non-alphanumeric | |
- while( | |
- column -1 >= 0 && | |
+ while(column -1 >= 0 && | |
isCharAlphanumeric(promptText[column-1]) && | |
- moveBackward() | |
- ) {} | |
+ moveBackward()) { | |
+ } | |
}; | |
function isCharAlphanumeric(charToTest) { | |
@@ -614,44 +645,15 @@ | |
return false; | |
}; | |
- function doComplete() { | |
- if(typeof config.completeHandle == 'function') { | |
- var completions = config.completeHandle(promptText); | |
- var len = completions.length; | |
- if (len === 1) { | |
- extern.promptText(promptText + completions[0]); | |
- } else if (len > 1 && config.cols) { | |
- var prompt = promptText; | |
- // Compute the number of rows that will fit in the width | |
- var max = 0; | |
- for (var i = 0;i < len;i++) { | |
- max = Math.max(max, completions[i].length); | |
- } | |
- max += 2; | |
- var n = Math.floor(config.cols / max); | |
- var buffer = ""; | |
- var col = 0; | |
- for (i = 0;i < len;i++) { | |
- var completion = completions[i]; | |
- buffer += completions[i]; | |
- for (var j = completion.length;j < max;j++) { | |
- buffer += " "; | |
- } | |
- if (++col >= n) { | |
- buffer += "\n"; | |
- col = 0; | |
- } | |
- } | |
- commandResult(buffer,"jquery-console-message-value"); | |
- extern.promptText(prompt); | |
- } | |
- } | |
- }; | |
- | |
function doNothing() {}; | |
+ function tabComplete() { | |
+ if (config.tabComplete) | |
+ return config.tabComplete(); | |
+ } | |
+ | |
extern.promptText = function(text){ | |
- if (typeof text === 'string') { | |
+ if (text) { | |
promptText = text; | |
column = promptText.length; | |
updatePromptDisplay(); | |
@@ -705,17 +707,4 @@ | |
return extern; | |
}; | |
- // Simple utility for printing messages | |
- $.fn.filledText = function(txt){ | |
- $(this).text(txt); | |
- $(this).html($(this).html().replace(/\n/g,'<br/>')); | |
- return this; | |
- }; | |
- | |
- // Alternative method for focus without scrolling | |
- $.fn.focusWithoutScrolling = function(){ | |
- var x = window.scrollX, y = window.scrollY; | |
- $(this).focus(); | |
- window.scrollTo(x, y); | |
- }; | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment