All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kohsuke.ajaxterm.js Maven / Gradle / Ivy

The newest version!
ajaxterm={};
ajaxterm.Terminal=function(id,options) {
    // options
    var width  = options.width || 80; // dimension of the terminal
    var height = options.height || 25;
    var endpoint = options.endpoint;  // URL of the server endpoint that delivers the request to Session.handleUpdate
    var additionalQueryString = options.query; // additional parameters sent to the server

	var ie=0;
	if(window.ActiveXObject)
		ie=1;
	var sid=""+Math.round(Math.random()*1000000000);
	var query0="s="+sid+"&w="+width+"&h="+height;
	var query1=query0+"&c=1&k=";
	var buf="";
	var timeout;
    var screenTimestamp = 0;
	var error_timeout;
	var keybuf=[];
	var sending=0;
	var rmax=1;

	var div=(typeof(id)=="string" ? document.getElementById(id) : id);
    var fitter=document.createElement('div');   // for shrinking the screen area to the right size
	var dstat=document.createElement('pre');
	var sled=document.createElement('span');    // status LED. indicate the communication with the server
	var opt_get=document.createElement('a');    //
	var opt_color=document.createElement('a');
	var opt_paste=document.createElement('a');
	var sdebug=document.createElement('span');
    var spacer=document.createElement('div');   // creates border & padding around the main screen
    var screen = document.createElement('div'); // holds dterm&cursor. origin of the cursor positioning
	var dterm=document.createElement('div');    // area that shows the screen
    var cursor=document.createElement('div');   // cursor

	function debug(s) {
		sdebug.innerHTML=s;
	}
	function error() {
		sled.className='off';
		debug("Connection lost timeout ts:"+((new Date).getTime()));
	}
	function opt_add(opt,name) {
		opt.className='off';
		opt.innerHTML=' '+name+' ';
		dstat.appendChild(opt);
		dstat.appendChild(document.createTextNode(' '));
	}
	function do_get(event) {
		opt_get.className=(opt_get.className=='off')?'on':'off';
		debug('GET '+opt_get.className);
	}
	function do_color(event) {
		var o=opt_color.className=(opt_color.className=='off')?'on':'off';
		if(o=='on')
			query1=query0+"&c=1&k=";
		else
			query1=query0+"&k=";
		debug('Color '+opt_color.className);
	}
	function is_clipboard_support() {
		if (window.clipboardData) {
			return true;
		} else if(window.netscape) {
			if (is_mozilla_clipboard_support() == '') {
				return true;
			} else {
				return false;
			}
		}
		return false;
	}
	function is_mozilla_clipboard_support(){
		try {
			netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
		} catch (err) {
			return err + '\nAccess denied, more info';
		}
		return '';
	}
	function mozilla_clipboard() {
		 // mozilla sucks
		if ((err=is_mozilla_clipboard_support()) != '') {
			debug(err);
			return undefined;
		}
		var clip = Components.classes["@mozilla.org/widget/clipboard;1"].createInstance(Components.interfaces.nsIClipboard);
		var trans = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
		if (!clip || !trans) {
			return undefined;
		}
		trans.addDataFlavor("text/unicode");
		clip.getData(trans,clip.kGlobalClipboard);
		var str=new Object();
		var strLength=new Object();
		try {
			trans.getTransferData("text/unicode",str,strLength);
		} catch(err) {
			return "";
		}
		if (str) {
			str=str.value.QueryInterface(Components.interfaces.nsISupportsString);
		}
		if (str) {
			return str.data.substring(0,strLength.value / 2);
		} else {
			return "";
		}
	}
	function do_paste(event) {
		var p=undefined;
		if (window.clipboardData) {
			p=window.clipboardData.getData("Text");
		} else if(window.netscape) {
			p=mozilla_clipboard();
		}
		if (p) {
			debug('Pasted');
			queue(encodeURIComponent(p));
		} else {
		}
	}
	function update() {
//		debug("ts: "+((new Date).getTime())+" rmax:"+rmax);
		if(sending==0) {
			sending=1;
			sled.className='on';
			var r=new XMLHttpRequest();
			var send="";
			while(keybuf.length>0) {
				send+=keybuf.pop();
			}
			var query=query1+send+"&t="+screenTimestamp;
            if (additionalQueryString)  query+='&'+additionalQueryString;
			if(opt_get.className=='on') {
				r.open("GET",endpoint+"?"+query,true);
				if(ie) {
					r.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
				}
			} else {
				r.open("POST",endpoint,true);
			}
			r.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
			r.onreadystatechange = function () {
//				debug("xhr:"+((new Date).getTime())+" state:"+r.readyState+" status:"+r.status+" statusText:"+r.statusText);
				if (r.readyState==4) {
					if(r.status==200) {
						window.clearTimeout(error_timeout);
						if(r.responseText.trim()!="") {
                            dterm.innerHTML = r.responseText;
							rmax=100;
						} else {
							rmax*=2;
							if(rmax>2000)
								rmax=2000;
						}

                        // update cursor position
                        var cxs = r.getResponseHeader("Cursor-X");
                        if(cxs!=null) {
                            var cx = new Number(cxs);
                            var cy = new Number(r.getResponseHeader("Cursor-Y"));
                            var sx = new Number(r.getResponseHeader("Screen-X"));
                            var sy = new Number(r.getResponseHeader("Screen-Y"));

                            var t=dterm.firstChild;
                            cursor.style.left=(dterm.offsetWidth*cx/sx)+"px";
                            cursor.style.top=(dterm.offsetHeight*cy/sy)+"px";
                            cursor.style.display="";
                        } else {
                            cursor.style.display="none";
                        }

						sending=0;
						sled.className='off';
						timeout=window.setTimeout(update,rmax);
                        screenTimestamp = r.getResponseHeader("Screen-Timestamp");
					} else {
						debug("Connection error status:"+r.status);
					}
				}
			}
			error_timeout=window.setTimeout(error,5000);
			if(opt_get.className=='on') {
				r.send(null);
			} else {
				r.send(query);
			}
		}
	}
	function queue(s) {
		keybuf.unshift(s);
		if(sending==0) {
			window.clearTimeout(timeout);
			timeout=window.setTimeout(update,1);
		}
	}
    // special keys that don't result in the keypress event.
    // we need to handle these in keydown
    var keyDownKeyCodes = {
        // see http://www.w3.org/TR/DOM-Level-3-Events/#determine-keydown-keyup-keyCode
        // also see http://www.javascripter.net/faq/keycodes.htm
        8:1, // Backspace
        9:1, // TAB
        27:1,   // Escape
        33:1,   // PageUp
        34:1,   // PageDown
        35:1,   // End
        36:1,   // Home
        37:1,   // Left
        38:1,   // Up
        39:1,   // Right
        40:1,   // Down
        45:1,   // Insert
        46:1,   // Del
        112:1, 113:1, 114:1, 115:1, 116:1, 117:1, 118:1, 119:1, 120:1, 121:1, 122:1, 123:1 // F1-F12
    };
	function keydown(ev) {
		if (!ev) ev=window.event;
        if ((keyDownKeyCodes[ev.keyCode] && ev.charCode==0) || ev.ctrlKey || ev.altKey) {
            // ev.charCode!=0 implies those are keys that produce ASCII codes
            return handleKey(ev,0);
        }
	}
	function keypress(ev) {
        if ((keyDownKeyCodes[ev.keyCode] && ev.charCode==0) || ev.ctrlKey || ev.altKey) {
            // we handled these in keydown
        } else {
            return handleKey(ev,ev.which)
        }
    }

    // which==0 appears to be used as a signel but not sure exactly why --- Kohsuke
    function handleKey(ev,which) {
		if (!ev) ev=window.event;
//		s="kp keyCode="+ev.keyCode+" which="+ev.which+" shiftKey="+ev.shiftKey+" ctrlKey="+ev.ctrlKey+" altKey="+ev.altKey;
//		debug(s);
//		return false;
//		else { if (!ev.ctrlKey || ev.keyCode==17) { return; }
		var kc;
		var k="";
		if (ev.keyCode)
			kc=ev.keyCode;
		if (which)
			kc=which;
		if (ev.altKey) {
			if (kc>=65 && kc<=90)
				kc+=32;
			if (kc>=97 && kc<=122) {
				k=String.fromCharCode(27)+String.fromCharCode(kc);
			}
		} else if (ev.ctrlKey) {
			if (kc>=65 && kc<=90) k=String.fromCharCode(kc-64); // Ctrl-A..Z
			else if (kc>=97 && kc<=122) k=String.fromCharCode(kc-96); // Ctrl-A..Z
			else if (kc==54)  k=String.fromCharCode(30); // Ctrl-^
			else if (kc==109) k=String.fromCharCode(31); // Ctrl-_
			else if (kc==219) k=String.fromCharCode(27); // Ctrl-[
			else if (kc==220) k=String.fromCharCode(28); // Ctrl-\
			else if (kc==221) k=String.fromCharCode(29); // Ctrl-]
			else if (kc==219) k=String.fromCharCode(29); // Ctrl-]
			else if (kc==219) k=String.fromCharCode(0);  // Ctrl-@
		} else if (which==0) {
			if (kc==9) k=String.fromCharCode(9);  // Tab
			else if (kc==8) k=String.fromCharCode(127);  // Backspace
			else if (kc==27) k=String.fromCharCode(27); // Escape
			else {
				if (kc==33) k="[5~";        // PgUp
				else if (kc==34) k="[6~";   // PgDn
				else if (kc==35) k="[4~";   // End
				else if (kc==36) k="[1~";   // Home
				else if (kc==37) k="[D";    // Left
				else if (kc==38) k="[A";    // Up
				else if (kc==39) k="[C";    // Right
				else if (kc==40) k="[B";    // Down
				else if (kc==45) k="[2~";   // Ins
				else if (kc==46) k="[3~";   // Del
				else if (kc==112) k="[[A";  // F1
				else if (kc==113) k="[[B";  // F2
				else if (kc==114) k="[[C";  // F3
				else if (kc==115) k="[[D";  // F4
				else if (kc==116) k="[[E";  // F5
				else if (kc==117) k="[17~"; // F6
				else if (kc==118) k="[18~"; // F7
				else if (kc==119) k="[19~"; // F8
				else if (kc==120) k="[20~"; // F9
				else if (kc==121) k="[21~"; // F10
				else if (kc==122) k="[23~"; // F11
				else if (kc==123) k="[24~"; // F12
				if (k.length) {
					k=String.fromCharCode(27)+k;
				}
			}
		} else {
			if (kc==8)
				k=String.fromCharCode(127);  // Backspace
			else
				k=String.fromCharCode(kc);
		}
		if(k.length) {
//			queue(encodeURIComponent(k));
			if(k=="+") {
				queue("%2B");
			} else {
				queue(escape(k));
			}
		}
		ev.cancelBubble=true;
		if (ev.stopPropagation) ev.stopPropagation();
		if (ev.preventDefault)  ev.preventDefault();
		return false;
	}
	function init() {
		sled.appendChild(document.createTextNode('\xb7'));
		sled.className='off';
		dstat.appendChild(sled);
		dstat.appendChild(document.createTextNode(' '));
		opt_add(opt_color,'Colors');
		opt_color.className='on';
		opt_add(opt_get,'GET');
		if (is_clipboard_support()) {
			opt_add(opt_paste,'Paste');
		}
		dstat.appendChild(sdebug);
		dstat.className='stat';
        div.appendChild(fitter);
        fitter.className = 'fitter';
        fitter.appendChild(dstat);
        fitter.appendChild(spacer);
        spacer.className='spacer';
        spacer.appendChild(screen);
        screen.className='screen';
        screen.appendChild(dterm);
		if(opt_color.addEventListener) {
			opt_get.addEventListener('click',do_get,true);
			opt_color.addEventListener('click',do_color,true);
			if (is_clipboard_support()) {
				opt_paste.addEventListener('click',do_paste,true);
			}
		} else {
			opt_get.attachEvent("onclick", do_get);
			opt_color.attachEvent("onclick", do_color);
			if (is_clipboard_support()) {
				opt_paste.attachEvent("onclick", do_paste);
			}
		}
		window.onkeypress=keypress;
        window.onkeydown=keydown;
		timeout=window.setTimeout(update,100);

        cursor.style.position="absolute";
        cursor.style.color="white";
        cursor.style.zIndex="999";
        cursor.innerHTML="_";
        screen.appendChild(cursor);
	}
	init();
};




© 2015 - 2025 Weber Informatics LLC | Privacy Policy