From a57018d05b4d84d217b5386a2b6b708d2e01e4e3 Mon Sep 17 00:00:00 2001 From: justme1968 Date: Sun, 14 Dec 2014 18:34:35 +0000 Subject: [PATCH] readingsGroup.pm: added collapsed/collapsible to visibility attribute added visibility command git-svn-id: svn://svn.code.sf.net/p/fhem/code/trunk@7214 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 3 + fhem/FHEM/33_readingsGroup.pm | 192 +++++++++++++++++-------- fhem/www/pgm2/fhemweb_readingsGroup.js | 95 ++++++++++++ 3 files changed, 231 insertions(+), 59 deletions(-) create mode 100644 fhem/www/pgm2/fhemweb_readingsGroup.js diff --git a/fhem/CHANGED b/fhem/CHANGED index 1be0e81e4..c01ba537b 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,8 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - feature: readingsGroup: added valuePrefix and valueSuffix attributes + added collapsed/collapsible to visibility attribute + added visibility command - bugfix: FB_CALLMONITOR: fixing not working company numbers reverse search for search.ch - bugfix: 70_PushNotifier repair set function (xusader) diff --git a/fhem/FHEM/33_readingsGroup.pm b/fhem/FHEM/33_readingsGroup.pm index 320299e37..9b2a3193e 100644 --- a/fhem/FHEM/33_readingsGroup.pm +++ b/fhem/FHEM/33_readingsGroup.pm @@ -39,10 +39,10 @@ sub readingsGroup_Initialize($) $hash->{DefFn} = "readingsGroup_Define"; $hash->{NotifyFn} = "readingsGroup_Notify"; $hash->{UndefFn} = "readingsGroup_Undefine"; - #$hash->{SetFn} = "readingsGroup_Set"; + $hash->{SetFn} = "readingsGroup_Set"; $hash->{GetFn} = "readingsGroup_Get"; $hash->{AttrFn} = "readingsGroup_Attr"; - $hash->{AttrList} = "disable:1,2,3 style timestampStyle ". join( " ", @mapping_attrs ) ." separator nolinks:1 noheading:1 nonames:1 notime:1 nostate:1 alwaysTrigger:1 sortDevices:1 visibility:hidden,hideable"; + $hash->{AttrList} = "disable:1,2,3 style timestampStyle ". join( " ", @mapping_attrs ) ." separator nolinks:1 noheading:1 nonames:1 notime:1 nostate:1 alwaysTrigger:1 sortDevices:1 visibility:hidden,hideable,collapsed,collapsible"; $hash->{FW_detailFn} = "readingsGroup_detailFn"; $hash->{FW_summaryFn} = "readingsGroup_detailFn"; @@ -233,6 +233,19 @@ lookup($$$$$$$$$) my($mapping,$name,$alias,$reading,$value,$room,$group,$row,$default) = @_; if( $mapping ) { + if( !ref($mapping) && $mapping =~ m/^{.*}$/) { + my $DEVICE = $name; + my $READING = $reading; + my $VALUE = $value; + my $ROW = $row; + my $m = eval $mapping; + if( $@ ) { + Log 2, $@ if( $@ ); + } else { + $mapping = $m; + } + } + if( ref($mapping) eq 'HASH' ) { $default = $mapping->{$name} if( defined($mapping->{$name}) ); $default = $mapping->{$reading} if( defined($mapping->{$reading}) ); @@ -243,13 +256,13 @@ lookup($$$$$$$$$) } if( !ref($default) && $default =~ m/^{.*}$/) { - my $DEVICE = $name; - my $READING = $reading; - my $VALUE = $value; - my $ROW = $row; - $default = eval $default; - $default = "" if( $@ ); - Log 2, $@ if( $@ ); + my $DEVICE = $name; + my $READING = $reading; + my $VALUE = $value; + my $ROW = $row; + $default = eval $default; + $default = "" if( $@ ); + Log 2, $@ if( $@ ); } return $default if( !defined($default) ); @@ -280,6 +293,20 @@ lookup2($$$$;$$) return "" if( !$lookup ); + if( !ref($lookup) && $lookup =~ m/^{.*}$/) { + my $DEVICE = $name; + my $READING = $reading; + my $VALUE = $value; + my $ROW = $row; + my $COLUMN = $column; + my $l = eval $lookup; + if( $@ ) { + Log 2, $@ if( $@ ); + } else { + $lookup = $l; + } + } + if( ref($lookup) eq 'HASH' ) { my $vf = ""; $vf = $lookup->{$reading} if( defined($reading) && exists($lookup->{$reading}) ); @@ -406,30 +433,16 @@ readingsGroup_2html($) my $devices = $hash->{DEVICES}; my $group = AttrVal( $d, "group", undef ); - - my $pgm = "Javascript:" . - "var rg = document.getElementById('readingsGroup-$d');". - "s=rg.style;". - "s.display = s.display=='none' ? 'block' : 'none';"; - - if( $group ) { - $pgm .= "var elArr = document.querySelectorAll('[groupId=$group]');". - "for(var k=0; k> "; + $show_hide .= ">"; } } @@ -439,7 +452,7 @@ readingsGroup_2html($) $ret .= ""; my $txt = AttrVal($d, "alias", $d); $txt = "$txt" if( $show_links ); - $ret .= "" if( $show_heading ); + $ret .= "" if( $show_heading ); $ret .= "
$show_hide$txt
$show_hide $txt
"; $ret .= "" if( $disable > 0 ); @@ -496,6 +509,13 @@ readingsGroup_2html($) my $name_style = lookup2($hash->{helper}{nameStyle},$name,$1,undef); my $value_columns = lookup2($hash->{helper}{valueColumns},$name,$1,undef); + if( !$FW_webArgs{"detail"} ) { + if( $visibility && $visibility eq "collapsed" && $txt ne '-' && $txt ne '+' && $txt ne '+-' ) { + $row_style = 'style=""' if( !$row_style ); + $row_style =~ s/style=(.)/style=$1display:none;/; + } + } + if( $txt eq 'br' ) { $ret .= sprintf("", ($row-1&1)?"odd":"even"); $ret .= ""; @@ -503,6 +523,36 @@ readingsGroup_2html($) ++$cell_row; $cell_column = 1; next; + } elsif( $txt eq '-' || $txt eq '+' || $txt eq '+-' ) { + my $collapsed = $visibility && ( $visibility eq "collapsed" ) && !$FW_webArgs{"detail"}; + + my $id = ''; + if( ($txt eq '+' && !$collapsed) + || ($txt eq '-' && $collapsed ) ) { + $id = ''; + $row_style = 'style=""' if( !$row_style ); + $row_style =~ s/style=(.)/style=$1display:none;/; + } elsif( $txt eq '+-' ) { + if( $collapsed ) { + $txt = '+'; + } else { + $txt = '-'; + } + $id = "id='plusminus'"; + } elsif( $txt ne '+' && $collapsed ) { + $row_style = 'style=""' if( !$row_style ); + $row_style =~ s/style=(.)/style=$1display:none;/; + } + + $ret .= sprintf("", ($row-1&1)?"odd":"even") if( $first ); + if( $visibility && ( $visibility eq "collapsed" || $visibility eq "collapsible" ) ) { + $ret .= ""; + } else { + $ret .= ""; + } + $first = 0; + ++$cell_column; + next; } elsif( $txt && $txt =~ m/^%([^%]*)(%(.*))?/ ) { my $icon = $1; my $cmd = $3; @@ -645,6 +695,13 @@ readingsGroup_2html($) my $name_style = lookup2($hash->{helper}{nameStyle},$name,$n,$v); my $value_style = lookup2($hash->{helper}{valueStyle},$name,$n,$v); + if( !$FW_webArgs{"detail"} ) { + if( $visibility && $visibility eq "collapsed" ) { + $row_style = 'style=""' if( !$row_style ); + $row_style =~ s/style=(.)/style=$1display:none;/; + } + } + my $value_format = lookup2($hash->{helper}{valueFormat},$name,$n,$v); next if( !defined($value_format) ); if( $value_format =~ m/%/ ) { @@ -1024,13 +1081,18 @@ readingsGroup_Set($@) { my ($hash, $name, $cmd, $param, @a) = @_; - my $list = "refresh:noArg"; + my $list = "visibility:toggle,toggle2"; if( $cmd eq "refresh" ) { readingsGroup_updateDevices($hash); return undef; + } elsif( $cmd eq "visibility" ) { + readingsGroup_updateDevices($hash); + DoTrigger( $hash->{NAME}, "visibility: $param" ); + return undef; } + return "Unknown argument $cmd, choose one of $list"; } @@ -1074,11 +1136,11 @@ readingsGroup_Attr($$$;$) if( $cmd eq "set" ) { my $attrVal = $attrVal; - if( $attrVal =~ m/^{.*}$/ ) { + if( $attrVal =~ m/^{.*}$/ && $attrVal =~ m/=>/ && $attrVal !~ m/\$/ ) { my $av = eval $attrVal; if( $@ ) { Log3 $hash->{NAME}, 3, $hash->{NAME} .": ". $@; - } else { + } else { $attrVal = $av if( ref($av) eq "HASH" ); } } @@ -1129,6 +1191,7 @@ readingsGroup_Attr($$$;$) Notes:
  • <device> can be of the form INTERNAL=VALUE where INTERNAL is the name of an internal value and VALUE is a regex.
  • +
  • <device> can be of the form ATTRIBUTE&VALUE where ATTRIBUTE is the name of an attribute and VALUE is a regex.
  • <device> can be of the form <STRING> or <{perl}> where STRING or the string returned by perl is inserted as a line in the readings list. skipped if STRING is undef.
  • If regex is a comma separatet list the reading values will be shown on a single line.
  • @@ -1206,23 +1269,23 @@ readingsGroup_Attr($$$;$) Attributes
    • alwaysTrigger
      - 1 -> alwaysTrigger update events. even if not visible.
    • + 1 -> alwaysTrigger update events. even if not visible.
    • disable
      1 -> disable notify processing and longpoll updates. Notice: this also disables rename and delete handling.
      2 -> also disable html table creation
      - 3 -> also disable html creation completely
    • + 3 -> also disable html creation completely
    • sortDevices
      1 -> sort the device lines alphabetically. use the first of sortby or alias or name that is defined for each device.
    • noheading
      - If set to 1 the readings table will have no heading.
    • + If set to 1 the readings table will have no heading.
    • nolinks
      - Disables the html links from the heading and the reading names.
    • + Disables the html links from the heading and the reading names.
    • nostate
      - If set to 1 the state reading is excluded.
    • + If set to 1 the state reading is excluded.
    • nonames
      - If set to 1 the reading name / row title is not displayed.
    • + If set to 1 the reading name / row title is not displayed.
    • notime
      - If set to 1 the reading timestamp is not displayed.
    • + If set to 1 the reading timestamp is not displayed.
    • mapping
      Can be a simple string or a perl expression enclosed in {} that returns a hash that maps reading names to the displayed name. The keys can be either the name of the reading or <device>.<reading>. @@ -1230,69 +1293,80 @@ readingsGroup_Attr($$$;$) group attribute and reading name respectively. You can also prefix these keywords with $ instead of %. Examples:
      attr temperatures mapping $DEVICE-$READING
      attr temperatures mapping {temperature => "%DEVICE Temperatur"} -
    • +
    • separator
      The separator to use between the device alias and the reading name if no mapping is given. Defaults to ':' - a space can be enteread as &nbsp;
    • + a space can be enteread as &nbsp;
    • style
      Specify an HTML style for the readings table, e.g.:
      - attr temperatures style style="font-size:20px"
    • + attr temperatures style style="font-size:20px"
    • cellStyle
      Specify an HTML style for a cell of the readings table. regular rows and colums are counted starting with 1, the row headings are column number 0. perl code has access to $ROW and $COLUMN. keys for hash lookup can be r:#, c:# or r:#,c:# , e.g.:
      - attr temperatures cellStyle { "c:0" => 'style="text-align:right"' }
    • + attr temperatures cellStyle { "c:0" => 'style="text-align:right"' }
    • nameStyle
      Specify an HTML style for the reading names, e.g.:
      - attr temperatures nameStyle style="font-weight:bold"
    • + attr temperatures nameStyle style="font-weight:bold"
    • valueStyle
      Specify an HTML style for the reading values, e.g.:
      - attr temperatures valueStyle style="text-align:right"
    • + attr temperatures valueStyle style="text-align:right"
    • valueColumn
      Specify the minimum column in which a reading should appear.
      - attr temperatures valueColumn { temperature => 2 }
    • + attr temperatures valueColumn { temperature => 2 }
    • valueColumns
      Specify an HTML colspan for the reading values, e.g.:
      - attr wzReceiverRG valueColumns { eventdescription => 'colspan="4"' }
    • + attr wzReceiverRG valueColumns { eventdescription => 'colspan="4"' }
    • valueFormat
      Specify an sprintf style format string used to display the reading values. If the format string is undef this reading will be skipped. Can be given as a string, a perl expression returning a hash or a perl expression returning a string, e.g.:
      attr temperatures valueFormat %.1f °C
      attr temperatures valueFormat { temperature => "%.1f °C", humidity => "%i %" }
      - attr temperatures valueFormat { ($READING eq 'temperature')?"%.1f °C":undef }
    • + attr temperatures valueFormat { ($READING eq 'temperature')?"%.1f °C":undef }
    • valuePrefix
      - text to be prepended to the reading value
    • + text to be prepended to the reading value
    • valueSuffix
      text to be appended after the reading value
      attr temperatures valueFormat { temperature => "%.1f", humidity => "%i" }
      - attr temperatures valueSuffix { temperature => "°C", humidity => " %" }
    • + attr temperatures valueSuffix { temperature => "°C", humidity => " %" }
    • nameIcon
      Specify the icon to be used instead of the reading name. Can be a simple string or a perl expression enclosed in {} that returns a hash that maps reading names to the icon name. e.g.:
      - attr devices nameIcon $DEVICE
    • + attr devices nameIcon $DEVICE
    • valueIcon
      Specify an icon to be used instead of the reading value. Can be a simple string or a perl expression enclosed in {} that returns a hash that maps reading value to the icon name. e.g.:
      attr devices valueIcon $VALUE
      attr devices valueIcon {state => '%VALUE'}
      attr devices valueIcon {state => '%devStateIcon'} - attr rgMediaPlayer valueIcon { "playStatus.paused" => "rc_PLAY", "playStatus.playing" => "rc_PAUSE" }
    • + attr rgMediaPlayer valueIcon { "playStatus.paused" => "rc_PLAY", "playStatus.playing" => "rc_PAUSE" }
    • commands
      Can be used in to different ways:
      • To make a reading or icon clickable by directly specifying the command that should be executed. eg.:
        - attr rgMediaPlayer commands { "playStatus.paused" => "set %DEVICE play", "playStatus.playing" => "set %DEVICE pause" }

      • + attr rgMediaPlayer commands { "playStatus.paused" => "set %DEVICE play", "playStatus.playing" => "set %DEVICE pause" }
      • Or if the mapped command is of the form <command>:[<modifier>] then the normal FHEMWEB webCmd widget for <modifier> will be used for this command. if <modifier> is omitted then the FHEMWEB lookup mechanism for <command> will be used. eg:
        attr rgMediaPlayer commands { volume => "volume:slider,0,1,100" }
        - attr lights commands { pct => "pct:", dim => "dim:" }
      • + attr lights commands { pct => "pct:", dim => "dim:" }
        +
    • visibility
      - if set will display a small button to the left of the readingsGroup name to expand/collapse the contenst of the readingsGroup. if a readingsGroup is expanded then all others in the same group will be collapsed.
      - hidden -> default state is hidden but can be expanded - hideable -> default state is visible but can be collapsed
    • -
    - + if set to hidden or hideable will display a small button to the left of the readingsGroup name to expand/hide the contents of the readingsGroup. if a readingsGroup is expanded then all others in the same group will be hidden.
    +
      + hidden -> default state is hidden but can be expanded
      + hideable -> default state is visible but can be hidden

      +
    + if set to collapsed or collapsible will recognise the specials <->,<+> and <+-> as the first elements of + a line to add a + or - symbol to this line. clicking on the + or - symbol will toggle between expanded and collapsed state. if a readingsGroup is expanded then all others in the same group will be collapsed. +
      + - -> line will be visible in expanded state
      + + -> line will be visible in collapsed state
      + +- -> line will be visible in both states
      +
      + collapsed-> default state is collapsed but can be expanded
      + collapsible -> default state is visible but can be collapsed +

The style, nameStyle and valueStyle attributes can also contain a perl expression enclosed in {} that returns the style diff --git a/fhem/www/pgm2/fhemweb_readingsGroup.js b/fhem/www/pgm2/fhemweb_readingsGroup.js new file mode 100644 index 000000000..b4e607dee --- /dev/null +++ b/fhem/www/pgm2/fhemweb_readingsGroup.js @@ -0,0 +1,95 @@ + +function +FW_readingsGroupToggle(d) { + var rg = document.getElementById( 'readingsGroup-'+d ); + if( rg ) { + s=rg.style; + s.display = s.display=='none' ? 'block' : 'none'; + + var group = rg.getAttribute('groupId'); + if( group ) { + var elArr = document.querySelectorAll( '[groupId='+group+']' ); + for( var k=0; k
updates disabled
$txt
$txt