blob: 77044a793c94b0e1fd590023ed195670fcd98c57 [file] [log] [blame]
Felix Meschberger97204d82012-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');
39 var sdebug = document.createElement('span');
40 var dterm = document.createElement('div');
41
42 function debug(s) {
43 sdebug.innerHTML = s;
44 }
45
46 function error() {
47 sled.className = 'off';
48 debug("Connection lost timeout ts:" + ((new Date).getTime()));
49 }
50
51 function update() {
52 if (sending == 0) {
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);
82 } else {
83 debug("Connection error status:" + r.status);
84 }
85 }
86 }
87 error_timeout = window.setTimeout(error, 5000);
88 r.send(query);
89 }
90 }
91
92 function queue(s) {
93 keybuf.unshift(s);
94 if (sending == 0) {
95 window.clearTimeout(timeout);
96 timeout = window.setTimeout(update, 1);
97 }
98 }
99
100 function keypress(ev, fromkeydown) {
101 // Translate to standard keycodes
102 if (!ev)
103 ev = window.event;
104 var kc;
105 if (ev.keyCode)
106 kc = ev.keyCode;
107 if (!fromkeydown && ev.which)
108 kc = ev.which;
109 if (ev.ctrlKey) {
110 if (kc >= 0 && kc <= 32)
111 kc = kc;
112 else if (kc >= 65 && kc <= 90)
113 kc -= 64;
114 else if (kc >= 97 && kc <= 122)
115 kc -= 96;
116 else {
117 switch (kc) {
118 case 54: kc=30; break; // Ctrl-^
119 case 109: kc=31; break; // Ctrl-_
120 case 219: kc=27; break; // Ctrl-[
121 case 220: kc=28; break; // Ctrl-\
122 case 221: kc=29; break; // Ctrl-]
123 default: return true;
124 }
125 }
126 } else if (fromkeydown) {
127 switch(kc) {
128 case 8: break; // Backspace
129 case 9: break; // Tab
130 case 27: break; // ESC
131 case 33: kc = 63276; break; // PgUp
132 case 34: kc = 63277; break; // PgDn
133 case 35: kc = 63275; break; // End
134 case 36: kc = 63273; break; // Home
135 case 37: kc = 63234; break; // Left
136 case 38: kc = 63232; break; // Up
137 case 39: kc = 63235; break; // Right
138 case 40: kc = 63233; break; // Down
139 case 45: kc = 63302; break; // Ins
140 case 46: kc = 63272; break; // Del
141 case 112: kc = 63236; break; // F1
142 case 113: kc = 63237; break; // F2
143 case 114: kc = 63238; break; // F3
144 case 115: kc = 63239; break; // F4
145 case 116: kc = 63240; break; // F5
146 case 117: kc = 63241; break; // F6
147 case 118: kc = 63242; break; // F7
148 case 119: kc = 63243; break; // F8
149 case 120: kc = 63244; break; // F9
150 case 121: kc = 63245; break; // F10
151 case 122: kc = 63246; break; // F11
152 case 123: kc = 63247; break; // F12
153 default: return true;
154 }
155 }
156
157 var k = "";
158 // Build character
159 switch (kc) {
160 case 126: k = "~~"; break;
161 case 63232: k = "~A"; break; // Up
162 case 63233: k = "~B"; break; // Down
163 case 63234: k = "~D"; break; // Left
164 case 63235: k = "~C"; break; // Right
165 case 63276: k = "~1"; break; // PgUp
166 case 63277: k = "~2"; break; // PgDn
167 case 63273: k = "~H"; break; // Home
168 case 63275: k = "~F"; break; // End
169 case 63302: k = "~3"; break; // Ins
170 case 63272: k = "~4"; break; // Del
171 case 63236: k = "~a"; break; // F1
172 case 63237: k = "~b"; break; // F2
173 case 63238: k = "~c"; break; // F3
174 case 63239: k = "~d"; break; // F4
175 case 63240: k = "~e"; break; // F5
176 case 63241: k = "~f"; break; // F6
177 case 63242: k = "~g"; break; // F7
178 case 63243: k = "~h"; break; // F8
179 case 63244: k = "~i"; break; // F9
180 case 63245: k = "~j"; break; // F10
181 case 63246: k = "~k"; break; // F11
182 case 63247: k = "~l"; break; // F12
183 default: k = String.fromCharCode(kc); break;
184 }
185
186// debug("fromkeydown=" + fromkeydown + ", ev.keyCode=" + ev.keyCode + ", " +
187// "ev.which=" + ev.which + ", ev.ctrlKey=" + ev.ctrlKey + ", " +
188// "kc=" + kc + ", k=" + k);
189
190 queue(encodeURIComponent(k));
191
192 ev.cancelBubble = true;
193 if (ev.stopPropagation) ev.stopPropagation();
194 if (ev.preventDefault) ev.preventDefault();
195
196 return true;
197 }
198
199 function keydown(ev) {
200 if (!ev)
201 ev = window.event;
202 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,
203 113:1, 114:1, 115:1, 116:1, 117:1, 118:1, 119:1, 120:1, 121:1, 122:1, 123:1 };
204 if (o[ev.keyCode] || ev.ctrlKey || ev.altKey) {
205 keypress(ev, true);
206 }
207 }
208
209 function init() {
210 if (typeof(XMLHttpRequest) == "undefined") {
211 XMLHttpRequest = function() {
212 try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
213 catch(e) {}
214 try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
215 catch(e) {}
216 try { return new ActiveXObject("Msxml2.XMLHTTP"); }
217 catch(e) {}
218 try { return new ActiveXObject("Microsoft.XMLHTTP"); }
219 catch(e) {}
220 throw new Error("This browser does not support XMLHttpRequest.");
221 };
222 }
223 sled.appendChild(document.createTextNode('\xb7'));
224 sled.className = 'off';
225 dstat.appendChild(sled);
226 dstat.appendChild(document.createTextNode(' '));
227 dstat.appendChild(sdebug);
228 dstat.className = 'stat';
229 div.appendChild(dstat);
230 var d = document.createElement('div');
231 d.appendChild(dterm);
232 div.appendChild(d);
233 document.onkeypress = keypress;
234 document.onkeydown = keydown;
235 timeout = window.setTimeout(update, 100);
236 }
237
238 init();
239
240}
241
242gogo.Terminal = function(div, width, height) {
243 return new this.Terminal_ctor(div, width, height);
244}
245