Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +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 query0 = "w=" + width + "&h=" + height; |
| 28 | var query1 = query0 + "&k="; |
| 29 | var buf = ""; |
| 30 | var timeout; |
| 31 | var error_timeout; |
| 32 | var keybuf = []; |
| 33 | var sending = 0; |
| 34 | var rmax = 1; |
| 35 | var force = 1; |
| 36 | |
| 37 | var dstat = document.createElement('pre'); |
| 38 | var sled = document.createElement('span'); |
Felix Meschberger | 9681295 | 2012-06-01 14:37:54 +0000 | [diff] [blame] | 39 | var sdebug = document.getElementById('statline'); |
Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +0000 | [diff] [blame] | 40 | var dterm = document.createElement('div'); |
| 41 | |
| 42 | function debug(s) { |
| 43 | sdebug.innerHTML = s; |
| 44 | } |
| 45 | |
| 46 | function error() { |
| 47 | sled.className = 'off'; |
Felix Meschberger | 9681295 | 2012-06-01 14:37:54 +0000 | [diff] [blame] | 48 | debug("Gogo Shell Processor not available"); |
Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +0000 | [diff] [blame] | 49 | } |
| 50 | |
| 51 | function update() { |
Felix Meschberger | 9681295 | 2012-06-01 14:37:54 +0000 | [diff] [blame] | 52 | if (sending == 0 /* && keybuf.length > 0 */ ) { |
Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +0000 | [diff] [blame] | 53 | sending = 1; |
| 54 | sled.className = 'on'; |
| 55 | var r = new XMLHttpRequest(); |
| 56 | var send = ""; |
| 57 | while (keybuf.length > 0) { |
| 58 | send += keybuf.pop(); |
| 59 | } |
| 60 | var query = query1 + send; |
| 61 | if (force) { |
| 62 | query = query + "&f=1"; |
| 63 | force = 0; |
| 64 | } |
| 65 | r.open("POST", "gogo", true); |
| 66 | r.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); |
| 67 | r.onreadystatechange = function () { |
| 68 | if (r.readyState == 4) { |
| 69 | if (r.status == 200) { |
| 70 | window.clearTimeout(error_timeout); |
| 71 | if (r.responseText.length > 0) { |
| 72 | dterm.innerHTML = r.responseText; |
| 73 | rmax = 100; |
| 74 | } else { |
| 75 | rmax *= 2; |
| 76 | if (rmax > 2000) |
| 77 | rmax = 2000; |
| 78 | } |
| 79 | sending=0; |
| 80 | sled.className = 'off'; |
| 81 | timeout = window.setTimeout(update, rmax); |
Felix Meschberger | 9681295 | 2012-06-01 14:37:54 +0000 | [diff] [blame] | 82 | } else if (r.status == 500) { |
| 83 | debug("Gogo Shell Processor not available") |
Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +0000 | [diff] [blame] | 84 | } else { |
Felix Meschberger | 9681295 | 2012-06-01 14:37:54 +0000 | [diff] [blame] | 85 | debug("General failure with Gogo Shell: " + r.status); |
Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +0000 | [diff] [blame] | 86 | } |
| 87 | } |
| 88 | } |
| 89 | error_timeout = window.setTimeout(error, 5000); |
| 90 | r.send(query); |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | function queue(s) { |
| 95 | keybuf.unshift(s); |
| 96 | if (sending == 0) { |
| 97 | window.clearTimeout(timeout); |
| 98 | timeout = window.setTimeout(update, 1); |
| 99 | } |
| 100 | } |
| 101 | |
Felix Meschberger | 23756c8 | 2013-01-21 21:05:03 +0000 | [diff] [blame] | 102 | function keypress(ev) { |
Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +0000 | [diff] [blame] | 103 | // Translate to standard keycodes |
| 104 | if (!ev) |
| 105 | ev = window.event; |
| 106 | var kc; |
| 107 | if (ev.keyCode) |
| 108 | kc = ev.keyCode; |
Felix Meschberger | 23756c8 | 2013-01-21 21:05:03 +0000 | [diff] [blame] | 109 | if (ev.which) |
Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +0000 | [diff] [blame] | 110 | kc = ev.which; |
| 111 | if (ev.ctrlKey) { |
| 112 | if (kc >= 0 && kc <= 32) |
| 113 | kc = kc; |
| 114 | else if (kc >= 65 && kc <= 90) |
| 115 | kc -= 64; |
| 116 | else if (kc >= 97 && kc <= 122) |
| 117 | kc -= 96; |
| 118 | else { |
| 119 | switch (kc) { |
| 120 | case 54: kc=30; break; // Ctrl-^ |
| 121 | case 109: kc=31; break; // Ctrl-_ |
| 122 | case 219: kc=27; break; // Ctrl-[ |
| 123 | case 220: kc=28; break; // Ctrl-\ |
| 124 | case 221: kc=29; break; // Ctrl-] |
| 125 | default: return true; |
| 126 | } |
| 127 | } |
Felix Meschberger | 23756c8 | 2013-01-21 21:05:03 +0000 | [diff] [blame] | 128 | } |
Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +0000 | [diff] [blame] | 129 | |
| 130 | var k = ""; |
| 131 | // Build character |
| 132 | switch (kc) { |
| 133 | case 126: k = "~~"; break; |
| 134 | case 63232: k = "~A"; break; // Up |
| 135 | case 63233: k = "~B"; break; // Down |
| 136 | case 63234: k = "~D"; break; // Left |
| 137 | case 63235: k = "~C"; break; // Right |
| 138 | case 63276: k = "~1"; break; // PgUp |
| 139 | case 63277: k = "~2"; break; // PgDn |
| 140 | case 63273: k = "~H"; break; // Home |
| 141 | case 63275: k = "~F"; break; // End |
| 142 | case 63302: k = "~3"; break; // Ins |
| 143 | case 63272: k = "~4"; break; // Del |
| 144 | case 63236: k = "~a"; break; // F1 |
| 145 | case 63237: k = "~b"; break; // F2 |
| 146 | case 63238: k = "~c"; break; // F3 |
| 147 | case 63239: k = "~d"; break; // F4 |
| 148 | case 63240: k = "~e"; break; // F5 |
| 149 | case 63241: k = "~f"; break; // F6 |
| 150 | case 63242: k = "~g"; break; // F7 |
| 151 | case 63243: k = "~h"; break; // F8 |
| 152 | case 63244: k = "~i"; break; // F9 |
| 153 | case 63245: k = "~j"; break; // F10 |
| 154 | case 63246: k = "~k"; break; // F11 |
| 155 | case 63247: k = "~l"; break; // F12 |
| 156 | default: k = String.fromCharCode(kc); break; |
| 157 | } |
| 158 | |
Felix Meschberger | 9681295 | 2012-06-01 14:37:54 +0000 | [diff] [blame] | 159 | var s = encodeURIComponent(k); |
| 160 | |
Felix Meschberger | 23756c8 | 2013-01-21 21:05:03 +0000 | [diff] [blame] | 161 | // debug("ev.keyCode=" + ev.keyCode + ", " + |
Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +0000 | [diff] [blame] | 162 | // "ev.which=" + ev.which + ", ev.ctrlKey=" + ev.ctrlKey + ", " + |
Felix Meschberger | 9681295 | 2012-06-01 14:37:54 +0000 | [diff] [blame] | 163 | // "kc=" + kc + ", k=" + k + ", s=" + s); |
Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +0000 | [diff] [blame] | 164 | |
Felix Meschberger | 9681295 | 2012-06-01 14:37:54 +0000 | [diff] [blame] | 165 | queue(s); |
Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +0000 | [diff] [blame] | 166 | |
| 167 | ev.cancelBubble = true; |
| 168 | if (ev.stopPropagation) ev.stopPropagation(); |
| 169 | if (ev.preventDefault) ev.preventDefault(); |
| 170 | |
| 171 | return true; |
| 172 | } |
| 173 | |
Felix Meschberger | 9681295 | 2012-06-01 14:37:54 +0000 | [diff] [blame] | 174 | function ignoreKey(ev) { |
| 175 | if (!ev) { |
| 176 | ev = window.event; |
| 177 | } |
| 178 | |
| 179 | ev.cancelBubble = true; |
| 180 | if (ev.stopPropagation) ev.stopPropagation(); |
| 181 | if (ev.preventDefault) ev.preventDefault(); |
| 182 | } |
Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +0000 | [diff] [blame] | 183 | |
| 184 | function init() { |
| 185 | if (typeof(XMLHttpRequest) == "undefined") { |
| 186 | XMLHttpRequest = function() { |
| 187 | try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } |
| 188 | catch(e) {} |
| 189 | try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } |
| 190 | catch(e) {} |
| 191 | try { return new ActiveXObject("Msxml2.XMLHTTP"); } |
| 192 | catch(e) {} |
| 193 | try { return new ActiveXObject("Microsoft.XMLHTTP"); } |
| 194 | catch(e) {} |
| 195 | throw new Error("This browser does not support XMLHttpRequest."); |
| 196 | }; |
| 197 | } |
Felix Meschberger | 9681295 | 2012-06-01 14:37:54 +0000 | [diff] [blame] | 198 | |
Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +0000 | [diff] [blame] | 199 | sled.appendChild(document.createTextNode('\xb7')); |
| 200 | sled.className = 'off'; |
| 201 | dstat.appendChild(sled); |
| 202 | dstat.appendChild(document.createTextNode(' ')); |
Felix Meschberger | 9681295 | 2012-06-01 14:37:54 +0000 | [diff] [blame] | 203 | // dstat.appendChild(sdebug); |
Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +0000 | [diff] [blame] | 204 | dstat.className = 'stat'; |
Felix Meschberger | 9681295 | 2012-06-01 14:37:54 +0000 | [diff] [blame] | 205 | |
Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +0000 | [diff] [blame] | 206 | div.appendChild(dstat); |
| 207 | var d = document.createElement('div'); |
| 208 | d.appendChild(dterm); |
| 209 | div.appendChild(d); |
Felix Meschberger | 9681295 | 2012-06-01 14:37:54 +0000 | [diff] [blame] | 210 | |
Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +0000 | [diff] [blame] | 211 | document.onkeypress = keypress; |
Felix Meschberger | 9681295 | 2012-06-01 14:37:54 +0000 | [diff] [blame] | 212 | document.onkeyup = ignoreKey; |
Felix Meschberger | 97204d8 | 2012-01-31 12:47:45 +0000 | [diff] [blame] | 213 | timeout = window.setTimeout(update, 100); |
| 214 | } |
| 215 | |
| 216 | init(); |
| 217 | |
| 218 | } |
| 219 | |
| 220 | gogo.Terminal = function(div, width, height) { |
| 221 | return new this.Terminal_ctor(div, width, height); |
| 222 | } |
| 223 | |