blob: 771efe060fe676c7468fb30b307db79689e03016 [file] [log] [blame]
Guillaume Nodet756cf8e2009-08-07 09:48:21 +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 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
243gogo.Terminal = function(div, width, height) {
244 return new this.Terminal_ctor(div, width, height);
245}
246