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

no.tsl2.nano.h5.2.5.1.source-code.websocket.client.js.template Maven / Gradle / Ivy

Go to download

TSL2 Framework Html5 Extensions (WebServer, Html5Presentation, RuleCover, BeanConfigurator, LogicTable-Sheet, Expression-Descriptors for Actions, Rules, URLs, Queries)

There is a newer version: 2.5.3
Show newest version
/*
 * javascript websocket-client implementation for nano.h5 (cr Thomas Schneider / 2014) 
 */
// to see the source in browser dev source tab, we give it a name
//# sourceURL=websocket.client.js

setTheme(false);

/**
 * websocket client implementation.
 */
var socket = new WebSocket(
		'ws${app.ssl.shortcut}://' + window.document.location.hostname + ':${websocket.server.port}');
console.log('websocket created:' + socket);

socket.onopen = function() {
	console.log('connecting websocket');
	// socket.send('websocket connected');
};

socket.onerror = function(error) {
	console.log('websocket error ' + error);
	if (${websocket.window.alert.message})
		window.alert("websocket error occurred! " + error + "\n\ndependency listeners, content assists and attachment uploading dont work!");
};

/**
 * print messages from server, or fill input-assist options
 */
socket.onmessage = function(e) {
	console.log('handling message \'' + e.data + '\'');
	if (e.data == 'submit')
		document.getElementById('progressbar').removeAttribute('hidden');
	else if (e.data.indexOf('/inputassist') == 0) {
		fillInputOptions(e.data);
	} else if (e.data.indexOf('/dependency') == 0) {
		refreshdependency(e.data);
	} else if (e.data.indexOf('/attachment') == 0) {
		// TODO: impl.
	} else if (e.data.indexOf('/broadcast') == 0) {
		showBroadcastMessage(e.data);
	} else if (e.data.indexOf('/dialog') >= 0) {
		showDialog(e.data);
	} else
		showStatusMessage(e.data);
};

socket.onclose = function(e) {
	console.log('websocket closed! code: ' + e.code + ', reason: \'' + e.reason
			+ '\'');
};

/*
 * // Sending canvas ImageData as ArrayBuffer var img =
 * canvas_context.getImageData(0, 0, 400, 320); var binary = new
 * Uint8Array(img.data.length); for (var i = 0; i < img.data.length; i++) {
 * binary[i] = img.data[i]; } socket.send(binary.buffer); // Sending file as
 * Blob var file = document.querySelector('input[type="file"]').files[0];
 * socket.send(file);
 */

/**
 * prints the given status message to the status line
 */
function showStatusMessage(msg) {
	console.log(msg);
	var wsElement = document.getElementById('${websocket.element.id}');
	if (wsElement != null)
		wsElement.childNodes[0].nodeValue = ' \t' + msg;
	//user must enable this feature in his browser...
	window.status = msg;
}

/**
 * prints the given broadcast message
 */
function showBroadcastMessage(msg) {
//	document.getElementById('${broadcast.element.id}').childNodes[0].nodeValue = ' \t'
//			+ msg;
	if (${websocket.speak.alert.message})
		speak(msg);
	if (${websocket.window.alert.message})
		window.alert(getValue(msg));
}

function speak(msg) {
	var synth = window.speechSynthesis;
	var utterThis = new SpeechSynthesisUtterance(msg);
	synth.speak(utterThis);
}

/**
 * different browser implementations: IE and Chrome use event.srcElement - all others event.target
 */
function target(e) {
	return e.srcElement || e.target; 
}

/**
 * each field having an InputAssist implementation will call this function on
 * 'onkeypress'.
 */
function inputassist(e) {
	var code;
	if (e.keyCode)
		code = e.keyCode;
	else if (e.which)
		code = e.which;
	var text = target(e).value + String.fromCharCode(code);
	var request = createMessage('inputassist', target(e).id, text);
	console.log('sending input-assist request: \'' + request + '\'');
	socket.send(request);
}

/**
 * will be called, if websocket-server returns with a response like:
 * 
 * @fieldID:value1,value2,...
 */
