FLOORPLAN: extended version with javascripts and undefine, copy, rename incl. processing for userattr

git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@7969 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
ulimaass 2015-02-14 11:50:18 +00:00
parent 09b530a795
commit 6f6f59acc8

View File

@ -45,12 +45,15 @@
# 0034: iOS fullscreen app - navigating to other floorplan doesn't open safari anymore (Feb 15, 2014) # 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) # 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) # 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 # Copyright notice
# #
# (c) 2012-2014 Copyright: Ulrich Maass # (c) 2012-2015 Copyright: Ulrich Maass
# #
# This file is part of fhem. # This file is part of fhem.
# #
@ -77,22 +80,23 @@
# Example: define Groundfloor FLOORPLAN # Example: define Groundfloor FLOORPLAN
# #
# Step 2: # 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 # Example: fhem/www/images/default/Groundfloor.png
# #
# Step 3: # Step 3:
# Activate 'Arrange-Mode' to have user-friendly fields to move items: # Activate 'Arrange-Mode' to have user-friendly fields to move items:
# attr <floorplanname> fp_arrange 1 # attr <floorplanname> fp_arrange 1
# Example: attr Groundfloor fp_arrange 1
# Delete this attribute when you're done with setup # 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> # 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> # 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 # 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 # Forward declaration
sub FLOORPLAN_Initialize($); # Initialize sub FLOORPLAN_Initialize($); # Initialize
sub FP_define(); # define <name> FLOORPLAN 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_Get($@); # get-command
sub FP_CGI(); # analyze URL sub FP_CGI(); # analyze URL
sub FP_digestCgi($); # digest CGI 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 sub
FLOORPLAN_Initialize($) FLOORPLAN_Initialize($)
{ {
my ($hash) = @_; my ($hash) = @_;
$hash->{DefFn} = "FP_define"; $hash->{DefFn} = "FP_define";
$hash->{UndefFn} = "FP_undefine";
$hash->{RenameFn} = "FP_rename";
$hash->{CopyFn} = "FP_copy";
$hash->{GetFn} = "FP_Get"; $hash->{GetFn} = "FP_Get";
$hash->{FW_detailFn} = "FP_detailFn"; #floorplan-specific detail-screen $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 ". $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 ". "stylesheet fp_noMenu:1,0 fp_backgroundimg fp_setbutton:1,0 fp_viewport ".
"CssFiles JavaScripts ". "CssFiles JavaScripts fp_roomIcons ";
"fp_roomIcons";
# CGI # CGI
my $name = "floorplan"; my $name = "floorplan";
my $fhem_url = "/" . $name ; my $fhem_url = "/" . $name ;
$data{FWEXT}{$fhem_url}{FUNC} = "FP_CGI"; $data{FWEXT}{$fhem_url}{FUNC} = "FP_CGI";
$data{FWEXT}{$fhem_url}{LINK} = $name; $data{FWEXT}{$fhem_url}{LINK} = $name;
$data{FWEXT}{$fhem_url}{NAME} = "Floorplans"; $data{FWEXT}{$fhem_url}{NAME} = "Floorplans";
#$data{FWEXT}{$fhem_url}{EMBEDDED} = 1; # not using embedded-mode to save screen-space $modules{_internal_}{AttrList} .= " VIEW_CSS"; # Global-Config for CSS
# Global-Config for CSS
$modules{_internal_}{AttrList} .= " VIEW_CSS";
my $n = 0; my $n = 0;
@FW_zoom = ("qday", "day","week","month","year"); #copied from FHEMWEB - using local version to avoid global variable @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 %FW_zoom = map { $_, $n++ } @FW_zoom; #copied from FHEMWEB - using local version to avoid global variable
return undef; return undef;
} }
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
################## ##################
# method 'define' # method 'define'
sub sub
FP_define(){ FP_define(){
my ($hash, $def) = @_; my ($hash, $def) = @_;
$hash->{STATE} = $hash->{NAME}; $hash->{STATE} = 'Defined';
my $name = $hash->{NAME}; my $name = $hash->{NAME};
if (AttrVal("global","userattr","") !~ m/fp_$name/) { if (AttrVal("global","userattr","") !~ m/fp_$name/) {
addToAttrList("fp_$name"); # create userattr fp_<name> if it doesn't exist yet 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"; Log3 $name, 3, "Floorplan - added global userattr fp_$name";
} }
return undef; 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 { } else {
FP_show(); # show floorplan FP_show(); # show floorplan
} }
# finish HTML & leave # finish HTML & leave back to FHEMWEB
FW_pO "</html>\n"; FW_pO "</html>\n";
$FW_subdir = ""; $FW_subdir = "";
return ("text/html; charset=$FW_encoding", $FW_RET); # $FW_RET composed by FW_pO, FP_pH etc return ("text/html; charset=$FW_encoding", $FW_RET); # $FW_RET composed by FW_pO, FP_pH etc
@ -318,6 +389,7 @@ FP_digestCgi($) {
%FP_webArgs = (); %FP_webArgs = ();
$FP_fwdetail = undef; $FP_fwdetail = undef;
$arg =~ s,^[?/],,; $arg =~ s,^[?/],,;
my ($atop, $aleft, $drop) = ""; #mod
foreach my $pv (split("&", $arg)) { # per each URL-section devided by & foreach my $pv (split("&", $arg)) { # per each URL-section devided by &
next if($pv eq ""); # happens when post forgot to set FW_ME next if($pv eq ""); # happens when post forgot to set FW_ME
$pv =~ s/\+/ /g; $pv =~ s/\+/ /g;
@ -326,7 +398,7 @@ FP_digestCgi($) {
$v =~ s/[\r]\n/\\\n/g if($v && $p && $p ne "data"); # Multiline: escape the NL for fhem $v =~ s/[\r]\n/\\\n/g if($v && $p && $p ne "data"); # Multiline: escape the NL for fhem
$FP_webArgs{$p} = $v; $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 "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 eq "cmd") { $cmd = $v; }
if($p =~ m/^cmd\.(.*)$/) { $cmd = $v; $c = $1; } if($p =~ m/^cmd\.(.*)$/) { $cmd = $v; $c = $1; }
if($p =~ m/^detl\.(.*)$/) { $FP_fwdetail = $1; } if($p =~ m/^detl\.(.*)$/) { $FP_fwdetail = $1; }
@ -355,7 +427,6 @@ FP_digestCgi($) {
return $cmd; return $cmd;
} }
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
################## ##################
# Page header, set webapp & css # Page header, set webapp & css
@ -400,6 +471,10 @@ FP_htmlHeader($) {
my $jsTemplate = '<script type="text/javascript" src="%s"></script>'; 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.min.js");
FW_pO sprintf($jsTemplate, "$FW_ME/pgm2/jquery-ui.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 # Other JavaScripts + their Attributes
@ -418,14 +493,16 @@ FP_htmlHeader($) {
next if($h !~ m/HASH/ || !$h->{SCRIPT} || $h->{SCRIPT} =~ m+pgm2/jquery+); next if($h !~ m/HASH/ || !$h->{SCRIPT} || $h->{SCRIPT} =~ m+pgm2/jquery+);
my $script = $h->{SCRIPT}; my $script = $h->{SCRIPT};
$script = ($script =~ m,^/,) ? "$FW_ME$script" : "$FW_ME/pgm2/$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 $csrf= ($FW_CSRF ? "fwcsrf='$defs{$FW_wname}{CSRFTOKEN}'" : "");
my $gen = 'generated="'.(time()-1).'"'; my $gen = 'generated="'.(time()-1).'"';
my $lp = 'longpoll="'.AttrVal($FW_wname,"longpoll",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 "<td><input type=\"text\" name=\"cmd\" size=\"30\"/></td>"; #input-field
FW_pO "</tr></table>"; FW_pO "</tr></table>";
FW_pO "</form></div>"; FW_pO "</form></div>";
# add edit *floorplanstyle.css if FP_arrange ?
# no floorplans defined? -> show message # no floorplans defined? -> show message
my $count=0; my $count=0;
foreach my $f (sort keys %defs) { foreach my $f (sort keys %defs) {
@ -471,7 +547,6 @@ FP_show(){
FP_htmlHeader("$FP_name"); FP_htmlHeader("$FP_name");
## body ## body
my $onload = $FW_longpoll ? "onload=\"FW_delayedStart()\"" : ""; 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 "<div id=\"backimg\" style=\"width: 99%; height: 99%;\">";
FW_pO FW_makeImage(AttrVal($FP_name, "fp_backgroundimg", "fp_$FP_name")); FW_pO FW_makeImage(AttrVal($FP_name, "fp_backgroundimg", "fp_$FP_name"));
FW_pO "</div>\n"; FW_pO "</div>\n";
@ -504,7 +579,9 @@ FP_show(){
$left = 0 if (!$left); $left = 0 if (!$left);
$style = 0 if (!$style); $style = 0 if (!$style);
# start device-specific table # 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 "<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 FW_pO " <table class=\"$type fp_$FP_name\" id=\"table-$d\" align=\"center\">"; # Main table per device
my ($allSets, $cmdlist, $txt) = FW_devState($d, ""); my ($allSets, $cmdlist, $txt) = FW_devState($d, "");
@ -532,7 +609,6 @@ FP_show(){
######################## ########################
# Device-state per device # 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 != 7) {
if ($style == 3 || $style == 6) { if ($style == 3 || $style == 6) {
FW_pO "<tr class=\"devicereading fp_$FP_name\" id=\"$d"."-$text\">"; # For css: class=devicereading, id=<devicename>-<reading> FW_pO "<tr class=\"devicereading fp_$FP_name\" id=\"$d"."-$text\">"; # For css: class=devicereading, id=<devicename>-<reading>
@ -568,7 +644,6 @@ FP_show(){
$txt=""; $txt="";
FW_pO "<tr class=\"devicetimestamp fp_$FP_name\" id=\"$d-devicetimestamp\">"; # For css: class=devicetimestamp, id=<devicename>-devicetimestamp 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 $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><div colspan=\"$cols\" informId=\"$d-$text-ts\">$txt</div>";
FW_pO "</td></tr>"; FW_pO "</td></tr>";
} }
@ -590,7 +665,7 @@ FP_show(){
my $values = $1; my $values = $1;
$FW_ME = "$FW_ME/floorplan/$FP_name"; $FW_ME = "$FW_ME/floorplan/$FP_name";
foreach my $fn (sort keys %{$data{webCmdFn}}) { 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"; no strict "refs";
$htmlTxt = &{$data{webCmdFn}{$fn}}($FW_ME, $htmlTxt = &{$data{webCmdFn}{$fn}}($FW_ME,
$d, $FW_room, $cmd, $values); $d, $FW_room, $cmd, $values);
@ -599,8 +674,8 @@ FP_show(){
} }
} }
if(defined($htmlTxt)) { if(defined($htmlTxt)) {
$htmlTxt =~ s/>desired-temp/>/; #mod20130929 $htmlTxt =~ s/>desired-temp/>/; #for FHT
$htmlTxt =~ s/>desiredTemperature/>/; #mod20131225 $htmlTxt =~ s/>desiredTemperature/>/; #for MAX!
FW_pO $htmlTxt; FW_pO $htmlTxt;
# END # Special handling (slider, dropdown, timepicker, ...) # END # Special handling (slider, dropdown, timepicker, ...)
} else { } else {
@ -617,7 +692,7 @@ FP_show(){
FW_pO "</table></form>"; FW_pO "</table></form>";
FW_pO "</div>\n"; FW_pO "</div>\n";
} } #end loop all decives
######################## ########################
# Finally the weblinks # Finally the weblinks
@ -631,8 +706,13 @@ FP_show(){
next if(!$type); next if(!$type);
next if($type ne "weblink"); next if($type ne "weblink");
# set position per weblink # set position per weblink
my ($top, $left, $style, $text) = split(/,/ , AttrVal("$d", "fp_$FP_name", undef)); my ($top, $left, $style, $text, $text2) = 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 $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 FW_pO "<div class = \"fp_$type fp_$FP_name weblink\" id = \"$d\">"; # div to make it accessible to arrangeByMouse
# print weblink # print weblink
$buttons = FW_showWeblink($d, $defs{$d}{LINK}, $defs{$d}{WLTYPE}, $buttons); $buttons = FW_showWeblink($d, $defs{$d}{LINK}, $defs{$d}{WLTYPE}, $buttons);
@ -684,7 +764,7 @@ FP_menuArrange() {
my $type = $defs{$d}{TYPE}; my $type = $defs{$d}{TYPE};
$type = '?' if (!$type); $type = '?' if (!$type);
# exclude these types from list of available devices # 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; my $disp = $d;
$disp .= ' (' . AttrVal($d,"room","Unsorted").") $type"; $disp .= ' (' . AttrVal($d,"room","Unsorted").") $type";
my $alias = AttrVal($d, "alias", undef); my $alias = AttrVal($d, "alias", undef);
@ -727,21 +807,6 @@ FP_menuArrange() {
# fields for top,left,style,text # fields for top,left,style,text
if ($attrd) { 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; my $disp = $FP_arrange eq "detail" ? $desc{$d} : $d;
FW_pO "<form method=\"$FW_formmethod\" action=\"$FW_ME/floorplan/$FP_name\">"; #form3 FW_pO "<form method=\"$FW_formmethod\" action=\"$FW_ME/floorplan/$FP_name\">"; #form3
@ -753,8 +818,8 @@ FP_menuArrange() {
FP_input("deva.$d", $d, "hidden") . "\n" . FP_input("deva.$d", $d, "hidden") . "\n" .
FP_input("dscr.$d", $disp, "text", "Selected device", 45, "", "disabled") . "\n<br>\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("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("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, 'id="fp_ar_input_left"' ) . "\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" . FW_select("","style.$d", \@styles, $style ? $style : 0, "menu-arrange") . "\n" .
FP_input("text.$d", $text ? $text : "", "text", "Description", 15) . "\n" . FP_input("text.$d", $text ? $text : "", "text", "Description", 15) . "\n" .
FW_submit("cmd.$d", "attr") . "\n" . FW_submit("cmd.$d", "attr") . "\n" .
@ -812,8 +877,6 @@ FP_detailFn($$$$) {
$ret .= ($row/2==int($row/2))?"even":"odd"; $ret .= ($row/2==int($row/2))?"even":"odd";
$ret .= '">'; $ret .= '">';
$ret .= "<td><div class=\"dname\"><a href=\"$FW_ME?detail=$fpd\">$fpd</a></div></td>"; $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\">$x</div></td>";
$ret .= "<td><div class=\"dval\">$y</div></td>"; $ret .= "<td><div class=\"dval\">$y</div></td>";
$ret .= "<td><div class=\"dval\">"; $ret .= "<td><div class=\"dval\">";
@ -973,12 +1036,12 @@ FP_pOfill($@) {
<li><a name="fp_arrange">fp_arrange</a><br> <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&amp;drop.
allowing to place devices easily on the screen.<br> allowing to place devices easily on the screen.<br>
Example: Example:
<ul> <ul>
<code>attr Groundfloor fp_arrange 1</code><br> <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> <code>attr Groundfloor fp_arrange WEB #activates arrange mode for frontend-device WEB only</code><br><br>
</ul> </ul>
</li> </li>
@ -1065,7 +1128,7 @@ FP_pOfill($@) {
<a name="FLOORPLAN"></a> <a name="FLOORPLAN"></a>
<h3>FLOORPLAN</h3> <h3>FLOORPLAN</h3>
<ul> <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 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. 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> Mit floorplanstyle.css kann die Formatierung angepasst werden.<br>
@ -1143,11 +1206,10 @@ FP_pOfill($@) {
<li><a name="fp_arrange">fp_arrange</a><br> <li><a name="fp_arrange">fp_arrange</a><br>
Aktiviert den "arrange-Modus" der ein zusätzliches Menü anzeigt, 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&amp;drop platziert werden.<br>
Beispiel: Beispiel:
<ul> <ul>
<code>attr Erdgeschoss fp_arrange 1</code><br> <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> <code>attr Erdgeschoss fp_arrange WEB #Aktiviert den arrange-Modus nur für die Webinstanz WEB</code><br><br>
</ul> </ul>
</li> </li>