Console.js (6547B)
1 /* 2 A DOS-like output console for JavaScript. 3 http://www.codeproject.com/script/Articles/MemberArticles.aspx?amid=3290305 4 5 Example usage: 6 var console = new Console('myConsoleDivId', 20, 40); 7 console.println('A console window with 20 rows and 40 characters.'); 8 console.setCursorPosition(6,6); 9 console.print('Printing in row 6, column 6'); 10 11 To get user-input, include the URL of PromptWindow.htm in the constructor: 12 var console = new Console('myConsoleDivId', 20, 40); 13 var yourName = console.input('What is your name? '); 14 console.println('Hello, ' + yourName); 15 16 */ 17 18 19 20 function Console(elementId, rows, columns, promptWindowUrl) { 21 /// <summary>Creates a new Console in the HTML element with given ID, with the specified rows and columns, and optionally the URL to the PromptWindow if the input() function is used.</summary> 22 23 // Get a reference to the HTML element which will hold the console. 24 this.element = document.getElementById(elementId); 25 if (!this.element) { 26 alert('No element with the ID ' + elementId + ' was found.'); 27 return; 28 } 29 // remove any child nodes of the element 30 while (this.element.hasChildNodes()) { 31 this.element.removeChild(this.element.childNodes[0]); 32 } 33 // make sure it acts like a 'pre' 34 this.element.style.whiteSpace = 'pre'; 35 36 this.rows = Math.floor(rows); 37 this.columns = Math.floor(columns); 38 this.cursorPosition = { 39 row: 0, 40 column: 0 41 }; 42 this.charGrid = new Array(this.rows); 43 this.promptWindowUrl = promptWindowUrl; 44 45 46 // add the TextNode objects 47 for (var i = 0; i < rows; i++) { 48 var textNode = document.createTextNode(''); 49 this.charGrid[i] = textNode; 50 this.element.appendChild(textNode); 51 if (i < rows - 1) { 52 // add a line break between each TextNode 53 this.element.appendChild(document.createElement('br')); 54 } 55 } 56 57 // clear the console screen 58 this.cls(); 59 60 } 61 62 Console.prototype.cls = function () { 63 /// <summary>Clears all the characters from the console and sets the cursor to 0,0.</summary> 64 65 // go through each row 66 for (var row = 0; row < this.rows; row++) { 67 68 // get the text node, make a string with 'col' spaces, and set this row as the string 69 var textNode = this.charGrid[row]; 70 var s = ''; 71 for (var col = 0; col < this.columns; col++) { 72 s += ' '; 73 } 74 textNode.data = s; 75 } 76 // move cursor to 0,0 77 this.setCursorPos(0, 0); 78 }; 79 80 Console.prototype.printAt = function (row, column, str, cycle) { 81 /// <summary>Private function - not intended to be used by outside programs. Prints a string at the given row and column, and optionally wraps the text if needed.</summary> 82 if (row >= this.rows || row < 0 || column < 0 || !str) { 83 // nothing to print 84 return; 85 } 86 87 // get the text in the target row 88 var oldRow = this.charGrid[row].data; 89 90 // tentatively put the new text for the row in newRow. This is probably too long or too short 91 var newRow = oldRow.substring(0, column) + str; 92 93 if (newRow.length < this.columns) { 94 // the text was too short, so get the remaining characters from the old string. 95 // E.g.: oldRow = "0123456789", printing "hi" over '4' so newRow = "0123hi", then appending "6789" to get "0123hi6789" 96 newRow += oldRow.substring(column + str.length); 97 // move the cursor to the character after the new string, e.g. just after "hi". 98 this.setCursorPos(row, column + str.length); 99 } else { 100 // need to wrap to the next row. 101 this.setCursorPos(row + 1, 0); 102 if (cycle && this.cursorPosition.row >= this.rows) { 103 // moved passed the bottom of the console. Need to delete the first line, and move each line up by one. 104 for (var rowIndex = 0; rowIndex < this.rows - 1; rowIndex++) { 105 this.charGrid[rowIndex].data = this.charGrid[rowIndex + 1].data; 106 } 107 // After moving up, there needs to be a new row at the bottom. Set to empty string. 108 var emptyRow = ''; 109 for (var col = 0; col < this.columns; col++) { 110 emptyRow += ' '; 111 } 112 this.charGrid[this.rows - 1].data = emptyRow; 113 // Cycled the lines up, so the current row should cycle by one as well 114 this.cursorPosition.row--; 115 row--; 116 } 117 } 118 119 // truncate the text if it is too long 120 if (newRow.length > this.columns) { 121 newRow = newRow.substring(0, this.columns); 122 } 123 // set the text to the current row. 124 this.charGrid[row].data = newRow; 125 }; 126 127 Console.prototype.print = function (str) { 128 /// <summary>Prints the given string at the current cursor position, wrapping text where necessary.</summary> 129 130 // get new location of cursor after text added 131 var newColumnPos = this.cursorPosition.column + str.length; 132 133 if (newColumnPos > this.columns) { 134 // text is too long to fit on one line. Add as much as possible, then recursively call print with the remainder of the string 135 136 var charsLeftOnCurLine = this.columns - this.cursorPosition.column; 137 var s = str.substring(0, charsLeftOnCurLine); 138 139 // print the first part 140 this.print(s); 141 142 // print rest of string 143 this.print(str.substring(charsLeftOnCurLine)); 144 145 } else { 146 // print the string at the current cursor position 147 this.printAt(this.cursorPosition.row, this.cursorPosition.column, str, true); 148 } 149 150 }; 151 152 Console.prototype.println = function (str) { 153 /// <summary>Prints the given string at the current cursor position, wrapping text where necessary, and appends a line break.</summary> 154 if (!str) { 155 str = ''; 156 } 157 158 // Actually, we don't add line-breaks. We simply pad out the line with spaces to that the cursor will be forced to the next line. 159 var extraSpaces = this.columns - ((this.cursorPosition.column + str.length) % this.columns); 160 var s2 = str; 161 for (var i = 0; i < extraSpaces; i++) { 162 s2 += ' '; 163 } 164 this.print(s2); 165 }; 166 167 Console.prototype.setCursorPos = function (row, column) { 168 /// <summary>Sets the cursor position to the given row and column.</summary> 169 this.cursorPosition.row = row; 170 this.cursorPosition.column = column; 171 }; 172 173 Console.prototype.input = function (message) { 174 /// <summary>Gets textual input from the user, and prints the message and the user's input to the screen.</summary> 175 if (message) { 176 this.print(message); 177 } 178 179 var result; 180 if (window.showModalDialog) { 181 // IE7 blocks calls to window.prompt (insanity!), so we need to use their showModalDialog 182 if (!this.promptWindowUrl) { 183 alert('JS Console Error\nConsole.promptWindowUrl not set. Set this to the URL of PromptWindow.htm\nPrompts disabled in Internet Explorer.'); 184 return ''; 185 } 186 result = window.showModalDialog(this.promptWindowUrl, message, "dialogWidth:300px;dialogHeight:200px"); 187 } else { 188 result = prompt(message); 189 } 190 191 if (result) { 192 this.println(result); 193 return result; 194 } else { 195 return ''; 196 } 197 };