function fillInputOptions(msg) {
	showStatusMessage('input-assist-response: ' + msg);
	var id = getId(msg);
	var value = getValue(msg);
	var list = value.substring(1, value.length - 1);
	console.log('creating input assist for ' + id + ' with elements: ' + list);

	// first, we remove the last input-assist
	var e = document.getElementById(id);
	e.setAttribute('list', id + '.datalist');
	//e = e.parentNode;
	var lastSelect = e.getElementsByTagName('datalist');
	if (lastSelect.length > 0)
		e.removeChild(lastSelect[0]);

	// now, the new options should be filled
	var select = e.appendChild(document.createElement('datalist'));
	select.setAttribute('name', id + '.datalist');
	select.setAttribute('id', id + '.datalist');
	var items = list.split(',');
	var option;
	for ( var i = 0; i < items.length; i++) {
		console.log('creating option \'' + items[i] + '\'');
		option = select.appendChild(document.createElement('option'));
		option.setAttribute('value', items[i]);
		// select.setAttribute('onclick', 'inputassistselect(event)');
		option.appendChild(document.createTextNode(items[i]));
	}

}

function getTarget(msg) {
	return msg.substring(1, msg.indexOf('@'));
}

function getId(msg) {
	return msg.substring(msg.indexOf('@') + 1, msg.indexOf(':'));
}

function getValue(msg) {
	return msg.substring(msg.indexOf(':') + 1);
}

function createMessage(target, id, value) {
	return createMessage(target, id, value, -1, -1);
}

function createMessage(target, id, value, clientX, clientY) {
	return '/' + target + '@' + id + '?' + clientX + ',' + clientY + ':'
			+ value;
}

/**
 * after an input-assist request and the following server response, a
 * selection list was provided for the user. if the user selects an item of this
 * list, the selected item value should be transferred to the input field and
 * the selection-element should be removed.
 */
/*
function inputassistselect(e) {
	console.log('transerring selected value \'' + target(e).value
			+ '\' to element: ' + target(e).name);
	var inputelement = document.getElementById(target(e).name);
	// setAttribute doesn't work here (on chrome), so we set the value directly.
	inputelement.setAttribute('value', target(e).value);
	inputelement.value = target(e).value;

	target(e).parentNode.removeChild(target(e));
}
*/
function getPosition(element) {
	var xPosition = 0;
	var yPosition = 0;

	while (element) {
		xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft);
		yPosition += (element.offsetTop - element.scrollTop + element.clientTop);
		element = element.offsetParent;
	}
	return {
		x : xPosition,
		y : yPosition
	};
}

/**
 * if an attribute has change listeners, the server will evaluate the new values
 * for that listeners, calling refreshdependency() for each listener to refresh
 * it's value on client side.
 */
function evaluatedependencies(e) {
	var x = -1, y = -1;
	if (e.clientX) {
		var parentPosition = getPosition(e.currentTarget);
		x = e.clientX - parentPosition.x;
		y = e.clientY - parentPosition.y;
	}
	var msg = createMessage('dependency', target(e).id, target(e).value,
			x, y);
	if (!${app.login.secure}) {
		showStatusMessage(msg);
	}
	socket.send(msg);
}

/**
 * if dependency-listeners are defined for value changes on an input field, the
 * server will inform these for the changes.
 */
function refreshdependency(msg) {
	if (!${app.login.secure}) {
		showStatusMessage('refreshing dependency: ' + msg);
	}
	var id = getId(msg);
	var value = getValue(msg);
	if (value != null)
		document.getElementById(id).value = value;
}

/**
 * sends a selected file to the server
 */
function transferattachment(src) {
	// Sending file as Blob
	var file = document.querySelector('input[type="file"]').files[0];
	showStatusMessage('sending attachment: ' + file.name);
	// first send the file name
	socket.send(createMessage('attachment', src.id, file.name));
	// now, send the bytes
	socket.send(file);
}

/**
 * html5 clipboard api (not used yet!)
 */
document.addEventListener('paste', function(e){
    if(e.clipboardData.types.indexOf('text/plain') > -1){
        processDataFromClipboard(e.clipboardData.getData('text/plain'));
//        e.preventDefault(); // We are already handling the data from the clipboard, we do not want it inserted into the document
    }
});

