Guillaume Nodet | 756cf8e | 2009-08-07 09:48:21 +0000 | [diff] [blame^] | 1 | // |
| 2 | // Licensed to the Apache Software Foundation (ASF) under one or more |
| 3 | // contributor license agreements. See the NOTICE file distributed with |
| 4 | // this work for additional information regarding copyright ownership. |
| 5 | // The ASF licenses this file to You under the Apache License, Version 2.0 |
| 6 | // (the "License"); you may not use this file except in compliance with |
| 7 | // the License. You may obtain a copy of the License at |
| 8 | // |
| 9 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | // |
| 11 | // Unless required by applicable law or agreed to in writing, software |
| 12 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | // See the License for the specific language governing permissions and |
| 15 | // limitations under the License. |
| 16 | // |
| 17 | |
| 18 | // |
| 19 | // Based on http://antony.lesuisse.org/software/ajaxterm/ |
| 20 | // Public Domain License |
| 21 | // |
| 22 | |
| 23 | gogo = { }; |
| 24 | |
| 25 | gogo.Terminal_ctor = function(div, width, height) { |
| 26 | |
| 27 | var ie = (window.ActiveXObject) ? 0 : 1; |
| 28 | var query0 = "w=" + width + "&h=" + height; |
| 29 | var query1 = query0 + "&k="; |
| 30 | var buf = ""; |
| 31 | var timeout; |
| 32 | var error_timeout; |
| 33 | var keybuf = []; |
| 34 | var sending = 0; |
| 35 | var rmax = 1; |
| 36 | var force = 1; |
| 37 | |
| 38 | var dstat = document.createElement('pre'); |
| 39 | var sled = document.createElement('span'); |
| 40 | var sdebug = document.createElement('span'); |
| 41 | var dterm = document.createElement('div'); |
| 42 | |
| 43 | function debug(s) { |
| 44 | sdebug.innerHTML = s; |
| 45 | } |
| 46 | |
| 47 | function error() { |
| 48 | sled.className = 'off'; |
| 49 | debug("Connection lost timeout ts:" + ((new Date).getTime())); |
| 50 | } |
| 51 | |
| 52 | function update() { |
| 53 | if (sending == 0) { |
| 54 | sending = 1; |
| 55 | sled.className = 'on'; |
| 56 | var r = new XMLHttpRequest(); |
| 57 | var send = ""; |
| 58 | while (keybuf.length > 0) { |
| 59 | send += keybuf.pop(); |
| 60 | } |
| 61 | var query = query1 + send; |
| 62 | if (force) { |
| 63 | query = query + "&f=1"; |
| 64 | force = 0; |
| 65 | } |
| 66 | r.open("POST", "gogo", true); |
| 67 | r.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); |
| 68 | r.onreadystatechange = function () { |
| 69 | if (r.readyState == 4) { |
| 70 | if (r.status == 200) { |
| 71 | window.clearTimeout(error_timeout); |
| 72 | if (r.responseText.length > 0) { |
| 73 | dterm.innerHTML = r.responseText; |
| 74 | rmax = 100; |
| 75 | } else { |
| 76 | rmax *= 2; |
| 77 | if (rmax > 2000) |
| 78 | rmax = 2000; |
| 79 | } |
| 80 | sending=0; |
| 81 | sled.className = 'off'; |
| 82 | timeout = window.setTimeout(update, rmax); |
| 83 | } else { |
| 84 | debug("Connection error status:" + r.status); |
| 85 | } |
| 86 | } |
| 87 | } |
| 88 | error_timeout = window.setTimeout(error, 5000); |
| 89 | r.send(query); |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | function queue(s) { |
| 94 | keybuf.unshift(s); |
| 95 | if (sending == 0) { |
| 96 | window.clearTimeout(timeout); |
| 97 | timeout = window.setTimeout(update, 1); |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | function keypress(ev) { |
| 102 | // Translate to standard keycodes |
| 103 | if (!ev) |
| 104 | ev = window.event; |
| 105 | var kc; |
| 106 | if (ev.keyCode) |
| 107 | kc = ev.keyCode; |
| 108 | if (ev.which) |
| 109 | kc = ev.which; |
| 110 | if (ev.ctrlKey) { |
| 111 | if (kc >= 0 && kc <= 32) |
| 112 | kc = kc; |
| 113 | else if (kc >= 65 && kc <= 90) |
| 114 | kc -= 64; |
| 115 | else if (kc >= 97 && kc <= 122) |
| 116 | kc -= 96; |
| 117 | else { |
| 118 | switch (kc) { |
| 119 | case 54: kc=30; break; // Ctrl-^ |
| 120 | case 109: kc=31; break; // Ctrl-_ |
| 121 | case 219: kc=27; break; // Ctrl-[ |
| 122 | case 220: kc=28; break; // Ctrl-\ |
| 123 | case 221: kc=29; break; // Ctrl-] |
| 124 | default: return true; |
| 125 | } |
| 126 | } |
| 127 | } else if (ev.which == 0) { |
| 128 | switch(kc) { |
| 129 | case 8: break; // Backspace |
| 130 | case 9: break; // Tab |
| 131 | case 27: break; // ESC |
| 132 | case 33: kc = 63276; break; // PgUp |
| 133 | case 34: kc = 63277; break; // PgDn |
| 134 | case 35: kc = 63275; break; // End |
| 135 | case 36: kc = 63273; break; // Home |
| 136 | case 37: kc = 63234; break; // Left |
| 137 | case 38: kc = 63232; break; // Up |
| 138 | case 39: kc = 63235; break; // Right |
| 139 | case 40: kc = 63233; break; // Down |
| 140 | case 45: kc = 63302; break; // Ins |
| 141 | case 46: kc = 63272; break; // Del |
| 142 | case 112: kc = 63236; break; // F1 |
| 143 | case 113: kc = 63237; break; // F2 |
| 144 | case 114: kc = 63238; break; // F3 |
| 145 | case 115: kc = 63239; break; // F4 |
| 146 | case 116: kc = 63240; break; // F5 |
| 147 | case 117: kc = 63241; break; // F6 |
| 148 | case 118: kc = 63242; break; // F7 |
| 149 | case 119: kc = 63243; break; // F8 |
| 150 | case 120: kc = 63244; break; // F9 |
| 151 | case 121: kc = 63245; break; // F10 |
| 152 | case 122: kc = 63246; break; // F11 |
| 153 | case 123: kc = 63247; break; // F12 |
| 154 | default: return true; |
| 155 | } |
| 156 | } |
| 157 | if (kc == 8) |
| 158 | kc = 127; |
| 159 | |
| 160 | var k = ""; |
| 161 | // Build character |
| 162 | switch (kc) { |
| 163 | case 126: k = "~~"; break; |
| 164 | case 63232: k = "~A"; break; // Up |
| 165 | case 63233: k = "~B"; break; // Down |
| 166 | case 63234: k = "~D"; break; // Left |
| 167 | case 63235: k = "~C"; break; // Right |
| 168 | case 63276: k = "~1"; break; // PgUp |
| 169 | case 63277: k = "~2"; break; // PgDn |
| 170 | case 63273: k = "~H"; break; // Home |
| 171 | case 63275: k = "~F"; break; // End |
| 172 | case 63302: k = "~3"; break; // Ins |
| 173 | case 63272: k = "~4"; break; // Del |
| 174 | case 63236: k = "~a"; break; // F1 |
| 175 | case 63237: k = "~b"; break; // F2 |
| 176 | case 63238: k = "~c"; break; // F3 |
| 177 | case 63239: k = "~d"; break; // F4 |
| 178 | case 63240: k = "~e"; break; // F5 |
| 179 | case 63241: k = "~f"; break; // F6 |
| 180 | case 63242: k = "~g"; break; // F7 |
| 181 | case 63243: k = "~h"; break; // F8 |
| 182 | case 63244: k = "~i"; break; // F9 |
| 183 | case 63245: k = "~j"; break; // F10 |
| 184 | case 63246: k = "~k"; break; // F11 |
| 185 | case 63247: k = "~l"; break; // F12 |
| 186 | default: k = String.fromCharCode(kc); break; |
| 187 | } |
| 188 | queue(encodeURIComponent(k)); |
| 189 | |
| 190 | ev.cancelBubble = true; |
| 191 | if (ev.stopPropagation) ev.stopPropagation(); |
| 192 | if (ev.preventDefault) ev.preventDefault(); |
| 193 | |
| 194 | return true; |
| 195 | } |
| 196 | |
| 197 | function keydown(ev) { |
| 198 | if (!ev) |
| 199 | ev = window.event; |
| 200 | if (ie) { |
| 201 | o = { 9:1, 8:1, 27:1, 33:1, 34:1, 35:1, 36:1, 37:1, 38:1, 39:1, 40:1, 45:1, 46:1, 112:1, |
| 202 | 113:1, 114:1, 115:1, 116:1, 117:1, 118:1, 119:1, 120:1, 121:1, 122:1, 123:1 }; |
| 203 | if (o[ev.keyCode] || ev.ctrlKey || ev.altKey) { |
| 204 | ev.which = 0; |
| 205 | return keypress(ev); |
| 206 | } |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | function init() { |
| 211 | if (typeof(XMLHttpRequest) == "undefined") { |
| 212 | XMLHttpRequest = function() { |
| 213 | try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } |
| 214 | catch(e) {} |
| 215 | try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } |
| 216 | catch(e) {} |
| 217 | try { return new ActiveXObject("Msxml2.XMLHTTP"); } |
| 218 | catch(e) {} |
| 219 | try { return new ActiveXObject("Microsoft.XMLHTTP"); } |
| 220 | catch(e) {} |
| 221 | throw new Error("This browser does not support XMLHttpRequest."); |
| 222 | }; |
| 223 | } |
| 224 | sled.appendChild(document.createTextNode('\xb7')); |
| 225 | sled.className = 'off'; |
| 226 | dstat.appendChild(sled); |
| 227 | dstat.appendChild(document.createTextNode(' ')); |
| 228 | dstat.appendChild(sdebug); |
| 229 | dstat.className = 'stat'; |
| 230 | div.appendChild(dstat); |
| 231 | var d = document.createElement('div'); |
| 232 | d.appendChild(dterm); |
| 233 | div.appendChild(d); |
| 234 | document.onkeypress = keypress; |
| 235 | document.onkeydown = keydown; |
| 236 | timeout = window.setTimeout(update, 100); |
| 237 | } |
| 238 | |
| 239 | init(); |
| 240 | |
| 241 | } |
| 242 | |
| 243 | gogo.Terminal = function(div, width, height) { |
| 244 | return new this.Terminal_ctor(div, width, height); |
| 245 | } |
| 246 | |