Skip this dialog in the future");
$("body").append(div);
function
doClose()
{
if($(div).find("input:checked").length)
FW_cmd(FW_root+"?cmd=attr "+wn+" confirmDelete 0&XHR=1");
$(this).dialog("close"); $(div).remove();
}
$(div).dialog({
dialogClass:"no-close", modal:true, width:"auto", closeOnEscape:true,
maxWidth:$(window).width()*0.9, maxHeight:$(window).height()*0.9,
buttons: [
{text:"Yes", click:function(){ location.href = ma[0]; doClose(); }},
{text:"No", click:function(){ doClose(); }}]
});
});
});
}
// Show the webCmd list in a dialog if: smallScreen & hiddenroom=detail & room
function
FW_smallScreenCommands()
{
if($("div#menu select").length == 0 || // not SmallScreen
$("div#content").attr("room") == undefined || // not room Overview
$("div#content div.col1 a").length > 0) // no hiddenroom=detail
return;
$("div#content div.col1").each(function(){
var tr = $(this).closest("tr");
if($(tr).find("> td").length <= 2)
return;
$(this).html("
");
if(row++ == 0) {
$(t).find("tr:last").append($(this).find("a").html());
} else {
$(this).attr("data-orig", 1);
this.orig=$(this).parent();
$(t).find("tr:last").append($(this).detach());
}
});
FW_okDialog(t, this, function(){
$("#FW_okDialog [data-orig]").each(function(){
$(this).detach().appendTo(this.orig);
});
});
});
});
}
if(window.jQuery) {
$(document).ready(FW_jqueryReadyFn);
} else {
// FLOORPLAN compatibility
loadScript("pgm2/jquery.min.js", function() {
loadScript("pgm2/jquery-ui.min.js", function() {
FW_jqueryReadyFn();
}, true);
}, true);
}
// FLOORPLAN compatibility
function
FW_delayedStart()
{
setTimeout("FW_longpoll()", 100);
}
function
log(txt)
{
var d = new Date();
var ms = ("000"+(d.getMilliseconds()%1000));
ms = ms.substr(ms.length-3,3);
txt = d.toTimeString().substring(0,8)+"."+ms+" "+txt;
if(typeof window.console != "undefined")
console.log(txt);
}
function
addcsrf(arg)
{
if(typeof FW_csrfToken != "undefined") {
arg = arg.replace(/&fwcsrf=[^&]*/,'');
arg += '&fwcsrf='+encodeURIComponent(FW_csrfToken);
}
return arg;
}
function
FW_csrfRefresh(callback)
{
log("FW_csrfRefresh, last was "+(FW_csrfOk ? "ok":"bad"));
if(!FW_csrfOk) // avoid endless loop
return;
$.ajax({
url:location.pathname+"?XHR=1",
success: function(data, textStatus, request){
FW_csrfToken = request.getResponseHeader('x-fhem-csrftoken');
FW_csrfOk = false;
if(callback)
callback();
}
});
}
function
FW_cmd(arg, callback)
{
if(arg.length < 120)
log("FW_cmd:"+arg);
else
log("FW_cmd:"+arg.substr(0,120)+"...");
$.ajax({
url:addcsrf(arg)+'&fw_id='+$("body").attr('fw_id'),
method:'POST',
success: function(data, textStatus, req){
FW_csrfOk = true;
if(callback)
callback(req.responseText);
else if(req.responseText)
FW_errmsg(req.responseText, 5000);
},
error:function(xhr, status, err) {
if(xhr.status == 400 && typeof FW_csrfToken != "undefined") {
FW_csrfToken = "";
FW_csrfRefresh(function(){FW_cmd(arg, callback)});
}
}
});
}
function
FW_errmsg(txt, timeout)
{
log("ERRMSG:"+txt+"<");
var errmsg = document.getElementById("errmsg");
if(!errmsg) {
if(txt == "")
return;
errmsg = document.createElement('div');
errmsg.setAttribute("id","errmsg");
document.body.appendChild(errmsg);
}
if(txt == "") {
document.body.removeChild(errmsg);
return;
}
errmsg.innerHTML = txt;
if(timeout)
setTimeout("FW_errmsg('')", timeout);
}
function
FW_okDialog(txt, parent, removeFn)
{
var div = $("
");
$(div).html(txt);
$("body").append(div);
var oldPos = $("body").scrollTop();
$(div).dialog({
dialogClass:"no-close", modal:true, width:"auto", closeOnEscape:true,
maxWidth:$(window).width()*0.9, maxHeight:$(window).height()*0.9,
buttons: [{text:"OK", click:function(){
$(this).dialog("close");
if(removeFn)
removeFn();
$(div).remove();
}}]
});
FW_replaceWidgets(div);
$(div).find("a").each(function(){FW_replaceLink(this);}); //Forum #33766
if(parent)
$(div).dialog( "option", "position", {
my: "left top", at: "right bottom",
of: parent, collision: "flipfit"
});
setTimeout(function(){$("body").scrollTop(oldPos);}, 1); // Not ideal.
}
function
FW_menu(evt, el, arr, dis, fn, embedEl)
{
if(!embedEl)
evt.stopPropagation();
if($("#fwmenu").length) {
delfwmenu();
return;
}
var html = '';
$("body").append(html);
function
delfwmenu()
{
$("ul#fwmenu").remove();
$('html').unbind('click.fwmenu');
}
var wt = $(window).scrollTop();
$("#fwmenu")
.menu({
select: function(e,ui) { // changes the scrollTop();
e.stopPropagation();
fn($(e.currentTarget).find("[row]").attr("row"));
delfwmenu();
setTimeout(function(){ $(window).scrollTop(wt) }, 1); // Bug in select?
}
});
var off = $(el).offset();
if(embedEl) {
var embOff = $(embedEl).offset();
off.top += embOff.top;
off.left += embOff.left;
}
var dH = $("#fwmenu").height(), dW = $("#fwmenu").width(),
wH = $(window).height(), wW = $(window).width();
var ey = off.top+dH+20, ex = off.left+dW;
if(ex>wW && ey>wH) { off.top -= dH; off.left -= (dW+16);
} else if(ey > wH) { off.top -= dH; off.left += 20;
} else if(ex > wW) { off.left -= (dW+16);
} else { off.top += 20;
}
$("#fwmenu").css(off);
$('html').bind('click.fwmenu', function() { delfwmenu(); });
}
function
FW_getLink(el)
{
var attr = $(el).attr("href");
if(!attr) {
attr = $(el).attr("onclick"); // Tablet/smallScreen version
if(!attr)
return "";
attr = attr.replace(/^location.href='/,'');
attr = attr.replace(/'$/,'');
}
return attr;
}
function
FW_replaceLink(el)
{
var attr = FW_getLink(el);
if(!attr)
return;
var ma = attr.match(/^(.*\?)(cmd[^=]*=.*)$/);
if(ma == null || ma.length == 0 || !ma[2].match(/=(save|set)/)) {
ma = attr.match(new RegExp("^"+FW_root)); // Avoid "Connection lost" @iOS
if(ma) {
$(el).click(function(e) {
// Open link in window/tab, Forum #39154
if(e.shiftKey || e.ctrlKey || e.metaKey || e.button == 1)
return;
e.preventDefault();
FW_leaving = 1;
if($(el).attr("target") == "_blank") {
window.open(attr, '_blank').focus();
} else {
location.href = attr;
}
});
}
return;
}
$(el).removeAttr("href");
$(el).removeAttr("onclick");
$(el).click(function() {
FW_cmd(attr+"&XHR=1", function(txt){
if(!txt)
return;
if(ma[2].match(/=set/)) // Forum #38875
FW_okDialog('
'+txt+'', el);
else
FW_errmsg(txt, 5000);
});
});
$(el).css("cursor", "pointer");
}
function
FW_htmlQuote(text)
{
return text.replace(/&/g, '&') // Same as in 01_FHEMWEB
.replace(//g, '>');
}
function
FW_inlineModify() // Do not generate a new HTML page upon pressing modify
{
var cm;
if( typeof AddCodeMirror == 'function' ) {
// init codemirror for FW_style edit textarea
AddCodeMirror($('textarea[name="data"]'));
}
$('#DEFa').click(function(){
var old = $('#edit').css('display');
$('#edit').css('display', old=='none' ? 'block' : 'none');
$('#disp').css('display', old=='none' ? 'none' : 'block');
if( typeof AddCodeMirror == 'function' ) {
var s=document.getElementById("edit").getElementsByTagName("textarea");
AddCodeMirror(s[0], function(pcm) {cm = pcm;});
}
});
$("div input.psc[type=submit]:not(.get)").click(function(e){
e.preventDefault();
var newDef = typeof cm !== 'undefined' ?
cm.getValue() : $(this).closest("form").find("textarea").val();
var cmd = $(this).attr("name")+"="+$(this).attr("value")+" "+newDef;
var isDef = true, reloadIfOk = false;
if(newDef == undefined || $(this).attr("value").indexOf("modify") != 0) {
isDef = false;
var div = $(this).closest("div.makeSelect");
var devName = $(div).attr("dev"),
cmd = $(div).attr("cmd");
var sel = $(this).closest("form").find("select");
var arg = $(sel).val();
var ifid = (devName+"-"+arg).replace(/([^_a-z0-9])/gi,
function(m){ return "\\"+m });
if($(".dval[informid="+ifid+"]").length == 0) {
if(cmd == "attr") {
reloadIfOk = true;
} else {
$(this).unbind('click').click();// No element found to replace, reload
return;
}
}
newDef = $(this).closest("form").find("input:text").val();
if(newDef == undefined)
newDef = $(this).closest("form").find("[name^=val]").val();
cmd = $(this).attr("name")+"="+cmd+" "+devName+" "+arg+" "+newDef;
}
FW_cmd(FW_root+"?"+encodeURIComponent(cmd)+"&XHR=1", function(resp){
if(!resp && reloadIfOk)
location.reload();
if(resp) {
resp = FW_htmlQuote(resp);
if(resp.indexOf("\n") >= 0)
resp = ''+resp+' ';
return FW_okDialog(resp);
}
if(isDef) {
if(newDef.indexOf("\n") >= 0)
newDef = ''+newDef+' ';
else
newDef = FW_htmlQuote(newDef);
$("div#disp").html(newDef).css("display", "");
$("div#edit").css("display", "none");
}
});
});
}
function
FW_rawDef()
{
$("div.rawDef a").each(function(){ // Help on detail window
var dev = FW_getLink(this).split(" ").pop().split("&")[0];
$(this).unbind("click");
$(this).attr("href", "#"); // Desktop: show underlined Text
$(this).removeAttr("onclick");
$(this).click(function(evt){
if($("#rawDef").length) {
$("#rawDef").remove();
return;
}
var textAreaStyle = typeof AddCodeMirror == 'function'?'opacity:0':'';
$("#content").append(''+
''+
'Execute commands '+
' Dump "Probably associated with" too '+
'
');
var cmVar;
function
fillData(opt)
{
var s = $('#rawDef textarea');
FW_cmd(FW_root+"?cmd=list "+opt+" "+dev+"&XHR=1", function(data) {
var re = new RegExp("^define", "gm");
data = data.replace(re, "defmod");
s.val(data);
var off = $("#rawDef").position().top-20;
$('body, html').animate({scrollTop:off}, 500);
$("#rawDef button").hide();
var propertychange = function() {
var nData = $("#rawDef textarea").val();
if(nData != data)
$("#rawDef button").show();
else
$("#rawDef button").hide();
};
s.bind('input propertychange', propertychange);
if(cmVar) {
cmVar.setValue(data);
} else if(typeof AddCodeMirror == 'function') {
AddCodeMirror(s, function(cm) {
cmVar = cm;
cm.on("change", function() {
s.val(cm.getValue());
propertychange();
})
});
}
});
}
fillData("-r");
$("#rawDef input").click(function(){fillData(this.checked ?"-R":"-r")});
$("#rawDef button").click(function(){
var data = $("#rawDef textarea").val();
var arr = data.split("\n"), str="", i1=-1;
function
doNext()
{
if(++i1 >= arr.length) {
return FW_okDialog("Executed everything, no errors found.");
}
str += arr[i1];
if(arr[i1].charAt(arr[i1].length-1) === "\\") {
str += "\n";
return doNext();
}
if(str != "") {
str = str.replace(/\\\n/g, "\n")
.replace(/;;/g, ";");
FW_cmd(FW_root+"?cmd."+dev+"="+encodeURIComponent(str)+"&XHR=1",
function(r){
if(r)
return FW_okDialog(''+r+' ');
str = "";
doNext();
});
} else {
doNext();
}
}
doNext();
});
});
});
}
var FW_arrowDown, FW_arrowRight;
function
FW_treeMenu()
{
var a = $("a").get(0);
var col = 'rgb(39, 135, 38)';
if(window.getComputedStyle && a)
col = getComputedStyle(a,null).getPropertyValue('color');
FW_arrowRight = 'data:image/svg+xml;utf8, '
.replace('gray', col);
FW_arrowDown =FW_arrowRight.replace('/>',' transform="rotate(90,896,896)"/>');
var fnd;
$("div#menu table.room").each(function(){ // one loop per Block
var t = this, ma = {};
$(t).find("td > div > a > span").each(function(e){
var span = this, spanTxt = $(span).text().replace(/,/g,'');
var ta = spanTxt.split("->");
if(ta.length <= 1)
return;
fnd = true;
var nxt="", lst="", tr=$(span).closest("tr");
for(var i1=0; i1"+ta[i1];
if(!ma[nxt]) {
$(tr).before("");
}
ma[nxt] = true;
lst = nxt;
}
$(span).html(ta[ta.length-1]);
$(tr).attr("data-mTree", nxt)
.addClass("menuTree level"+(ta.length-1));
});
});
if(fnd) {
$("head").append(
"");
var t = $("div#menu table.room");
$(t).find("tr[data-mTree]").not(".level0").hide();
$(t).find("tr.menuTree").click(function(){treeClick(this)});
$(t).find("tr.menuTree > td > div > div")
.css("background-image", "url('"+FW_arrowRight+"')");
var selRoom = $("div#content").attr("room");
if(selRoom) {
var ta = selRoom.split("->"), nxt="";
for(var i1=0; i1"+ta[i1]);
treeClick($(t).find("tr.menuTree[data-nxt="+nxt+"]"));
}
}
}
function
treeClick(el)
{
var tgt = FW_escapeSelector($(el).attr("data-nxt"));
if($(el).hasClass("closed")) {
$(el).closest("table").find("tr[data-mTree="+tgt+"]").show();
$(el).find("div>div").css("background-image", "url('"+FW_arrowDown+"')");
} else {
$(el).closest("table").find("tr[data-mTree^="+tgt+"]")
.hide().addClass("closed");
$(el).find("div>div").css("background-image", "url('"+FW_arrowRight+"')");
}
$(el).toggleClass("closed");
$(el).toggleClass("open");
};
}
function
FW_escapeSelector(s)
{
if(typeof s != 'string')
return s;
return s.replace(/[ .#\[\]>]/g, function(r) { return '\\'+r });
}
/*************** LONGPOLL START **************/
var FW_pollConn;
var FW_longpollOffset = 0;
var FW_leaving;
var FW_lastDataTime=0;
function
FW_doUpdate(evt)
{
var errstr = "Connection lost, trying a reconnect every 5 seconds.";
var input="";
var retryTime = 5000;
var now = new Date()/1000;
// iOS closes HTTP after 60s idle, websocket after 240s idle
if(now-FW_lastDataTime > 59) {
errstr="";
retryTime = 100;
}
FW_lastDataTime = now;
// Websocket starts with Android 4.4, and IE10
if(typeof WebSocket == "function" && evt && evt.target instanceof WebSocket) {
if(evt.type == 'close' && !FW_leaving) {
FW_errmsg(errstr, retryTime-100);
FW_pollConn.close();
FW_pollConn = undefined;
setTimeout(FW_longpoll, retryTime);
return;
}
input = evt.data;
FW_longpollOffset = 0;
} else {
if(FW_pollConn.readyState == 4 && !FW_leaving) {
if(FW_pollConn.status == "400") {
location.reload();
return;
}
FW_errmsg(errstr, retryTime-100);
setTimeout(FW_longpoll, retryTime);
return;
}
if(FW_pollConn.readyState != 3)
return;
input = FW_pollConn.responseText;
}
var devs = new Array();
if(!input || input.length <= FW_longpollOffset)
return;
FW_serverLastMsg = (new Date()).getTime()/1000;
for(;;) {
var nOff = input.indexOf("\n", FW_longpollOffset);
if(nOff < 0)
break;
var l = input.substr(FW_longpollOffset, nOff-FW_longpollOffset);
FW_longpollOffset = nOff+1;
log("Rcvd: "+(l.length>132 ? l.substring(0,132)+"...("+l.length+")":l));
if(!l.length)
continue;
if(l.indexOf("<")== 0) { // HTML returned by proxy, if FHEM behind is dead
FW_closeConn();
FW_errmsg(errstr, retryTime-100);
setTimeout(FW_longpoll, retryTime);
return;
}
var d = JSON.parse(l);
if(d.length != 3)
continue;
function
setValue(d) // is Callable from eval below
{
$("[informId='"+d[0]+"']").each(function(){
if(this.setValueFn) { // change the select/etc value
this.setValueFn(d[1].replace(/\n/g, '\u2424'));
} else {
if(d[2].match(/\n/) && !d[2].match(/<.*>/)) // format multiline
d[2] = ''+d[2]+' ';
var ma = /^([\s\S]*)<\/html>$/.exec(d[2]);
if(!d[0].match("-")) // not a reading
$(this).html(d[2]);
else if(ma)
$(this).html(ma[1]);
else
$(this).text(d[2]);
if(d[0].match(/-ts$/)) // timestamps
$(this).addClass('changed');
$(this).find("a").each(function() { FW_replaceLink(this) });
}
});
}
if( d[0].match(/^#FHEMWEB:/) ) {
eval(d[1]);
} else {
setValue(d);
}
// updateLine is deprecated, use setValueFn
for(var w in FW_widgets)
if(FW_widgets[w].updateLine && !FW_widgets[w].second)
FW_widgets[w].updateLine(d);
devs.push(d);
}
// used for SVG to avoid double-reloads
for(var w in FW_widgets)
if(FW_widgets[w].updateDevs && !FW_widgets[w].second)
FW_widgets[w].updateDevs(devs);
// reset the connection to avoid memory problems
if(FW_longpollOffset > 1024*1024 && FW_longpollOffset==input.length)
FW_longpoll();
}
function
FW_closeConn()
{
FW_leaving = 1;
if(!FW_pollConn)
return;
if(typeof FW_pollConn.close == "function")
FW_pollConn.close();
else if(typeof FW_pollConn.abort == "function")
FW_pollConn.abort();
FW_pollConn = undefined;
}
function
FW_longpoll()
{
FW_closeConn();
FW_leaving = 0;
FW_longpollOffset = 0;
// Build the notify filter for the backend
var filter = $("body").attr("longpollfilter");
if(filter == null)
filter = "";
var retry;
if(filter == "") {
$("embed").each(function() { // wait for all embeds to be there
if(retry)
return;
var ed = FW_getSVG(this);
if(!retry && ed == undefined && filter != ".*" && --embedLoadRetry > 0) {
retry = 1;
setTimeout(FW_longpoll, 100);
return;
}
if(ed && $(ed).find("svg[flog]").attr("flog"))
filter=".*";
});
if(retry)
return;
}
if(filter == "") {
if(FW_urlParams.room) filter="room="+FW_urlParams.room;
if(FW_urlParams.detail) filter=FW_urlParams.detail;
}
if($("#floorplan").length>0) //floorplan special
filter += ";iconPath="+$("body").attr("name");
if(filter == "") {
var content = document.getElementById("content");
if(content) {
var room = content.getAttribute("room");
if(room)
filter="room="+room;
}
}
var iP = $("body").attr("iconPath");
if(iP != null)
filter = filter +";iconPath="+iP;
var since = "null";
if(FW_serverGenerated)
since = FW_serverLastMsg + (FW_serverGenerated-FW_serverFirstMsg);
var query = "?XHR=1"+
"&inform=type=status;filter="+filter+";since="+since+";fmt=JSON"+
'&fw_id='+$("body").attr('fw_id')+
"×tamp="+new Date().getTime();
var loc = (""+location).replace(/\?.*/,"");
if(typeof WebSocket == "function" && FW_longpollType == "websocket") {
FW_pollConn = new WebSocket(loc.replace(/[#&?].*/,'')
.replace(/^http/i, "ws")+query);
FW_pollConn.onclose =
FW_pollConn.onerror =
FW_pollConn.onmessage = FW_doUpdate;
FW_pollConn.onopen = function(){FW_wsPing(FW_pollConn);};
} else {
FW_pollConn = new XMLHttpRequest();
FW_pollConn.open("GET", location.pathname+query, true);
if(FW_pollConn.overrideMimeType) // Win 8.1, #66004
FW_pollConn.overrideMimeType("application/json");
FW_pollConn.onreadystatechange = FW_doUpdate;
FW_pollConn.send(null);
}
log("Inform-channel opened ("+(FW_longpollType==1 ? "HTTP":FW_longpollType)+
") with filter "+filter);
}
function
FW_wsPing(conn) // idle websockets are closed by the browser after 55sec
{
if(!conn || conn.readyState != conn.OPEN)
return;
conn.send("\n");
// setTimeout(function(){FW_wsPing(conn);}, 30000);
}
/*************** LONGPOLL END **************/
/*************** WIDGETS START **************/
/*************** "Double" select in detail window ****/
function
FW_detailSelect(selEl, mayMissing)
{
if(selEl.target)
selEl = selEl.target;
var selVal = $(selEl).val();
var div = $(selEl).closest("div.makeSelect");
if(!div.attr("list")) // hiddenRoom=input
return;
var arg,
listArr = $(div).attr("list").split(" "),
devName = $(div).attr("dev"),
cmd = $(div).attr("cmd");
var i1;
for(i1=0; i1 selVal.length)
vArr = arg.substr(selVal.length+1).split(",");
}
FW_replaceWidget($(selEl).next(), devName, vArr,undefined,selVal,
undefined, undefined, undefined,
function(newEl) {
if(cmd == "attr")
FW_queryValue('{AttrVal("'+devName+'","'+selVal+'","")}', newEl);
if(cmd == "set")
FW_queryValue('{ReadingsVal("'+devName+'","'+selVal+'","")}', newEl);
});
}
function
FW_callCreateFn(elName, devName, vArr, currVal, set, params, cmd, finishFn)
{
for(var wn in FW_widgets) {
if(FW_widgets[wn].createFn && !FW_widgets[wn].second) {
var newEl = FW_widgets[wn].createFn(elName, devName, vArr,
currVal, set, params, cmd);
if(newEl)
return finishFn(wn, newEl);
}
}
var v0 = vArr[0].split("-")[0];
if(v0.indexOf("uzsu") == 0)
v0 = "uzsu";
if(FW_availableJs[v0]) {
loadScript("pgm2/fhemweb_"+v0+".js", function() {
if(FW_widgets[vArr[0]].createFn)
var newEl = FW_widgets[vArr[0]].createFn(elName, devName, vArr,
currVal, set, params, cmd);
finishFn(vArr[0], newEl);
});
} else {
finishFn();
}
}
function
FW_replaceWidget(oldEl,devName,vArr,currVal,reading,set,params,cmd,readyFn)
{
var elName = $(oldEl).attr("name");
if(!elName)
elName = $(oldEl).find("[name]").attr("name");
if(vArr.length == 0) { // No parameters, input field
var newEl = FW_createTextField(elName, devName, ["textField"], currVal,
set, params, cmd);
finishFn("textField", newEl);
} else {
return FW_callCreateFn(elName, devName, vArr, currVal, set,
params, cmd, finishFn);
}
function
finishFn(wn, newEl)
{
if(!newEl) {
vArr.unshift("select");
newEl = FW_createSelect(elName,devName,vArr,currVal,set,params,cmd);
wn = "select";
}
if(!newEl) { // Simple link
newEl = $('');
$(newEl).click(function(arg) { cmd(params[0]) });
$(oldEl).replaceWith(newEl);
if(readyFn)
return readyFn(newEl);
return;
}
$(newEl).addClass(wn+"_widget");
if( $(newEl).find("[informId]").length==0 && !$(newEl).attr("informId") ) {
if(reading) {
var a = $(oldEl).closest("form").find("input[type=submit][value=attr]");
$(newEl).attr("informId", devName+(a.length?"-a-":"-")+reading);
}
var addTitle = $("body").attr("data-addHtmlTitle");
if(reading != "state" && addTitle==1)
$(newEl).attr("title", reading);
}
$(oldEl).replaceWith(newEl);
if(newEl.activateFn) // CSS is not applied if newEl is not in the document
newEl.activateFn();
if(readyFn)
readyFn(newEl);
}
}
function
FW_queryValue(cmd, el)
{
log("FW_queryValue:"+cmd);
var query = location.pathname+"?cmd="+encodeURIComponent(cmd)+"&XHR=1";
query = addcsrf(query);
var qConn = new XMLHttpRequest();
qConn.onreadystatechange = function() {
if(qConn.readyState != 4)
return;
var qResp = qConn.responseText.replace(/\n$/, '');
qResp = qResp.replace(/\n/g, '\u2424');
if(el.setValueFn)
el.setValueFn(qResp);
qConn.abort();
}
qConn.open("GET", query, true);
qConn.send(null);
}
/*************** TEXTFIELD **************/
function
FW_createTextField(elName, devName, vArr, currVal, set, params, cmd)
{
if(vArr.length != 1 ||
(vArr[0] != "textField" &&
vArr[0] != "textFieldNL" &&
vArr[0] != "textField-long" &&
vArr[0] != "textFieldNL-long") ||
(params && params.length))
return undefined;
var is_long = (vArr[0].indexOf("long") > 0);
var newEl = $("").get(0);
if(set && set != "state" && vArr[0].indexOf("NL") < 0)
$(newEl).append(set+":");
$(newEl).append('
');
var inp = $(newEl).find("input").get(0);
if(elName)
$(inp).attr('name', elName);
if(currVal != undefined)
$(inp).val(currVal);
function addBlur() { if(cmd) $(inp).blur(function() { cmd($(inp).val()) }); };
newEl.setValueFn = function(arg){ $(inp).val(arg) };
addBlur();
var myFunc = function(){
$(inp).unbind("blur");
$('body').append(
'
'+
''+
'
');
var txt = $(inp).val();
txt = txt.replace(/\u2424/g, '\n');
$("#td_longText").val(txt);
var cm;
if(typeof AddCodeMirror == 'function') {
AddCodeMirror($("#td_longText"), function(pcm) {cm = pcm;});
}
$('#editdlg').dialog(
{ modal:true, closeOnEscape:true, width:$(window).width()*3/4,
height:$(window).height()*3/4,
close:function(){ $('#editdlg').remove(); },
buttons:[
{ text:"Cancel", click:function(){
$(this).dialog('close');
addBlur();
}},
{ text:"OK", click:function(){
if(cm)
$("#td_longText").val(cm.getValue());
var res=$("#td_longText").val();
res = res.replace(/\n/g, '\u2424' );
$(this).dialog('close');
$(inp).val(res);
addBlur();
}}]
});
};
if(is_long)
$(newEl).click(myFunc);
return newEl;
}
/*************** select **************/
function
FW_createSelect(elName, devName, vArr, currVal, set, params, cmd)
{
if(vArr.length < 2 || vArr[0] != "select" || (params && params.length))
return undefined;
var newEl = document.createElement('select');
var vHash = {};
for(var j=1; j < vArr.length; j++) {
var o = document.createElement('option');
o.text = o.value = vArr[j].replace(/#/g," ");
vHash[vArr[j]] = 1;
newEl.options[j-1] = o;
}
if(currVal)
$(newEl).val(currVal);
if(elName)
$(newEl).attr('name', elName);
if(cmd)
$(newEl).change(function(arg) { cmd($(newEl).val()) });
newEl.setValueFn = function(arg) { if(vHash[arg]) $(newEl).val(arg); };
return newEl;
}
/*************** selectNumbers **************/
// Syntax: selectnumbers,
,,,,lin|log10
function
FW_createSelectNumbers(elName, devName, vArr, currVal, set, params, cmd)
{
if(vArr.length < 6 || vArr[0] != "selectnumbers" || (params && params.length))
return undefined;
var min = parseFloat(vArr[1]);
var stp = parseFloat(vArr[2]);
var max = parseFloat(vArr[3]);
var dp = parseFloat(vArr[4]); // decimal points
var fun = vArr[5]; // function
if(currVal != undefined)
currVal = currVal.replace(/[^\d.\-]/g, "");
currVal = (currVal==undefined || currVal=="") ? min : parseFloat(currVal);
if(max==min)
return undefined;
if(!(fun == "lin" || fun == "log10"))
return undefined;
if(currVal < min)
currVal = min;
if(currVal > max)
currVal = max;
var newEl = document.createElement('select');
var vHash = {};
var k = 0;
var v = 0;
if (fun == "lin") {
for(var j=min; j <= max; j+=stp) {
var o = document.createElement('option');
o.text = o.value = j.toFixed(dp);
vHash[j.toString()] = 1;
newEl.options[k] = o;
k++;
}
} else if (fun == "log10") {
if(min <= 0 || max <= 0)
return undefined;
for(var j=Math.log10(min); j <= Math.log10(max)+stp; j+=stp) {
var o = document.createElement('option');
var w = Math.pow(10, j)
if (w > max)
w = max;
if (v == w.toFixed(dp))
continue;
v = w.toFixed(dp);
o.text = o.value = v;
vHash[v] = 1;
newEl.options[k] = o;
k++;
}
}
if(currVal)
$(newEl).val(currVal.toFixed(dp));
if(elName)
$(newEl).attr('name', elName);
if(cmd)
$(newEl).change(function(arg) { cmd($(newEl).val()) });
newEl.setValueFn = function(arg) { if(vHash[arg]) $(newEl).val(arg); };
return newEl;
}
/*************** noArg **************/
function
FW_createNoArg(elName, devName, vArr, currVal, set, params, cmd)
{
if(vArr.length != 1 || vArr[0] != "noArg" || (params && params.length))
return undefined;
var newEl = $('').get(0);
if(elName)
$(newEl).append('
');
return(newEl);
}
/*************** slider **************/
function
FW_createSlider(elName, devName, vArr, currVal, set, params, cmd)
{
// min, step, max, float
if(vArr.length < 4 || vArr.length > 5 || vArr[0] != "slider" ||
(params && params.length))
return undefined;
var min = parseFloat(vArr[1]);
var stp = parseFloat(vArr[2]);
var max = parseFloat(vArr[3]);
var flt = (vArr.length == 5 && vArr[4] == "1");
var dp = 0; // decimal points for float
if(flt) {
var s = ""+stp;
if(s.indexOf(".") >= 0)
dp = s.substr(s.indexOf(".")+1).length;
}
if(currVal != undefined)
currVal = currVal.replace(/[^\d.\-]/g, "");
currVal = (currVal==undefined || currVal=="") ? min : parseFloat(currVal);
if(max==min)
return undefined;
if(currVal < min || currVal > max)
currVal = min;
var newEl = $('
').get(0);
var slider = $('
').get(0);
$(newEl).append(slider);
var sh = $('
'+currVal+'
').get(0);
$(slider).append(sh);
if(elName)
$(newEl).append('
');
var lastX=-1, offX=0, maxX=0, val=currVal;
newEl.activateFn = function() {
if(currVal < min || currVal > max)
return;
if(!slider.offsetWidth)
return setTimeout(newEl.activateFn, 1);
maxX = slider.offsetWidth-sh.offsetWidth;
offX = (currVal-min)*maxX/(max-min);
var strVal = (flt ? currVal.toFixed(dp) : ""+parseInt(currVal));
sh.innerHTML = strVal;
sh.setAttribute('style', 'left:'+offX+'px;');
if(elName)
slider.nextSibling.setAttribute('value', strVal);
}
$(newEl).keydown(function(e){
if(e.keyCode == 37) currVal -= stp;
else if(e.keyCode == 39) currVal += stp;
else return;
if(currVal < min) currVal = min;
if(currVal > max) currVal = max;
offX = (currVal-min)*maxX/(max-min);
var strVal = (flt ? currVal.toFixed(dp) : ""+parseInt(currVal));
sh.innerHTML = strVal;
sh.setAttribute('style', 'left:'+offX+'px;');
if(cmd)
cmd(strVal);
if(elName)
slider.nextSibling.setAttribute('value', strVal);
});
function
touchFn(e, fn)
{
e.preventDefault(); // Prevents Safari from scrolling!
if(e.touches == null || e.touches.length == 0)
return;
e.clientX = e.touches[0].clientX;
fn(e);
}
function
mouseDown(e)
{
var oldFn1 = document.onmousemove, oldFn2 = document.onmouseup,
oldFn3 = document.ontouchmove, oldFn4 = document.ontouchend;
e.stopPropagation(); // Dashboard fix
lastX = e.clientX; // Does not work on IE8
function
mouseMove(e)
{
e.stopPropagation(); // Dashboard fix
if(maxX == 0) // Forum #35846
maxX = slider.offsetWidth-sh.offsetWidth;
var diff = e.clientX-lastX; lastX = e.clientX;
offX += diff;
if(offX < 0) offX = 0;
if(offX > maxX) offX = maxX;
val = offX/maxX * (max-min);
val = flt ? (Math.floor(val/stp)*stp+min).toFixed(dp) :
(Math.floor(Math.floor(val/stp)*stp)+min);
sh.innerHTML = val;
sh.setAttribute('style', 'left:'+offX+'px;');
}
document.onmousemove = mouseMove;
document.ontouchmove = function(e) { touchFn(e, mouseMove); }
document.onmouseup = document.ontouchend = function(e)
{
e.stopPropagation(); // Dashboard fix
document.onmousemove = oldFn1; document.onmouseup = oldFn2;
document.ontouchmove = oldFn3; document.ontouchend = oldFn4;
if(cmd)
cmd(val);
if(elName)
slider.nextSibling.setAttribute('value', val);
};
};
sh.onselectstart = function() { return false; }
sh.onmousedown = mouseDown;
sh.ontouchstart = function(e) { touchFn(e, mouseDown); }
newEl.setValueFn = function(arg) {
var res = arg.match(/[\d.\-]+/); // extract first number
currVal = (res ? parseFloat(res[0]) : min);
if(currVal < min || currVal > max)
currVal = min;
newEl.activateFn();
};
return newEl;
}
/*************** TIME **************/
function
FW_createTime(elName, devName, vArr, currVal, set, params, cmd)
{
if(vArr.length != 1 || vArr[0] != "time" || (params && params.length))
return undefined;
var open="-", closed="+";
var newEl = document.createElement('div');
$(newEl).append('
');
$(newEl).append('
');
var inp = $(newEl).find("[type=text]");
var btn = $(newEl).find("[type=button]");
currVal = (currVal ? currVal : "12:00")
.replace(/[^\d]*(\d\d):(\d\d).*/g,"$1:$2");
$(inp).val(currVal)
if(elName)
$(inp).attr("name", elName);
var hh, mm; // the slider elements
newEl.setValueFn = function(arg) {
arg = arg.replace(/[^\d]*(\d\d):(\d\d).*/g,"$1:$2");
$(inp).val(arg);
var hhmm = arg.split(":");
if(hhmm.length == 2 && hh && mm) {
hh.setValueFn(hhmm[0]);
mm.setValueFn(hhmm[1]);
}
};
$(btn).click(function(){ // Open/Close the slider view
var v = $(inp).val();
if($(btn).val() == open) {
$(btn).val(closed);
$(newEl).find(".timeSlider").remove();
hh = mm = undefined;
if(cmd)
cmd(v);
return;
}
$(btn).val(open);
if(v.indexOf(":") < 0) {
v = "12:00";
$(inp).val(v);
}
var hhmm = v.split(":");
function
tSet(idx, arg)
{
if((""+arg).length < 2)
arg = '0'+arg;
hhmm[idx] = arg;
$(inp).val(hhmm.join(":"));
}
$(newEl).append('
');
var ts = $(newEl).find(".timeSlider");
hh = FW_createSlider(undefined, devName+"HH", ["slider", 0, 1, 23],
hhmm[0], undefined, params, function(arg) { tSet(0, arg) });
mm = FW_createSlider(undefined, devName+"MM", ["slider", 0, 5, 55],
hhmm[1], undefined, params, function(arg) { tSet(1, arg) });
$(ts).append("
"); $(ts).append(hh); hh.activateFn();
$(ts).append("
"); $(ts).append(mm); mm.activateFn();
});
return newEl;
}
/*************** MULTIPLE **************/
function
FW_createMultiple(elName, devName, vArr, currVal, set, params, cmd)
{
if(vArr.length < 2 || (vArr[0]!="multiple" && vArr[0]!="multiple-strict") ||
(params && params.length))
return undefined;
var newEl = $('
').get(0);
if(currVal)
$(newEl).val(currVal);
if(elName)
$(newEl).attr("name", elName);
newEl.setValueFn = function(arg){ $(newEl).val(arg) };
for(var i1=1; i1
'+ // funny stuff for ios6 style, forum #23561
''+
' '+'
'+
''+v+' ';
delete(selObj[v]);
}
var selArr=[];
for(var i1 in selObj)
selArr.push(i1);
var strict = (vArr[0] == "multiple-strict");
$('body').append(
''+
'
'+(!strict ? '
' : '')+
'
');
$('#multidlg').dialog(
{ modal:true, closeOnEscape:false, maxHeight:$(window).height()*3/4,
buttons:[
{ text:"Cancel", click:function(){ $('#multidlg').remove(); }},
{ text:"OK", click:function(){
var res=[];
if($("#md_freeText").val())
res.push($("#md_freeText").val());
$("#multidlg table input").each(function(){
if($(this).prop("checked"))
res.push($(this).attr("name"));
});
$('#multidlg').remove();
$(newEl).val(res.join(","));
if(cmd)
cmd(res.join(","));
}}]});
});
return newEl;
}
/*************** WIDGETS END **************/
/*************** SCRIPT LOAD FUNCTIONS START **************/
function
loadScript(sname, callback, force)
{
var h = document.head || document.getElementsByTagName('head')[0];
sname = FW_root+"/"+sname;
if(FW_scripts[sname]) {
if(FW_scripts[sname].loaded) {
if(callback)
callback();
} else {
FW_scripts[sname].callbacks.push(callback);
}
return;
}
if(!FW_docReady && !force) {
FW_scripts[sname] = { callbacks:[ callback] };
return;
}
var script = document.createElement("script");
script.src = sname;
script.async = script.defer = false;
script.type = "text/javascript";
FW_scripts[sname] = { callbacks:[ callback] };
function
scriptLoaded()
{
var p = FW_scripts[sname];
p.loaded = true;
if(!p.called) {
p.called = true;
for(var i1=0; i1< p.callbacks.length; i1++)
if(p.callbacks[i1]) // pushing undefined callbacks on the stack is ok
p.callbacks[i1]();
}
delete(p.callbacks);
}
log("Loading script "+sname);
if(FW_isIE) {
script.onreadystatechange = function() {
if(script.readyState == 'loaded' || script.readyState == 'complete') {
script.onreadystatechange = null;
scriptLoaded();
}
}
} else {
if(FW_isiOS)
FW_closeConn();
script.onload = function(){
scriptLoaded();
}
}
h.appendChild(script);
}
function
loadLink(lname)
{
var h = document.head || document.getElementsByTagName('head')[0];
lname = FW_root+"/"+lname;
var arr = h.getElementsByTagName("link");
for(var i1=0; i1= 0)
attr = $(this).attr("attr");
});
var ua={};
if(attr && attr != "") {
try {
ua=JSON.parse(attr);
} catch(e){
FW_errmsg(sname+" Parameter "+e,5000);
}
}
return ua;
}
/*************** SCRIPT LOAD FUNCTIONS END **************/
function
print_call_stack() {
var stack = new Error().stack;
console.log("PRINTING CALL STACK");
console.log( stack );
}
function
FW_getSVG(emb)
{
if(emb.contentDocument)
return emb.contentDocument;
if(typeof emb.getSVGDocument == "function") {
try {
return emb.getSVGDocument();
} catch(err) {
// dom not loaded -> fall through -> retry;
}
}
return undefined;
}
/*
=pod
=begin html
noArg - show no input field.
time - show a JavaScript driven timepicker.
Example: attr FS20dev widgetOverride on-till:time
textField - show an input field.
Example: attr WEB widgetOverride room:textField
textFieldNL - show the input field and hide the label.
textField-long - show an input-field, but upon
clicking on the input field open a textArea (60x25).
textFieldNL-long - the behaviour is the same
as :textField-long, but no label is displayed.
slider,<min>,<step>,<max>[,1] - show
a JavaScript driven slider. The optional ,1 at the end
avoids the rounding of floating-point numbers.
multiple,<val1>,<val2>,..." - present a
multiple-value-selector with an additional textfield. The result is
comman separated.
multiple-strict,<val1>,<val2>,... - like :multiple, but
without the textfield.
selectnumbers,<min>,<step>,<max>,<number of
digits after decimal point>,lin|log10" - display a select widget
generated with values from min to max with step.
lin generates a constantly increasing series. log10 generates an
exponentially increasing series to base 10, step is related to the
exponent, e.g. 0.0625.
select,<val1>,<val2>,... - show a dropdown with all values.
NOTE : this is also the fallback, if no modifier is found.
=end html
=begin html_DE
noArg - es wird kein weiteres Eingabefeld angezeigt.
time - zeigt ein Zeitauswahlmenü.
Beispiel: attr FS20dev widgetOverride on-till:time
textField - zeigt ein Eingabefeld.
Beispiel: attr WEB widgetOverride room:textField
textField-long - ist wie textField, aber beim Click im Eingabefeld wird
ein Dialog mit einer HTML textarea (60x25) wird geöffnet.
slider,<min>,<step>,<max>[,1] - zeigt einen
Schieberegler. Das optionale 1 (isFloat) vermeidet eine Rundung der
Fliesskommazahlen.
multiple,<val1>,<val2>,... - zeigt eine Mehrfachauswahl mit
einem zusätzlichen Eingabefeld. Das Ergebnis ist Komma
separiert.
multiple-strict,<val1>,<val2>,... - ist wie :multiple,
bloß ohne Eingabefeld.
selectnumbers,<min>,<step>,<max>,<number of
digits after decimal point>,lin|log10" zeigt ein HTML-select mit einer
Zahlenreihe vom Wert min bis Wert max mit Schritten von step
angezeigt.
Die Angabe lin erzeugt eine konstant ansteigende Reihe. Die Angabe
log10 erzeugt eine exponentiell ansteigende Reihe zur Basis 10,
step bezieht sich auf den Exponenten, z.B. 0.0625.
select,<val1>,<val2>,... - zeigt ein HTML select mit allen
Werten. Achtung : so ein Widget wird auch dann angezeigt, falls
kein passender Modifier gefunden wurde.
=end html_DE
=cut
*/