function processDataFromClipboard(clipboard) {
	var target = document.getElementById('clipboard.paste.target');
	if (target != null) {
		target.nodeValue = clipboard;
	}
}

/*
 * not working yet...
 */
function fade(btn) {
	document.getElementsByTagName("body")[0].className = "fade-out";
}

function disablePage(e) {
	e = e || window.event;

  var all = document.querySelectorAll("#container select, #container input, #container textarea, #container button");
  for (let el of all) { el.disabled = true; }

//	gp = document.getElementById('glasspane');    
//	gp.style.display='none';
//	e.stopPropagation();
}

 /**
  * used in HtmlUtil.java
  */
function openNav() {
    document.getElementById("tslSidenav").style.width = "250px";
    document.getElementById("glasspane").style.marginLeft = "250px";
    document.body.style.backgroundColor = "rgba(0,0,0,0.4)";
}

function closeNav() {
    document.getElementById("tslSidenav").style.width = "0";
    document.getElementById("glasspane").style.marginLeft= "0";
    document.body.style.backgroundColor = "white";
}

/**
 * if a submit (reload page from server) was requested, disable the current page and don't handle the event further...
 */
window.addEventListener('onsubmit', function(e){
	disablePage(e);
});
document.addEventListener('ondblclick', function(e){
	disablePage(e);
});

function showDialog(htmlDlg) {
	htmlDlg = htmlDlg.substring(8); // '/dialog:'
	if (isHex(htmlDlg))
		htmlDlg = hex2a(htmlDlg);
	//create the html dialog
	body = document.getElementsByTagName("body")[0];
	body.insertAdjacentHTML('afterbegin', htmlDlg);

	//show the dialog
	var formDialog = document.getElementById('wsdialog.formDialog');
	formDialog.showModal();

	//listen to the events
	document.getElementById('wsdialog.button').onclick = function() {
		elements = document.getElementsByName("wsdialog.formDialog");
		var values = value;
		if (elements.length > 0) {
			values += "::{";
			for (let i = 0; i < elements.length; i++) {
				const e = elements[i];
				values += e.name + ":" + e.value + ",";
			}
			values += "}";
		}
		formDialog.close(values);
	};
	document.getElementById('wsdialog.formDialog').addEventListener('close', function() {
		var result = createMessage('dialog', "returnvalue", formDialog.returnValue);
		console.log('sending dialog result: \'' + result + '\'');
		socket.send(result);
	});
}

function hex2a(hexx) {
    var hex = hexx.toString();//force conversion
    var str = '';
    for (var i = 0; (i < hex.length && hex.substr(i, 2) !== '00'); i += 2)
		str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
	console.log('hex2ascii: ' + str);
    return str;
}
function isHex(h) {
	var a = parseInt(h,16);
	return (a.toString(16) ===h.toLowerCase())
}

function selectOnClick(e) {
	e = e || window.event;
	this_ = target(e).parentElement

	/*if (e.originalEvent.detail < 2 || window.event.originalEvent.detail < 2) */
	this_.getElementsByTagName('input')[0].checked = !this_.getElementsByTagName('input')[0].checked;
}

function openOnDblClick(e) {
	e = e || window.event;
	this_ = target(e).parentElement
	
	location=this_.getElementsByTagName('a')[0];
	disablePage(e);
}
function toggleOnClick() {
	setTheme(true);
}

function setTheme(next) {
	const themes = ['dark', 'light', 'dark-contrast', 'light-contrast'];
    var currentTheme = document.documentElement.getAttribute("data-theme");
	if (currentTheme === null)
		currentTheme = localStorage.getItem('data-theme');
	var index = themes.indexOf(currentTheme);

	if (next == true) {
		if (index < themes.length - 1) 
			index++
		else
			index = 0;
	}
	var targetTheme = themes[index];
    document.documentElement.setAttribute('data-theme', targetTheme);
    localStorage.setItem('data-theme', targetTheme);
    console.log('data-theme: ' + targetTheme);
};




© 2015 - 2025 Weber Informatics LLC | Privacy Policy