mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-08 13:24:56 +00:00
FLOORPLAN: extended version with javascripts and undefine, copy, rename incl. processing for userattr
git-svn-id: https://svn.fhem.de/fhem/trunk@7969 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
5de8ab705e
commit
bca625137e
@ -45,12 +45,15 @@
|
||||
# 0034: iOS fullscreen app - navigating to other floorplan doesn't open safari anymore (Feb 15, 2014)
|
||||
# 0035: added allowedCommands-Attribute based on FHEMWEB (Feb 20, 2014)
|
||||
# 0036: added style "commands only", changed html-method "get" to "$FW_formmethod" (June 19, 2014)
|
||||
# 0037: updated to match fhemweb.js developments (Rudi, Jan 17, 2015)
|
||||
# 0038: added arrange by drag&drop provided by Markus (mluckey), added longpollfilter (nesges),
|
||||
# added processing of global userattr fp_<name> and their value per device for rename, copy, delete (Jan 31, 2015)
|
||||
#
|
||||
################################################################
|
||||
#
|
||||
# Copyright notice
|
||||
#
|
||||
# (c) 2012-2014 Copyright: Ulrich Maass
|
||||
# (c) 2012-2015 Copyright: Ulrich Maass
|
||||
#
|
||||
# This file is part of fhem.
|
||||
#
|
||||
@ -77,22 +80,23 @@
|
||||
# Example: define Groundfloor FLOORPLAN
|
||||
#
|
||||
# Step 2:
|
||||
# store picture fp_<name>.png in your modpath. This will be used as background-picture.
|
||||
# store picture fp_<name>.png in your imagepath. This will be used as background-picture.
|
||||
# Example: fhem/www/images/default/Groundfloor.png
|
||||
#
|
||||
# Step 3:
|
||||
# Activate 'Arrange-Mode' to have user-friendly fields to move items:
|
||||
# attr <floorplanname> fp_arrange 1
|
||||
# Example: attr Groundfloor fp_arrange 1
|
||||
# Delete this attribute when you're done with setup
|
||||
# To make objects display, they will thereby get assigned
|
||||
# Arrange-Mode displays a popup to add and edit how devices will be shown. Arrange devices using drag&drop.
|
||||
# When adding objects to your floorplan, they will thereby get assigned
|
||||
# attr <device> fp_<name> <top>,<left>,<style>,<text>
|
||||
# displays <device> on floorplan <name> at position top:<top>,left:<left> with style <style> and description <text>
|
||||
# styles: 0: icon/state only, 1: name+icon, 2: name+icon+commands 3:Device-Readings(+name) 4:S300TH
|
||||
# Example: attr lamp fp_Groundfloor 100,100,1,TableLamp #displays lamp at position 100px,100px
|
||||
#
|
||||
# Repeat step 3 to add further devices. Delete attr fp_<name> when all devices are arranged on your screen. Enjoy.
|
||||
# Repeat step 3 to add further devices. Delete attr fp_arrange when all devices are arranged on your screen. Enjoy.
|
||||
#
|
||||
# Check the colorful pdf-docu in http://sourceforge.net/p/fhem/code/HEAD/tree/trunk/fhem/docs/fhem-floorplan-installation-guide.pdf
|
||||
# Check the colorful pdf-docu in http://sourceforge.net/p/fhem/code/HEAD/tree/trunk/fhem/docs/fhem-floorplan-installation-guide_de.pdf
|
||||
#
|
||||
################################################################################
|
||||
|
||||
@ -107,6 +111,10 @@ use vars qw(@FW_fhemwebjs); # List of fhemweb*js scripts to load - from FHE
|
||||
# Forward declaration
|
||||
sub FLOORPLAN_Initialize($); # Initialize
|
||||
sub FP_define(); # define <name> FLOORPLAN
|
||||
sub FP_undefine($$); # delete <name>
|
||||
sub FP_rename($$); # rename <old> <new>
|
||||
sub FP_copy($$); # copy <old> <new>
|
||||
sub FP_copy_rename_delete($$$); # exec for copy, rename, delete
|
||||
sub FP_Get($@); # get-command
|
||||
sub FP_CGI(); # analyze URL
|
||||
sub FP_digestCgi($); # digest CGI
|
||||
@ -147,51 +155,114 @@ my @styles = ("0 (Icon only)","1 (Name+Icon)","2 (Name+Icon+Commands)","3 (Devic
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
##################
|
||||
# method 'initialize'
|
||||
sub
|
||||
FLOORPLAN_Initialize($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
$hash->{DefFn} = "FP_define";
|
||||
$hash->{UndefFn} = "FP_undefine";
|
||||
$hash->{RenameFn} = "FP_rename";
|
||||
$hash->{CopyFn} = "FP_copy";
|
||||
$hash->{GetFn} = "FP_Get";
|
||||
$hash->{FW_detailFn} = "FP_detailFn"; #floorplan-specific detail-screen
|
||||
$hash->{AttrList} = "refresh fp_arrange:1,detail,WEB,0 commandfield:1,0 fp_default:1,0 ".
|
||||
"stylesheet fp_noMenu:1,0 fp_backgroundimg fp_setbutton:1,0 fp_viewport ".
|
||||
"CssFiles JavaScripts ".
|
||||
"fp_roomIcons";
|
||||
"CssFiles JavaScripts fp_roomIcons ";
|
||||
# CGI
|
||||
my $name = "floorplan";
|
||||
my $fhem_url = "/" . $name ;
|
||||
$data{FWEXT}{$fhem_url}{FUNC} = "FP_CGI";
|
||||
$data{FWEXT}{$fhem_url}{LINK} = $name;
|
||||
$data{FWEXT}{$fhem_url}{NAME} = "Floorplans";
|
||||
#$data{FWEXT}{$fhem_url}{EMBEDDED} = 1; # not using embedded-mode to save screen-space
|
||||
# Global-Config for CSS
|
||||
$modules{_internal_}{AttrList} .= " VIEW_CSS";
|
||||
|
||||
$modules{_internal_}{AttrList} .= " VIEW_CSS"; # Global-Config for CSS
|
||||
|
||||
my $n = 0;
|
||||
@FW_zoom = ("qday", "day","week","month","year"); #copied from FHEMWEB - using local version to avoid global variable
|
||||
%FW_zoom = map { $_, $n++ } @FW_zoom; #copied from FHEMWEB - using local version to avoid global variable
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
##################
|
||||
# method 'define'
|
||||
sub
|
||||
FP_define(){
|
||||
my ($hash, $def) = @_;
|
||||
$hash->{STATE} = $hash->{NAME};
|
||||
$hash->{STATE} = 'Defined';
|
||||
my $name = $hash->{NAME};
|
||||
if (AttrVal("global","userattr","") !~ m/fp_$name/) {
|
||||
addToAttrList("fp_$name"); # create userattr fp_<name> if it doesn't exist yet
|
||||
# Log 3, "Floorplan - added global userattr fp_$name";
|
||||
Log3 $name, 3, "Floorplan - added global userattr fp_$name";
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
##################
|
||||
# method 'undefine'
|
||||
sub
|
||||
FP_undefine($$) {
|
||||
my ($hash,$arg) = @_;
|
||||
FP_copy_rename_delete('delete',$hash->{NAME},undef);
|
||||
return undef;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
##################
|
||||
# FLOORPLAN rename
|
||||
sub
|
||||
FP_rename($$) {
|
||||
my ($new,$old) = @_;
|
||||
FP_copy_rename_delete('rename',$old,$new);
|
||||
return undef;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
##################
|
||||
# FLOORPLAN copy
|
||||
sub
|
||||
FP_copy($$) {
|
||||
my ($old,$new) = @_;
|
||||
FP_copy_rename_delete('copy',$old,$new);
|
||||
return undef;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
##################
|
||||
# FLOORPLAN copy_rename_delete
|
||||
sub
|
||||
FP_copy_rename_delete($$$) {
|
||||
my ($cmd,$old,$new) = @_;
|
||||
my $aold = "fp_$old";
|
||||
my $anew = $new ? "fp_$new" : '';
|
||||
Log3 $old, 3, "Floorplan - $cmd $old - processing...";
|
||||
if ( ($cmd =~ m/(copy|rename)/) && (AttrVal("global","userattr","") !~ m/$anew/) ) {
|
||||
addToAttrList("$anew"); # create userattr fp_<name> if it doesn't exist yet for $new
|
||||
Log3 $old, 3, "Floorplan - added global userattr $anew";
|
||||
}
|
||||
foreach my $d (sort keys %defs) {
|
||||
next if (!$attr{$d}{"$aold"} && !$attr{$d}{"$anew"});
|
||||
if ($cmd =~ m/(copy|rename)/) {
|
||||
AnalyzeCommand(undef, "attr $d $anew ".AttrVal($d,$aold,""),AttrVal($FW_wname,"allowedCommands",undef));
|
||||
Log3 $new, 3, "Floorplan - added attr $d $anew ".AttrVal($d,$anew,"");
|
||||
}
|
||||
if ($cmd =~ m/(rename|delete)/) {
|
||||
Log3 $old, 3, "Floorplan - deleted attr $d $aold ".AttrVal($d,$aold,"");
|
||||
AnalyzeCommand(undef, "deleteattr $d $aold",AttrVal($FW_wname,"allowedCommands",undef));
|
||||
}
|
||||
}
|
||||
if ($cmd =~ m/(rename|delete)/) {
|
||||
my $ua = $attr{global}{userattr};
|
||||
$ua =~ s/ $aold//;
|
||||
AnalyzeCommand(undef, "attr global userattr $ua",AttrVal($FW_wname,"allowedCommands",undef));
|
||||
Log3 $old, 3, "Floorplan - deleted global userattr $aold"; # delete the global userattr if $old gets deleted
|
||||
}
|
||||
Log3 $old, 3, "Floorplan - $cmd $old - complete.";
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
##################
|
||||
@ -299,7 +370,7 @@ FP_CGI(){
|
||||
} else {
|
||||
FP_show(); # show floorplan
|
||||
}
|
||||
# finish HTML & leave
|
||||
# finish HTML & leave back to FHEMWEB
|
||||
FW_pO "</html>\n";
|
||||
$FW_subdir = "";
|
||||
return ("text/html; charset=$FW_encoding", $FW_RET); # $FW_RET composed by FW_pO, FP_pH etc
|
||||
@ -318,22 +389,23 @@ FP_digestCgi($) {
|
||||
%FP_webArgs = ();
|
||||
$FP_fwdetail = undef;
|
||||
$arg =~ s,^[?/],,;
|
||||
foreach my $pv (split("&", $arg)) { #per each URL-section devided by &
|
||||
my ($atop, $aleft, $drop) = ""; #mod
|
||||
foreach my $pv (split("&", $arg)) { # per each URL-section devided by &
|
||||
next if($pv eq ""); # happens when post forgot to set FW_ME
|
||||
$pv =~ s/\+/ /g;
|
||||
$pv =~ s/%([\dA-F][\dA-F])/chr(hex($1))/ige;
|
||||
my ($p,$v) = split("=",$pv, 2); #$p = parameter, $v = value
|
||||
my ($p,$v) = split("=",$pv, 2); # $p = parameter, $v = value
|
||||
$v =~ s/[\r]\n/\\\n/g if($v && $p && $p ne "data"); # Multiline: escape the NL for fhem
|
||||
$FP_webArgs{$p} = $v;
|
||||
if($p eq "arr.dev") { $v =~ m,^([\.\w]*)\s\(,; $v = $1 if ($1); $FP_arrange_selected = $v; $FP_arrange_default = $v; }
|
||||
if($p eq "add.dev") { $v =~ m,^([\.\w]*)\s\(,; $v = $1 if ($1); $cmd = "attr $v fp_$FP_name 50,100"; }
|
||||
if($p eq "add.dev") { $v =~ m,^([\.\w]*)\s\(,; $v = $1 if ($1); $cmd = "attr $v fp_$FP_name 50,200,1"; }
|
||||
if($p eq "cmd") { $cmd = $v; }
|
||||
if($p =~ m/^cmd\.(.*)$/) { $cmd = $v; $c = $1; }
|
||||
if($p =~ m/^detl\.(.*)$/) { $FP_fwdetail = $1; }
|
||||
if($p =~ m/^dev\.(.*)$/) { $dev{$1} = $v; }
|
||||
if($p =~ m/^arg\.(.*)$/) { $arg{$1} = $v; }
|
||||
if($p =~ m/^val\.(.*)$/) { $val{$1} = $v; }
|
||||
if($p =~ m/^deva\.(.*)$/) { $deva{$1} = $v; $FP_arrange_selected = undef;}
|
||||
if($p =~ m/^deva\.(.*)$/) { $deva{$1} = $v; $FP_arrange_selected = undef; }
|
||||
if($p =~ m/^attr\.(.*)$/) { $attr{$1} = $v; }
|
||||
if($p =~ m/^top\.(.*)$/) { $top{$1} = $v; }
|
||||
if($p =~ m/^left\.(.*)$/) { $left{$1} = $v; }
|
||||
@ -342,20 +414,19 @@ FP_digestCgi($) {
|
||||
if($p eq "pos") { %FW_pos = split(/[=;]/, $v); }
|
||||
}
|
||||
my $dele = ($cmd =~ m/^deleteattr/);
|
||||
$cmd.=" $dev{$c}" if(defined($dev{$c})); #FHT device
|
||||
$cmd.=" $dev{$c}" if(defined($dev{$c})); # FHT device
|
||||
$cmd.=" $arg{$c}" if(defined($arg{$c})&&
|
||||
($arg{$c} ne "state" || $cmd !~ m/^set/)); #FHT argument (e.g. desired-temp)
|
||||
$cmd.=" $val{$c}" if(defined($val{$c})); #FHT value
|
||||
$cmd.=" $deva{$c}" if(defined($deva{$c})); #arrange device
|
||||
$cmd.=" $attr{$c}" if(defined($attr{$c})); #arrange attr
|
||||
$cmd.=" $top{$c}" if(defined($top{$c}) && !$dele); #arrange top
|
||||
$cmd.=",$left{$c}" if(defined($left{$c}) && !$dele); #arrange left
|
||||
$cmd.=",$style{$c}" if(defined($style{$c})&& !$dele); #arrange style
|
||||
$cmd.=",$text{$c}" if(defined($text{$c}) && !$dele); #arrange text
|
||||
($arg{$c} ne "state" || $cmd !~ m/^set/)); # FHT argument (e.g. desired-temp)
|
||||
$cmd.=" $val{$c}" if(defined($val{$c})); # FHT value
|
||||
$cmd.=" $deva{$c}" if(defined($deva{$c})); # arrange device
|
||||
$cmd.=" $attr{$c}" if(defined($attr{$c})); # arrange attr
|
||||
$cmd.=" $top{$c}" if(defined($top{$c}) && !$dele); # arrange top
|
||||
$cmd.=",$left{$c}" if(defined($left{$c}) && !$dele); # arrange left
|
||||
$cmd.=",$style{$c}" if(defined($style{$c})&& !$dele); # arrange style
|
||||
$cmd.=",$text{$c}" if(defined($text{$c}) && !$dele); # arrange text
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
##################
|
||||
# Page header, set webapp & css
|
||||
@ -400,6 +471,10 @@ FP_htmlHeader($) {
|
||||
my $jsTemplate = '<script type="text/javascript" src="%s"></script>';
|
||||
FW_pO sprintf($jsTemplate, "$FW_ME/pgm2/jquery.min.js");
|
||||
FW_pO sprintf($jsTemplate, "$FW_ME/pgm2/jquery-ui.min.js");
|
||||
FW_pO sprintf($jsTemplate, "$FW_ME/pgm2/floorplan_click.js"); #enlarge clickable area per widget
|
||||
if ($FP_arrange && ($FP_arrange eq "1" || ($FP_arrange eq $FW_wname) || $FP_arrange eq "detail")) {
|
||||
FW_pO sprintf($jsTemplate, "$FW_ME/pgm2/floorplan_drag.js") ; #arrange-mode drag&drop
|
||||
}
|
||||
|
||||
#######################
|
||||
# Other JavaScripts + their Attributes
|
||||
@ -418,14 +493,16 @@ FP_htmlHeader($) {
|
||||
next if($h !~ m/HASH/ || !$h->{SCRIPT} || $h->{SCRIPT} =~ m+pgm2/jquery+);
|
||||
my $script = $h->{SCRIPT};
|
||||
$script = ($script =~ m,^/,) ? "$FW_ME$script" : "$FW_ME/pgm2/$script";
|
||||
FW_pO sprintf($jsTemplate, $script);
|
||||
FW_pO sprintf($jsTemplate, $script) if ($script);
|
||||
}
|
||||
}
|
||||
|
||||
my $csrf= ($FW_CSRF ? "fwcsrf='$defs{$FW_wname}{CSRFTOKEN}'" : "");
|
||||
my $gen = 'generated="'.(time()-1).'"';
|
||||
my $lp = 'longpoll="'.AttrVal($FW_wname,"longpoll",1).'"';
|
||||
FW_pO "</head>\n<body name=\"$title\" $gen $lp $csrf>";
|
||||
my $lpf = 'longpollfilter="fp_'.$FP_name.'=.%2B"'; #longpollfilter - only devices present on this floorplan shall be notified
|
||||
$lpf =~ s/:/%3/g;
|
||||
FW_pO "</head>\n<body name=\"$title\" $gen $lp $lpf $csrf>";
|
||||
}
|
||||
|
||||
|
||||
@ -444,7 +521,6 @@ FP_showStart() {
|
||||
FW_pO "<td><input type=\"text\" name=\"cmd\" size=\"30\"/></td>"; #input-field
|
||||
FW_pO "</tr></table>";
|
||||
FW_pO "</form></div>";
|
||||
# add edit *floorplanstyle.css if FP_arrange ?
|
||||
# no floorplans defined? -> show message
|
||||
my $count=0;
|
||||
foreach my $f (sort keys %defs) {
|
||||
@ -471,7 +547,6 @@ FP_show(){
|
||||
FP_htmlHeader("$FP_name");
|
||||
## body
|
||||
my $onload = $FW_longpoll ? "onload=\"FW_delayedStart()\"" : "";
|
||||
FW_pO "<body id=\"$FP_name-body\" $onload>\n";
|
||||
FW_pO "<div id=\"backimg\" style=\"width: 99%; height: 99%;\">";
|
||||
FW_pO FW_makeImage(AttrVal($FP_name, "fp_backgroundimg", "fp_$FP_name"));
|
||||
FW_pO "</div>\n";
|
||||
@ -493,7 +568,7 @@ FP_show(){
|
||||
foreach my $d (sort keys %defs) { # loop all devices
|
||||
my $type = $defs{$d}{TYPE};
|
||||
my $attr = AttrVal("$d","fp_$FP_name", undef);
|
||||
next if(!$attr || $type eq "weblink"); # skip if device-attribute not set for current floorplan-name
|
||||
next if(!$attr || $type eq "weblink"); # skip if device-attribute not set for current floorplan-name
|
||||
|
||||
my ($top, $left, $style, $text, $text2) = split(/,/ , $attr);
|
||||
# $top = position in px, top
|
||||
@ -504,7 +579,9 @@ FP_show(){
|
||||
$left = 0 if (!$left);
|
||||
$style = 0 if (!$style);
|
||||
# start device-specific table
|
||||
FW_pO "\n<div style=\"position:absolute; top:".$top."px; left:".$left."px;\" id=\"div-$d\">";
|
||||
my $t2 = $text2 ? $text2 : " ";
|
||||
# wrapper-div needed for floorplan_drag.js and for positioning
|
||||
FW_pO "\n<div fp_style=\"$style\" fp_text=\"$text\" fp_text2=\"$t2\" fp_name=\"$FP_name\" class=\"fp_device_div\" style=\"position:absolute; top:".$top."px; left:".$left."px;\" id=\"div-$d\">";
|
||||
FW_pO "<form method=\"$FW_formmethod\" action=\"$FW_ME/floorplan/$FP_name/$d\" autocomplete=\"off\">";
|
||||
FW_pO " <table class=\"$type fp_$FP_name\" id=\"table-$d\" align=\"center\">"; # Main table per device
|
||||
my ($allSets, $cmdlist, $txt) = FW_devState($d, "");
|
||||
@ -532,12 +609,11 @@ FP_show(){
|
||||
|
||||
########################
|
||||
# Device-state per device
|
||||
# FW_pO "<tr class=\"devicestate fp_$FP_name\" id=\"$d\">"; # For css: class=devicestate, id=devicename
|
||||
if ($style != 7) {
|
||||
if ($style == 3 || $style == 6) {
|
||||
FW_pO "<tr class=\"devicereading fp_$FP_name\" id=\"$d"."-$text\">"; # For css: class=devicereading, id=<devicename>-<reading>
|
||||
} else {
|
||||
FW_pO "<tr class=\"devicestate fp_$FP_name\" id=\"$d\">"; # For css: class=devicestate, id=<devicename>
|
||||
FW_pO "<tr class=\"devicestate fp_$FP_name\" id=\"$d\">"; # For css: class=devicestate, id=<devicename>
|
||||
}
|
||||
$txt =~ s/measured-temp: ([\.\d]*) \(Celsius\)/$1/; # format FHT-temperature
|
||||
### use device-specific icons according to userattr fp_image or fp_<floorplan>.image
|
||||
@ -568,7 +644,6 @@ FP_show(){
|
||||
$txt="";
|
||||
FW_pO "<tr class=\"devicetimestamp fp_$FP_name\" id=\"$d-devicetimestamp\">"; # For css: class=devicetimestamp, id=<devicename>-devicetimestamp
|
||||
$txt = ReadingsTimestamp($d, $text, "Undefined Reading $d-<b>$text</b>"); # Style3+6 = DeviceReading given in $text
|
||||
# FW_pO "<td><div colspan=\"$cols\" informId=\"$d-$text-ts\">$txt</div></td>";
|
||||
FW_pO "<td><div colspan=\"$cols\" informId=\"$d-$text-ts\">$txt</div>";
|
||||
FW_pO "</td></tr>";
|
||||
}
|
||||
@ -579,10 +654,10 @@ FP_show(){
|
||||
my @cList = split(":", $cmdlist);
|
||||
my @rList = map { ReplaceEventMap($d,$_,1) } @cList;
|
||||
my $firstIdx = 0;
|
||||
FW_pO " <tr class=\"devicecommands\" id=\"$d-devicecommands\">";
|
||||
FW_pO " <tr class=\"devicecommands\" id=\"$d-devicecommands\">";
|
||||
|
||||
my $oldMe = $FW_ME;
|
||||
foreach my $cmd (sort @cList) {
|
||||
foreach my $cmd (sort @cList) {
|
||||
# Special handling (slider, dropdown, timepicker, ...)
|
||||
my $htmlTxt;
|
||||
my @c = split(' ', $cmd);
|
||||
@ -590,7 +665,7 @@ FP_show(){
|
||||
my $values = $1;
|
||||
$FW_ME = "$FW_ME/floorplan/$FP_name";
|
||||
foreach my $fn (sort keys %{$data{webCmdFn}}) {
|
||||
my $FW_room = ""; ##needed to be able to reuse code from FHEMWEB
|
||||
my $FW_room = ''; ##needed to be able to reuse code from FHEMWEB
|
||||
no strict "refs";
|
||||
$htmlTxt = &{$data{webCmdFn}{$fn}}($FW_ME,
|
||||
$d, $FW_room, $cmd, $values);
|
||||
@ -599,17 +674,17 @@ FP_show(){
|
||||
}
|
||||
}
|
||||
if(defined($htmlTxt)) {
|
||||
$htmlTxt =~ s/>desired-temp/>/; #mod20130929
|
||||
$htmlTxt =~ s/>desiredTemperature/>/; #mod20131225
|
||||
FW_pO $htmlTxt;
|
||||
# END # Special handling (slider, dropdown, timepicker, ...)
|
||||
$htmlTxt =~ s/>desired-temp/>/; #for FHT
|
||||
$htmlTxt =~ s/>desiredTemperature/>/; #for MAX!
|
||||
FW_pO $htmlTxt;
|
||||
# END # Special handling (slider, dropdown, timepicker, ...)
|
||||
} else {
|
||||
FW_pH "cmd.$d=set $d $cmd",
|
||||
ReplaceEventMap($d,$cmd,1),1,"devicecommands";
|
||||
}
|
||||
}
|
||||
$FW_ME = $oldMe;
|
||||
FW_pO "</tr>";
|
||||
$FW_ME = $oldMe;
|
||||
FW_pO "</tr>";
|
||||
|
||||
} elsif($type eq "FileLog") {
|
||||
# $row = FW_dumpFileLog($d, 1, $row);
|
||||
@ -617,7 +692,7 @@ FP_show(){
|
||||
|
||||
FW_pO "</table></form>";
|
||||
FW_pO "</div>\n";
|
||||
}
|
||||
} #end loop all decives
|
||||
|
||||
########################
|
||||
# Finally the weblinks
|
||||
@ -631,8 +706,13 @@ FP_show(){
|
||||
next if(!$type);
|
||||
next if($type ne "weblink");
|
||||
# set position per weblink
|
||||
my ($top, $left, $style, $text) = split(/,/ , AttrVal("$d", "fp_$FP_name", undef));
|
||||
FW_pO "\n<div style=\"position:absolute; top:".$top."px; left:".$left."px\" id = \"div-$d\">"; # div to position the weblink
|
||||
my ($top, $left, $style, $text, $text2) = split(/,/ , AttrVal("$d", "fp_$FP_name", undef));
|
||||
$text = "" if (!$text);
|
||||
$text2 = "" if (!$text2);
|
||||
$left = 0 if (!$left);
|
||||
$style = 0 if (!$style);
|
||||
FW_pO "\n<div fp_style=\"$style\" fp_text=\"$text\" fp_text2=\"$text2\" fp_name=\"$FP_name\" class=\"fp_weblink_div style_$style\" style=\"position:absolute; top:".
|
||||
$top."px; left:".$left."px\" id = \"div-$d\">"; # div to position the weblink
|
||||
FW_pO "<div class = \"fp_$type fp_$FP_name weblink\" id = \"$d\">"; # div to make it accessible to arrangeByMouse
|
||||
# print weblink
|
||||
$buttons = FW_showWeblink($d, $defs{$d}{LINK}, $defs{$d}{WLTYPE}, $buttons);
|
||||
@ -684,7 +764,7 @@ FP_menuArrange() {
|
||||
my $type = $defs{$d}{TYPE};
|
||||
$type = '?' if (!$type);
|
||||
# exclude these types from list of available devices
|
||||
next if ($type =~ m/^(WEB|CUL$|FHEM.*|FileLog|PachLog|PID|SUNRISE.*|FLOORPLAN|holiday|Global|notify|autocreate)/ );
|
||||
next if ($type =~ m/^(WEB|CUL$|FHEM2FHEM|FHEMWEB|FileLog|PachLog|PID|SUNRISE.*|FLOORPLAN|holiday|Global|notify|autocreate)/ );
|
||||
my $disp = $d;
|
||||
$disp .= ' (' . AttrVal($d,"room","Unsorted").") $type";
|
||||
my $alias = AttrVal($d, "alias", undef);
|
||||
@ -727,22 +807,7 @@ FP_menuArrange() {
|
||||
|
||||
# fields for top,left,style,text
|
||||
if ($attrd) {
|
||||
if (!$FP_fwdetail) { # arrange-by-mouse not from fhemweb-screen floorplan-details
|
||||
#### arrangeByMouse by Torsten
|
||||
FW_pO "<script type=\"text/javascript\">";
|
||||
FW_pO "function show_coords(e){";
|
||||
FW_pO " var device = document.getElementById(\"fp_ar_input_top\").name.replace(/top\./,\"\");"; # get device-ID from 'top'-field
|
||||
FW_pO " var X = e.pageX;"; # e is the event, pageX and pageY the click-ccordinates
|
||||
FW_pO " var Y = e.pageY;";
|
||||
FW_pO " document.getElementById(\"fp_ar_input_top\").value = Y;"; # updates the input-fields top and left with the click-coordinates
|
||||
FW_pO " document.getElementById(\"fp_ar_input_left\").value = X;";
|
||||
FW_pO " document.getElementById(\"div-\"+device).style.top = Y+\"px\";"; # moves the device
|
||||
FW_pO " document.getElementById(\"div-\"+device).style.left = X+\"px\";";
|
||||
FW_pO "}";
|
||||
FW_pO "document.getElementById(\"backimg\").addEventListener(\"click\",show_coords,false);"; # attach event-handler to background-picture
|
||||
FW_pO "</script>";
|
||||
}
|
||||
### build the form
|
||||
### build the form
|
||||
my $disp = $FP_arrange eq "detail" ? $desc{$d} : $d;
|
||||
FW_pO "<form method=\"$FW_formmethod\" action=\"$FW_ME/floorplan/$FP_name\">"; #form3
|
||||
my ($top, $left, $style, $text, $text2) = split(",", $attrd);
|
||||
@ -753,8 +818,8 @@ FP_menuArrange() {
|
||||
FP_input("deva.$d", $d, "hidden") . "\n" .
|
||||
FP_input("dscr.$d", $disp, "text", "Selected device", 45, "", "disabled") . "\n<br>\n" .
|
||||
FP_input("attr.$d", "fp_$FP_name", "hidden") . "\n" .
|
||||
FP_input("top.$d", $top ? $top : 10, "text", "Top", 4, 4, 'id="fp_ar_input_top"') . "\n" .
|
||||
FP_input("left.$d", $left ? $left : 10, "text", "Left", 4, 4, 'id="fp_ar_input_left"' ) . "\n" .
|
||||
FP_input("top.$d", $top ? $top : 10, "text", "Top", 4, 4, 'onkeydown="increment(event, this)" class="'.$d.'" id="fp_ar_input_top"') . "\n" .
|
||||
FP_input("left.$d", $left ? $left : 10, "text", "Left", 4, 4, 'onkeydown="increment(event, this)" class="'.$d.'" id="fp_ar_input_left"' ) . "\n" .
|
||||
FW_select("","style.$d", \@styles, $style ? $style : 0, "menu-arrange") . "\n" .
|
||||
FP_input("text.$d", $text ? $text : "", "text", "Description", 15) . "\n" .
|
||||
FW_submit("cmd.$d", "attr") . "\n" .
|
||||
@ -812,8 +877,6 @@ FP_detailFn($$$$) {
|
||||
$ret .= ($row/2==int($row/2))?"even":"odd";
|
||||
$ret .= '">';
|
||||
$ret .= "<td><div class=\"dname\"><a href=\"$FW_ME?detail=$fpd\">$fpd</a></div></td>";
|
||||
# FW_pH "detail=$_", $_;
|
||||
# $ret = "<a href=\"$link\">$txt</a>";
|
||||
$ret .= "<td><div class=\"dval\">$x</div></td>";
|
||||
$ret .= "<td><div class=\"dval\">$y</div></td>";
|
||||
$ret .= "<td><div class=\"dval\">";
|
||||
@ -973,12 +1036,12 @@ FP_pOfill($@) {
|
||||
|
||||
|
||||
<li><a name="fp_arrange">fp_arrange</a><br>
|
||||
Activates the "arrange mode" which shows an additional menu on the screen,
|
||||
Activates the "arrange mode" which shows an additional menu on the screen to choose style and description.<br>
|
||||
When the arrange-mode is activated, devices can be placed freely on the screen by drag&drop.
|
||||
allowing to place devices easily on the screen.<br>
|
||||
Example:
|
||||
<ul>
|
||||
<code>attr Groundfloor fp_arrange 1</code><br>
|
||||
<code>attr Groundfloor fp_arrange detail #displays the devices with infos room, type, alias</code><br>
|
||||
<code>attr Groundfloor fp_arrange WEB #activates arrange mode for frontend-device WEB only</code><br><br>
|
||||
</ul>
|
||||
</li>
|
||||
@ -1065,7 +1128,7 @@ FP_pOfill($@) {
|
||||
<a name="FLOORPLAN"></a>
|
||||
<h3>FLOORPLAN</h3>
|
||||
<ul>
|
||||
Fügt dem fhem-Menü einen zusätzlichen Menüpunkt "Floorplans" hinzu, dre zu einer Anzeige ohne fhem-Menü, Räume oder device-Listen führt.
|
||||
Fügt dem fhem-Menü einen zusätzlichen Menüpunkt "Floorplans" hinzu, der zu einer Anzeige ohne fhem-Menü, Räume oder device-Listen führt.
|
||||
Geräte können an einer festlegbaren Koordinate auf dem Bildschirm angezeigt werden, üblicherweise mit einem anklickbaren icon, das das Ein- oder Aus-Schalten
|
||||
des Geräts durch klicken erlaubt. Ein Hintergrundbild kann verwendet werden - z.B. ein Grundriss oder jegliches andere Bild.
|
||||
Mit floorplanstyle.css kann die Formatierung angepasst werden.<br>
|
||||
@ -1143,11 +1206,10 @@ FP_pOfill($@) {
|
||||
|
||||
<li><a name="fp_arrange">fp_arrange</a><br>
|
||||
Aktiviert den "arrange-Modus" der ein zusätzliches Menü anzeigt,
|
||||
mit dem Geräte auf dem Bildschirm angeordnet werden können. Dabei können die Koordinaten auch durch Platzieren mit der Maus gesetzt werden.<br>
|
||||
mit dem Geräte auf dem Bildschirm angeordnet werden können. Bei aktiviertem arrange-mode können alle devices per drag&drop platziert werden.<br>
|
||||
Beispiel:
|
||||
<ul>
|
||||
<code>attr Erdgeschoss fp_arrange 1</code><br>
|
||||
<code>attr Erdgeschoss fp_arrange detail #Zeigt die Geräte mit den Infos Raum, Typ und Alias</code><br>
|
||||
<code>attr Erdgeschoss fp_arrange WEB #Aktiviert den arrange-Modus nur für die Webinstanz WEB</code><br><br>
|
||||
</ul>
|
||||
</li>
|
||||
|
Loading…
x
Reference in New Issue
Block a user