From 2a2641ae1ece067d3c3c51ed00e6fece3ffff474 Mon Sep 17 00:00:00 2001 From: rudolfkoenig <> Date: Tue, 9 Oct 2012 07:05:32 +0000 Subject: [PATCH] Time-Picker, darkstyle fixes git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@1941 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- CHANGED | 4 ++- FHEM/01_FHEMWEB.pm | 80 ++++++++++++++++++++++-------------------- FHEM/11_FHT.pm | 3 +- docs/commandref.html | 10 ++++-- www/pgm2/darkstyle.css | 29 ++++++++++----- www/pgm2/fhemweb.js | 60 +++++++++++++++++++++++++++++-- www/pgm2/style.css | 15 ++++---- 7 files changed, 140 insertions(+), 61 deletions(-) diff --git a/CHANGED b/CHANGED index f7d0c706e..3f721ff8c 100644 --- a/CHANGED +++ b/CHANGED @@ -66,7 +66,9 @@ - feature: module IPCAM added. (M. Fischer) - feature: module HTTPSRV added (Boris) - feature: module FLOORPLAN added (Uli Maass) - - bugfix: FHEMWEB: weblink with group attribute is shown together with other elements + - bugfix: FHEMWEB: weblink with group attribute is shown together with other + elements + - feature: FHEMWEB: timepicker added - 2011-12-31 (5.2) diff --git a/FHEM/01_FHEMWEB.pm b/FHEM/01_FHEMWEB.pm index dbc947d4c..e093134b7 100755 --- a/FHEM/01_FHEMWEB.pm +++ b/FHEM/01_FHEMWEB.pm @@ -24,7 +24,6 @@ sub FW_makeImage($); sub FW_SetDirs(); sub FW_ReadIconsFrom($$); sub FW_ReadIcons($); -sub FW_GetIcons(); sub FW_IconURL($); sub FW_roomOverview($); sub FW_select($$$$@); @@ -341,7 +340,8 @@ FW_ServeSpecial($$$) { } sub -FW_SetDirs() { +FW_SetDirs() +{ # web server root if(-d "$attr{global}{modpath}/www") { @@ -413,12 +413,11 @@ FW_AnswerCall($) $FW_commandref = "$FW_docdir/commandref.html"; #Debug "commandref.html is at $FW_commandref"; - FW_GetIcons(); # get the icon set for the current instance $MW_dir = AttrVal($FW_wname, "fwmodpath", "$attr{global}{modpath}/FHEM"); $FW_ss = AttrVal($FW_wname, "smallscreen", 0); $FW_tp = AttrVal($FW_wname, "touchpad", $FW_ss); - my $prf = AttrVal($FW_wname, "stylesheetPrefix", ""); + %FW_icons= %{$defs{$FW_wname}{fhemIcons}}; # Lets go: if($arg =~ m,^$FW_ME/docs/(.*)\.(html|txt|pdf)$,) { @@ -580,6 +579,7 @@ FW_AnswerCall($) FW_pO "" if($rf); } + my $prf = AttrVal($FW_wname, "stylesheetPrefix", ""); $prf = "smallscreen" if(!$prf && $FW_ss); $prf = "touchpad" if(!$prf && $FW_tp); FW_pO ""; @@ -778,9 +778,9 @@ FW_makeSelect($$$$) ############################## sub -FW_makeImage($) { - -my ($name)= @_; +FW_makeImage($) +{ + my ($name)= @_; my $iconpath= FW_IconPath($name); if(defined($iconpath)) { my $iconurl= FW_IconURL($name); @@ -962,7 +962,6 @@ FW_roomOverview($) } else { - FW_GetIcons(); # get the icon set for the current instance foreach(my $idx = 0; $idx < @list1; $idx++) { my ($l1, $l2) = ($list1[$idx], $list2[$idx]); if(!$l1) { @@ -997,7 +996,6 @@ FW_showRoom() { return if(!$FW_room); - FW_GetIcons(); # get the icon set for the current instance FW_pO "
"; FW_pO "
"; @@ -1076,26 +1074,39 @@ FW_showRoom() if($values =~ m/^slider,(.*),(.*),(.*)/) { ##### Slider my ($min,$stp, $max) = ($1, $2, $3); my $srf = $FW_room ? "&room=$FW_room" : ""; - my $curr = ReadingsVal($d, $cmd, Value($d)); + my $cv = ReadingsVal($d, $cmd, Value($d)); $cmd = "" if($cmd eq "state"); - $curr=~s/[^\d\.]//g; + $cv =~ s/[^\d\.]//g; FW_pO "". "
". "
$min
". "
". "". ""; $firstIdx=1; + } elsif($values =~ m/^time$/) { ##### Time picker + my $srf = $FW_room ? "&room=$FW_room" : ""; + my $cv = ReadingsVal($d, $cmd, Value($d)); + $cmd = "" if($cmd eq "state"); + my $c = "\"$FW_ME?cmd=set $d $cmd %$srf\""; + FW_pO "". + "". + "". + ""; + $firstIdx=1; + } else { ##### Dropdown my @tv = split(",", $values); - # Hack: eventmap (translation only) should not result in a dropdown. - # eventMap/webCmd/etc handling must be cleaned up. + # Hack: eventmap (translation only) should not result in a + # dropdown. eventMap/webCmd/etc handling must be cleaned up. if(@tv > 1) { $firstIdx=1; if($cmd eq "desired-temp") { @@ -1819,7 +1830,6 @@ FW_style($$) $ret = ""; } elsif($a[1] eq "iconFor") { - FW_GetIcons(); # get the icon set for the current instance FW_pO "
"; foreach my $i (sort grep {/^ico/} keys %FW_icons) { FW_pO "
"; @@ -2079,12 +2089,12 @@ FW_Attr(@) } +# recursively reads .gif .ico .jpg .png files and returns filenames as array +# recursion starts at $FW_icondir/$dir +# filenames are relative to $FW_icondir sub -FW_ReadIconsFrom($$) { - # recursively reads .gif .ico .jpg .png files and returns filenames as array - # recursion starts at $FW_icondir/$dir - # filenames are relative to $FW_icondir - +FW_ReadIconsFrom($$) +{ my ($prepend,$dir)= @_; return if($dir =~ m,/\.svn,); @@ -2108,7 +2118,7 @@ FW_ReadIconsFrom($$) { if($entry =~ m/^(.*)\.($ICONEXTENSION)$/i) { my $logicalname= $1; my $iconname= "${prepend}${logicalname}"; - #Debug " icon: \"$iconname\""; + #Debug " icon: $iconname / $filename"; $FW_icons{$iconname}= $filename; } } @@ -2140,7 +2150,8 @@ FW_ReadIcons($) # if now icons were found so far, read icons from icondir itself FW_ReadIconsFrom("", "") unless(%FW_icons); - $hash->{fhemIcons} = \%FW_icons; + my %icons = %FW_icons; + $hash->{fhemIcons} = \%icons; my $dumpLevel = 4; if($attr{global}{verbose} >= $dumpLevel) { @@ -2149,15 +2160,6 @@ FW_ReadIcons($) Log $dumpLevel, " $k => " . $FW_icons{$k}; } } - -} - -# get the icon set from the device -sub -FW_GetIcons() { - #Debug "Getting icons for $FW_wname."; - my $hash= $defs{$FW_wname}; - %FW_icons= %{$hash->{fhemIcons}}; } sub @@ -2165,13 +2167,15 @@ FW_canonicalizeIcon($) { my ($name)= @_; if($name =~ m/^(.*)\.($ICONEXTENSION)$/) { Log 1, "WARNING: argument of FW_canonicalizeIcon($name) has extension - inform the developers!"; + $name= $1; } return $name; } sub -FW_getIcon($) { +FW_getIcon($) +{ my ($name)= @_; $name= FW_canonicalizeIcon($name); return $FW_icons{$name} ? $name : undef; @@ -2182,10 +2186,10 @@ FW_getIcon($) { # FS20.on -> $FW_icondir/dark/FS20.on.png # weather/sunny -> $FW_icondir/default/weather/sunny.gif sub -FW_IconPath($) { +FW_IconPath($) +{ my ($name)= @_; $name= FW_canonicalizeIcon($name); - FW_GetIcons(); # get the icon set for the current instance my $path= $FW_icons{$name}; return $path ? $FW_icondir . "/" . $path : undef; } @@ -2194,7 +2198,9 @@ FW_IconPath($) { # examples: # FS20.on -> /icons/FS20.on # weather/sunny -> /icons/sunny -sub FW_IconURL($) { +sub +FW_IconURL($) +{ my ($name)= @_; $name= FW_canonicalizeIcon($name); return "$FW_ME/icons/${name}"; @@ -2308,8 +2314,6 @@ FW_Notify($$) my $rn = AttrVal($dn, "room", ""); if($filter eq "all" || $rn =~ m/\b$filter\b/) { - FW_GetIcons(); # get the icon set for the current instance - my @old = ($FW_wname, $FW_ME, $FW_longpoll, $FW_ss, $FW_tp, $FW_subdir); $FW_wname = $ntfy->{SNAME}; $FW_ME = "/" . AttrVal($FW_wname, "webname", "fhem"); @@ -2450,7 +2454,7 @@ FW_Get($@) { my ($hash, @a) = @_; $FW_wname= $hash->{NAME}; - + %FW_icons= %{$hash->{fhemIcons}}; if($a[1] eq "icon") { return "need one icon as argument" if(int(@a) != 3); diff --git a/FHEM/11_FHT.pm b/FHEM/11_FHT.pm index 338be664f..9713ec01b 100755 --- a/FHEM/11_FHT.pm +++ b/FHEM/11_FHT.pm @@ -212,7 +212,8 @@ FHT_Set($@) my @list = map { ($_.".0", $_+0.5) } (6..30); pop @list; my $tmpList="on,off,".join(",",@list); - $cmdList =~ s/-temp/-temp:$tmpList/g; + $cmdList =~ s/-temp/-temp:$tmpList/g; # FHEMWEB sugar + $cmdList =~ s/(-from.|-to.)/$1:time/g; return "Unknown argument $cmd, choose one of $cmdList"; } diff --git a/docs/commandref.html b/docs/commandref.html index 0249fd2c6..2c2f6f030 100644 --- a/docs/commandref.html +++ b/docs/commandref.html @@ -9918,8 +9918,9 @@ KlikAanKlikUit, NEXA, CHACON, HomeEasy UK.
You need to define an RFXtrx433 If the first value references a command, for which "set device ?" lists a number possible choices (e.g. desired-temp for FHT devices), then a select widget will be displayed. If the values are - "slider,min,step,max", then a javascript driven slider is displayed. If - the command is state, then the value will be used as a command.
+ "slider,min,step,max", then a javascript driven slider is displayed. + if the value is "time", then a javascript timepicker is displayed. + If the command is state, then the value will be used as a command.
Examples:
    attr lamp webCmd on:off:on-for-timer 10
    @@ -9929,8 +9930,11 @@ KlikAanKlikUit, NEXA, CHACON, HomeEasy UK.
    You need to define an RFXtrx433 define d2 dummy
    attr d2 webCmd state
    attr d2 set setList state:slider,0,1,10
    + define d3 dummy
    + attr d3 webCmd state
    + attr d3 set setList state:time
- Note: this an attribute for the displayed device, not for the FHEMWEB + Note: this is an attribute for the displayed device, not for the FHEMWEB instance.
diff --git a/www/pgm2/darkstyle.css b/www/pgm2/darkstyle.css index 36249f275..066ce1d2d 100644 --- a/www/pgm2/darkstyle.css +++ b/www/pgm2/darkstyle.css @@ -7,10 +7,12 @@ body { background-color: #444444; background-image:url(../icons/darklogo); b a { color: #CCCCCC; text-decoration: none;} a:hover { color: #ffffff; } -table.block { border:1px solid #ffffff; width: 100%; background: #333333; box-shadow:5px 5px 5px #000; } +table.block { border:1px solid #ffffff; width: 100%; + background: #333333; box-shadow:5px 5px 5px #000; } table.block tr.odd { background: #111111; } table.block tr.sel { background: red; } -table { -moz-border-radius:8px; border-radius:8px; border-spacing: 0px; padding-bottom: 6px; padding-top: 6px;} +table { border-radius:8px; border-spacing: 0px; + padding-bottom: 6px; padding-top: 6px;} table#room { background: #111111; width: 140px;} table#room a { color: #CCCCCC; text-decoration: none; } @@ -18,10 +20,15 @@ table#room a:hover { color: #ffffff; } table#room tr.sel { background: red; } th {color:red; text-align: left; padding-left: 10px; font-weight: bold;} td {padding-left: 10px; padding-right: 10px; padding-top: 3px; padding-bottom: 3px;} -input {outline:none; background-color: #111111; border: 1px solid #ffffff; color: #cccccc; padding:5px; margin-left: 10px; border-radius:8px; box-shadow: 5px 5px 5px #000000;} +input {outline:none; background-color: #111111; + border: 1px solid #ffffff; color: #cccccc; padding:5px; + margin-left: 10px; border-radius:8px; box-shadow: 5px 5px 5px #000000;} input:focus {border: 1px solid red;} -textarea {min-width:1000px; background-color: #111111; border: 1px solid #ffffff; color: #cccccc; padding:5px; margin-left: 10px; border-radius:8px; box-shadow: 5px 5px 5px #000000;} +textarea {min-width:1000px; background-color: #111111; + border: 1px solid #ffffff; color: #cccccc; + padding:5px; margin-left: 10px; + border-radius:8px; box-shadow: 5px 5px 5px #000000;} /* next lines are for commandref and faq @@ -37,10 +44,14 @@ h2,h3,h4 { color:#EEE; line-height:1.3; margin-top:1.5em; font-family:Verdana; } select.attr,input.attr,select.set,input.set { margin-bottom:10px; } a img { border-style:none; } -set,.attr { margin-bottom:10px; float:left; } -.slider { float:right; width:250px; height:26px;} -.set .slider { margin-left:10px; background:#101010; - -moz-border-radius:8px; border-radius:8px; } +/* detail-selector & slider */ +select { margin-left:5px; margin-right:5px; } +.set,.attr { margin-bottom:5px; float:left; } +.slider { margin-left:10px; float:left; width:250px; height:26px; } +.set .slider { background:#101010; border-radius:8px; } +/* timepicker */ +.set .set { margin-bottom:2px; margin-top:3px; } + .handle { position:relative; cursor:pointer; width:50px; height:20px; - line-height:20px; border:3px solid; color:white; text-align:center; } + line-height:20px; border:2px solid; color:white; text-align:center; } .downText { margin-top:2px; } diff --git a/www/pgm2/fhemweb.js b/www/pgm2/fhemweb.js index 258064906..9c7e71d11 100644 --- a/www/pgm2/fhemweb.js +++ b/www/pgm2/fhemweb.js @@ -100,6 +100,9 @@ Slider(slider, min, stp, max, curr, cmd) val = Math.floor(Math.floor(val/stp)*stp); sh.innerHTML = val; sh.setAttribute('style', 'left:'+offX+'px;'); + if(cmd && cmd.substring(0,3) == "js:") { + eval(cmd.substring(3).replace('%',val)); + } } document.onmousemove = mouseMove; document.ontouchmove = function(e) { touchFn(e, mouseMove); } @@ -109,7 +112,9 @@ Slider(slider, min, stp, max, curr, cmd) document.onmousemove = oldFn1; document.onmouseup = oldFn2; document.ontouchmove = oldFn3; document.ontouchend = oldFn4; if(cmd) { - document.location = cmd.replace('%',val); + if(cmd.substring(0,3) != "js:") { + document.location = cmd.replace('%',val); + } } else { slider.nextSibling.setAttribute('value', val); } @@ -119,10 +124,54 @@ Slider(slider, min, stp, max, curr, cmd) sh.onselectstart = function() { return false; } sh.onmousedown = mouseDown; sh.ontouchstart = function(e) { touchFn(e, mouseDown); } - } +function +setTime(el,name,val) +{ + var el = el.parentNode.parentNode.firstChild; + var v = el.value.split(":"); + v[name == "H" ? 0 : 1] = ''+val; + if(v[0].length < 2) v[0] = '0'+v[0]; + if(v[1].length < 2) v[1] = '0'+v[1]; + el.value = v[0]+":"+v[1]; + el.setAttribute('value', el.value); +} + +function +addTime(el,cmd) +{ + var par = el.parentNode; + var v = par.firstChild.value; + var brOff = par.innerHTML.indexOf("
"); + + if(brOff > 0) { + par.innerHTML = par.innerHTML.substring(0, brOff).replace('"-"','"+"'); + if(cmd) + document.location = cmd.replace('%',v); + return; + } + + el.setAttribute('value', '-'); + if(v.indexOf(":") < 0) + par.firstChild.value = v = "12:00"; + var val = v.split(":"); + + for(var i = 0; i < 2; i++) { + par.appendChild(document.createElement('br')); + + var sl = document.createElement('div'); + sl.innerHTML = '
'+val[i]+ + '
'; + par.appendChild(sl); + sl.setAttribute('class', par.getAttribute('class')); + + Slider(sl.firstChild, 0, (i==0 ? 1 : 5), (i==0 ? 23 : 55), val[i], + 'js:setTime(slider,"'+(i==0? "H":"M")+'",%)'); + } +} + /*************** Select **************/ /** Change attr/set argument type to input:text or select **/ function @@ -156,6 +205,11 @@ FW_selChange(sel, list, elName) ''; Slider(newEl.firstChild, min, stp, max, undefined, undefined); + } else if(vArr.length == 1 && vArr[0] == "time") { + newEl = document.createElement('div'); + newEl.innerHTML=''+ + ''; + } else { newEl = document.createElement('select'); for(var j=0; j < vArr.length; j++) { @@ -164,7 +218,7 @@ FW_selChange(sel, list, elName) } } - newEl.setAttribute('class', el.getAttribute('class')); //changed from el.class + newEl.setAttribute('class', el.getAttribute('class')); newEl.setAttribute('name', el.getAttribute('name')); el.parentNode.replaceChild(newEl, el); diff --git a/www/pgm2/style.css b/www/pgm2/style.css index 2ddfcf0d2..c08ec46d0 100644 --- a/www/pgm2/style.css +++ b/www/pgm2/style.css @@ -18,7 +18,7 @@ img { border-style: none; } table.block { border:1px solid gray; background: #F8F8E0; } table.block tr.odd { background: #F0F0D8; } table.block tr.sel { background: #F0F0D8; } -table { -moz-border-radius:8px; border-radius:8px; } +table { border-radius:8px; } table#room { border:1px solid gray; width: 100%; background: #D7FFFF; } table#room tr.sel { background: #A0FFFF; } @@ -31,12 +31,15 @@ div#dist { padding-top:0.3em; } a img { border-style:none; } +/* detail-selector & slider */ +select { margin-left:5px; margin-right:5px; } .set,.attr { margin-bottom:5px; float:left; } -.slider { float:right; width:250px; height:26px; } -.set .slider { margin-left:10px; background:#F0F0D8; - -moz-border-radius:8px; border-radius:8px; } +.slider { float:left; width:250px; height:26px; } +.set .slider { background:#F0F0D8; border-radius:8px; } +/* timepicker */ +.set .set { margin-bottom:2px; margin-top:3px; } + .handle { position:relative; cursor:pointer; width:50px; - height:20px; line-height:20px; - -moz-user-select:none; user-select:none; + height:20px; line-height:20px; user-select:none; border:3px solid; color:#278727; text-align:center; } .downText { margin-top:2px; }