',parent);
});
});
$("form").each(function(){ // main input special cases
var input = $(this).find("input.maininput");
if(!input.length)
return;
$(this).on("submit", function(e) {
var val = $(input).val();
if(val.match(/^\s*ver.*/)) { // version
e.preventDefault();
$(input).val("");
return FW_showVersion(val);
} else if(val.match(/^\s*shutdown/)) { // shutdown
FW_cmd(FW_root+"?XHR=1&cmd="+val);
$(input).val("");
return false;
} else if(val.match(/^\s*l\s/)) { // l dev
var m = val.match(/^\s*l\s+(.*)/);
location.href = FW_root+"?detail="+m[1];
e.preventDefault();
return false;
} else if(val.match(/^\s*get\s+/)) { // get
// make get use xhr instead of reload
//return true;
FW_cmd(FW_root+"?cmd="+encodeURIComponent(val)+"&XHR=1", function(data){
if( !data.match( /^[\s\S]*<\/html>/ ) ) {
data = data.replace( '<', '<' );
data = '
'+data+'
';
}
if( location.href.indexOf('?') === -1 )
$('#content').html(data);
else
FW_okDialog(data);
});
e.preventDefault();
$(input).val("");
return false;
}
return true;
});
});
$("table.attributes tr div.dname") // Click on attribute fills input value
.each(function(){
$(this)
.html(''+$(this).html()+'')
.css({cursor:"pointer"})
.click(function(){
var attrName = $(this).text();
var sel = "#sel_attr"+$(this).attr("data-name").replace(/\./g,'_');
if($(sel+" option[value='"+attrName+"']").length == 0)
$(sel).append('');
$(sel).val(attrName);
FW_detailSelect(sel, true);
$(sel).trigger("change");
});
});
$("[name=icon-filter]").on("change keyup paste", function() {
clearTimeout($.data(this, 'delayTimer'));
var wait = setTimeout(FW_filterIcons, 300);
$(this).data('delayTimer', wait);
});
$("pre.motd").each(function(){ // add links for passwort setting
var txt = $(this).text();
txt = txt.replace(/(configuring|define|attr) .*/g, function(x) {
return ""+x+"";
});
$(this).html(txt);
$(this).find("a").click(function(){
var txt = $(this).text();
var ma = txt.match(/configuring.*device (.*)/); // ??
if(ma)
location.href = FW_root+"?detail="+ma[1];
FW_cmd(FW_root+"?cmd="+encodeURIComponent(txt)+"&XHR=1",
function(data){
if(txt.indexOf("attr") == 0) $("pre.motd").html("");
if(txt.indexOf("define") == 0)
location.href = FW_root+"?detail=allowed";
});
});
});
var sa = location.search.substring(1).split("&");
for(var i = 0; i < sa.length; i++) {
var kv = sa[i].split("=");
FW_urlParams[kv[0]] = decodeURIComponent(kv[1]);
}
$("select[id^=sel_attr],select[id^=sel_set],select[id^=sel_get]")
.change(function(){ // online help
var val = $(this).val();
var m = $(this).attr("name").match(/arg.(set|get|attr)(.*)/);
if(!m)
return;
$("#devSpecHelp").remove();
var sel=this, devName=m[2], selType=m[1];
var group = $(this).parent().find(':selected').parent().attr('label');
FW_displayHelp(devName, sel, selType, val, group);
});
FW_smallScreenCommands();
FW_inlineModify();
FW_detLink();
FW_treeMenu();
$("body").attr("data-os", FW_os);
// automatic reload for style change
if(location.search.indexOf("cmd=style%20select") > 0) {
$('a[href*="style set"],a[onclick*="style set"]').each(function(){
var href = $(this).attr("href");
if(!href && (href = $(this).attr("onclick")))
href = href.substr(15,href.length-16);
$(this).click(function(e){
e.preventDefault();
FW_cmd(href+"&XHR=1", function(data) { location.reload(true); });
});
});
}
}
function
FW_displayHelp(devName, sel, selType, val, group)
{
if(group) {
if(group.indexOf("userattr") >= 0)
return;
devName = (group == "framework" ? "commandref" : group);
}
FW_getHelp(devName, function(data) { // show either the next or the outer li
$("#content")
.append("");
var wb = $("#content > #workbench");
wb.html(data);
var mtype = wb.find("a[id]").attr("id"), aTag;
if(!mtype)
mtype = wb.find("a[name]").attr("name");
if(devName == "commandref")
mtype = "";
if(mtype) { // current syntax: FHEMWEB-attr-webCmd
var mv = (""+mtype+"-"+selType+"-"+val).replace(/[^a-z0-9_-]/ig,'_');
aTag = wb.find("a[id="+mv+"]");
if(!$(aTag).length) { // old style #1 syntax: FHEMWEBwebCmd
mv = (""+mtype+val).replace(/[^a-z0-9_-]/ig,'_');
aTag = wb.find("a[name="+mv+"]");
}
}
if(!$(aTag).length) { // old style #2 syntax : webCmd
var v = (val).replace(/[^a-z0-9_-]/ig,'_');
aTag = wb.find("a[name="+v+"]");
}
if(!$(aTag).length) { // regexp attributes, like backend_.*
wb.find("a[id^='"+mtype+"-"+selType+"-'][data-pattern]").each(
function() {
var dp = $(this).attr("data-pattern");
// if(!$(aTag).length && val.match(dp)) {
if(val.match(dp)) {
log("Searching for "+val+", found data-pattern "+dp);
aTag = this;
}
});
}
if($(aTag).length) {
var liTag = $(aTag).next("li");
if(!$(liTag).length)
liTag = $(aTag).parent("li");
if(!$(liTag).length)
liTag = $(aTag).parent().next("li");
$("#devSpecHelp").remove(); // shown only one if FHEM is slow
if($(liTag).length) {
$(sel).closest("div[cmd='"+selType+"']")
.after('')
$("#devSpecHelp").html($(liTag).html());
}
}
wb.remove();
});
}
var FW_helpData={};
function
FW_getHelp(dev, fn)
{
if(FW_helpData[dev])
return fn(FW_helpData[dev]);
if(dev == "commandref") {
var lang = $("body").attr("data-language");
var url = FW_root+"/docs/commandref_frame"+
(lang == "EN" ? "" : "_"+lang)+".html";
$.ajax({
url:url, headers: { "cache-control": "no-cache" },
success: function(data, textStatus, req){
FW_helpData[dev] = data;
return fn(data);
},
error:function(xhr, status, err) { log("E:"+err+"/"+status); }
});
return;
}
FW_cmd(FW_root+"?cmd=help "+dev+"&XHR=1", function(data) {
if(data.match(/^No help found/) &&
!dev.match(" DE")) // for our german only friends
return FW_getHelp(dev+" DE", fn);
FW_helpData[dev] = data;
return fn(data);
});
}
function
FW_showVersion(val)
{
FW_cmd(FW_root+"?cmd="+encodeURIComponent(val)+"&XHR=1", function(data){
var list = Object.keys(FW_version);
list.sort();
for(var i1=0; i1'+data+'');
});
return false;
}
function
FW_filterIcons()
{
var icons = $('.dist[title]');
icons.show();
var filterText = $('[name=icon-filter]').val();
if (filterText != '') {
var re = RegExp(filterText,"i");
icons.filter(function() {
return !re.test(this.title);
}).hide();
}
}
function
FW_delete(cmd, fCmd)
{
if($("body").attr("data-hiddenroom").match(/\binput\b/))
return FW_okDialog("Disabled");
if(!fCmd)
fCmd = addcsrf(FW_root+"?cmd="+cmd);
var cd = $("body").attr("data-confirmDelete");
if(!cd || cd == 0) {
location.href = fCmd;
return;
}
var div = $("
");
$(div).html("Do you really want to "+cmd+"?
"+
" Skip this dialog in the future");
$("body").append(div);
$(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(){ doClose(); location.href = fCmd; }},
{text:"No", click:doClose} ],
close: doClose
});
function
doClose()
{
var wn = $("body").attr("data-webName");
if($(div).find("input:checked").length)
FW_cmd(FW_root+"?cmd=attr "+wn+" confirmDelete 0&XHR=1");
$(this).dialog("close"); $(div).remove();
}
}
// For all the links starting with delete (deleteattr, etc)
function
FW_confirmDelete()
{
var b = $("body");
var cd = $(b).attr("data-confirmDelete");
if(!cd || cd == 0)
return;
var wn = $(b).attr("data-webName");
$("div#content").find("a").each(function(){
var href = $(this).attr("href");
if(!href)
return;
var ma = $(this).attr("href").match(/.*cmd[^=]*=(delete[^&]*).*$/);
if(!ma || ma.length != 2)
return;
FW_removeLink(this);
$(this).click(function(e){ FW_delete(ma[1], ma[0]) });
});
}
function
FW_renameDevice(dev)
{
var div = $("
");
$(div).html('Rename '+dev+' to:
');
$("body").append(div);
$(div).dialog({
dialogClass:"no-close", modal:true, width:"auto", closeOnEscape:true,
maxWidth:$(window).width()*0.9, maxHeight:$(window).height()*0.9,
buttons: [
{text:"Rename", click:function(){
var nn = $(div).find("input").val();
if(!nn.match(/^[a-z0-9._]*$/i))
return FW_okDialog("Illegal characters in the new name");
location.href = addcsrf(FW_root+"?cmd=rename "+dev+" "+nn);
}},
{text:"Cancel", click:doClose} ],
close: doClose
});
function
doClose()
{
$(this).dialog("close"); $(div).remove();
}
}
// 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(""+$(this).html()+"");
$(this).find("a").click(function(){
var t = $("
');
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("
time - show a JavaScript driven timepicker.
Example: attr FS20dev widgetOverride on-till:time
textField[,placeholder] - show an input field.
Example: attr WEB widgetOverride room:textField
textFieldNL[,placeholder] - show the input field and hide the label.
textField-long[,sizePct] - show an input-field, but upon
clicking on the input field open a textArea.
sizePct specifies the size of the dialog relative to the screen, in
percent. Default is 75
textFieldNL-long[,sizePct] - 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.
bitfield,<size><mask> - show a table of checkboxes (8 per
line) to set single bits. Default for size is 8 and for mask 2^32-1
widgetList,... - show a list of widgets. The arguments are concatenated,
and separated be the length of the following argument list.
Example: widgetList,3,select,opt1,opt2,1,textField
Note: the values will be sent to FHEM as a comma separated list, and only
preloaded widgets can be referenced.
=end html
=begin html_DE
noArg - es wird kein weiteres Eingabefeld angezeigt.
time - zeigt ein Zeitauswahlmenü.
Beispiel: attr FS20dev widgetOverride on-till:time
textField[,placeholder] - zeigt ein Eingabefeld.
Beispiel: attr WEB widgetOverride room:textField
textFieldNL[,placeholder] - Eingabefeld ohne Label.
textField-long[,sizePct] - ist wie textField, aber beim Click im
Eingabefeld wird ein Dialog mit einer HTML textarea wird
geöffnet. sizePct ist die relative Größe des Dialogs,
die Voreinstellung ist 75.
textFieldNL-long[,sizePct] - wi textField-long, aber kein Label wir
angezeigt.
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.
bitfield,<size>,<mask> - zeigt eine Tabelle von
Kontrollkästchen (8 pro Zeile), um einzelne Bits setzen zu koennen.
Die Voreinstellung fuer size ist 8 und fuer mask 2^32-1.
widgetList,... - zeigt eine Liste von Widgets. Die Argumente aller
widgets sind durch die Längenangabe der jeweiligen Argumentliste
getrennt.
Beispiel: widgetList,3,select,opt1,opt2,1,textField
Achtung: die Werte werden Komma separiert zu FHEM gesendet, und es
können nur bereits geladene widgets definiert werden.