blob: a204d4874a98d55e3b92f08ba3e89f88fbe3669b [file] [log] [blame]
Felix Meschberger044c4bf2012-01-31 12:47:45 +00001//
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
23gogo = { };
24
25gogo.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 Meschberger99c60c82012-06-01 14:37:54 +000039 var sdebug = document.getElementById('statline');
Felix Meschberger044c4bf2012-01-31 12:47:45 +000040 var dterm = document.createElement('div');
41
42 function debug(s) {
43 sdebug.innerHTML = s;
44 }
45
46 function error() {
47 sled.className = 'off';
Felix Meschberger99c60c82012-06-01 14:37:54 +000048 debug("Gogo Shell Processor not available");
Felix Meschberger044c4bf2012-01-31 12:47:45 +000049 }
50
51 function update() {
Felix Meschberger99c60c82012-06-01 14:37:54 +000052 if (sending == 0 /* && keybuf.length > 0 */ ) {
Felix Meschberger044c4bf2012-01-31 12:47:45 +000053 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 Meschberger99c60c82012-06-01 14:37:54 +000082 } else if (r.status == 500) {
83 debug("Gogo Shell Processor not available")
Felix Meschberger044c4bf2012-01-31 12:47:45 +000084 } else {
Felix Meschberger99c60c82012-06-01 14:37:54 +000085 debug("General failure with Gogo Shell: " + r.status);
Felix Meschberger044c4bf2012-01-31 12:47:45 +000086 }
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
102 function keypress(ev, fromkeydown) {
103 // Translate to standard keycodes
104 if (!ev)
105 ev = window.event;
106 var kc;
107 if (ev.keyCode)
108 kc = ev.keyCode;
109 if (!fromkeydown && ev.which)
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 }
128 } else if (fromkeydown) {
129 switch(kc) {
130 case 8: break; // Backspace
131 case 9: break; // Tab
132 case 27: break; // ESC
133 case 33: kc = 63276; break; // PgUp
134 case 34: kc = 63277; break; // PgDn
135 case 35: kc = 63275; break; // End
136 case 36: kc = 63273; break; // Home
137 case 37: kc = 63234; break; // Left
138 case 38: kc = 63232; break; // Up
139 case 39: kc = 63235; break; // Right
140 case 40: kc = 63233; break; // Down
141 case 45: kc = 63302; break; // Ins
142 case 46: kc = 63272; break; // Del
143 case 112: kc = 63236; break; // F1
144 case 113: kc = 63237; break; // F2
145 case 114: kc = 63238; break; // F3
146 case 115: kc = 63239; break; // F4
147 case 116: kc = 63240; break; // F5
148 case 117: kc = 63241; break; // F6
149 case 118: kc = 63242; break; // F7
150 case 119: kc = 63243; break; // F8
151 case 120: kc = 63244; break; // F9
152 case 121: kc = 63245; break; // F10
153 case 122: kc = 63246; break; // F11
154 case 123: kc = 63247; break; // F12
155 default: return true;
156 }
157 }
158
159 var k = "";
160 // Build character
161 switch (kc) {
162 case 126: k = "~~"; break;
163 case 63232: k = "~A"; break; // Up
164 case 63233: k = "~B"; break; // Down
165 case 63234: k = "~D"; break; // Left
166 case 63235: k = "~C"; break; // Right
167 case 63276: k = "~1"; break; // PgUp
168 case 63277: k = "~2"; break; // PgDn
169 case 63273: k = "~H"; break; // Home
170 case 63275: k = "~F"; break; // End
171 case 63302: k = "~3"; break; // Ins
172 case 63272: k = "~4"; break; // Del
173 case 63236: k = "~a"; break; // F1
174 case 63237: k = "~b"; break; // F2
175 case 63238: k = "~c"; break; // F3
176 case 63239: k = "~d"; break; // F4
177 case 63240: k = "~e"; break; // F5
178 case 63241: k = "~f"; break; // F6
179 case 63242: k = "~g"; break; // F7
180 case 63243: k = "~h"; break; // F8
181 case 63244: k = "~i"; break; // F9
182 case 63245: k = "~j"; break; // F10
183 case 63246: k = "~k"; break; // F11
184 case 63247: k = "~l"; break; // F12
185 default: k = String.fromCharCode(kc); break;
186 }
187
Felix Meschberger99c60c82012-06-01 14:37:54 +0000188 var s = encodeURIComponent(k);
189
Felix Meschberger044c4bf2012-01-31 12:47:45 +0000190// debug("fromkeydown=" + fromkeydown + ", ev.keyCode=" + ev.keyCode + ", " +
191// "ev.which=" + ev.which + ", ev.ctrlKey=" + ev.ctrlKey + ", " +
Felix Meschberger99c60c82012-06-01 14:37:54 +0000192// "kc=" + kc + ", k=" + k + ", s=" + s);
Felix Meschberger044c4bf2012-01-31 12:47:45 +0000193
Felix Meschberger99c60c82012-06-01 14:37:54 +0000194 queue(s);
Felix Meschberger044c4bf2012-01-31 12:47:45 +0000195
196 ev.cancelBubble = true;
197 if (ev.stopPropagation) ev.stopPropagation();
198 if (ev.preventDefault) ev.preventDefault();
199
200 return true;
201 }
202
203 function keydown(ev) {
204 if (!ev)
205 ev = window.event;
206 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,
207 113:1, 114:1, 115:1, 116:1, 117:1, 118:1, 119:1, 120:1, 121:1, 122:1, 123:1 };
208 if (o[ev.keyCode] || ev.ctrlKey || ev.altKey) {
209 keypress(ev, true);
Felix Meschberger99c60c82012-06-01 14:37:54 +0000210 } else {
211 ev.cancelBubble = true;
212 if (ev.stopPropagation) ev.stopPropagation();
213 if (ev.preventDefault) ev.preventDefault();
Felix Meschberger044c4bf2012-01-31 12:47:45 +0000214 }
215 }
Felix Meschberger99c60c82012-06-01 14:37:54 +0000216
217 function ignoreKey(ev) {
218 if (!ev) {
219 ev = window.event;
220 }
221
222 ev.cancelBubble = true;
223 if (ev.stopPropagation) ev.stopPropagation();
224 if (ev.preventDefault) ev.preventDefault();
225 }
Felix Meschberger044c4bf2012-01-31 12:47:45 +0000226
227 function init() {
228 if (typeof(XMLHttpRequest) == "undefined") {
229 XMLHttpRequest = function() {
230 try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
231 catch(e) {}
232 try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
233 catch(e) {}
234 try { return new ActiveXObject("Msxml2.XMLHTTP"); }
235 catch(e) {}
236 try { return new ActiveXObject("Microsoft.XMLHTTP"); }
237 catch(e) {}
238 throw new Error("This browser does not support XMLHttpRequest.");
239 };
240 }
Felix Meschberger99c60c82012-06-01 14:37:54 +0000241
Felix Meschberger044c4bf2012-01-31 12:47:45 +0000242 sled.appendChild(document.createTextNode('\xb7'));
243 sled.className = 'off';
244 dstat.appendChild(sled);
245 dstat.appendChild(document.createTextNode(' '));
Felix Meschberger99c60c82012-06-01 14:37:54 +0000246// dstat.appendChild(sdebug);
Felix Meschberger044c4bf2012-01-31 12:47:45 +0000247 dstat.className = 'stat';
Felix Meschberger99c60c82012-06-01 14:37:54 +0000248
Felix Meschberger044c4bf2012-01-31 12:47:45 +0000249 div.appendChild(dstat);
250 var d = document.createElement('div');
251 d.appendChild(dterm);
252 div.appendChild(d);
Felix Meschberger99c60c82012-06-01 14:37:54 +0000253
Felix Meschberger044c4bf2012-01-31 12:47:45 +0000254 document.onkeypress = keypress;
Felix Meschberger99c60c82012-06-01 14:37:54 +0000255 document.onkeydown = ignoreKey;
256 document.onkeyup = ignoreKey;
Felix Meschberger044c4bf2012-01-31 12:47:45 +0000257 timeout = window.setTimeout(update, 100);
258 }
259
260 init();
261
262}
263
264gogo.Terminal = function(div, width, height) {
265 return new this.Terminal_ctor(div, width, height);
266}
267