diff --git a/fhem/CHANGED b/fhem/CHANGED
index 831936d9d..a657a9299 100644
--- a/fhem/CHANGED
+++ b/fhem/CHANGED
@@ -1,5 +1,7 @@
# 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.
+ - new /www/pgm2/fhemweb_icon*.js: new widgets for FHEMWEB iconButtons,
+ iconLabel, iconRadio, iconSwitch (Forum:#75696)
- bugfix: 93_DbRep: V5.6.3, crash due to wrong timestamp calc (Forum:#77328)
- change: 01_FHEMWEB.js: on demand loading of fhemweb_*.js (Forum #76868)
- bugfix: 73_GardenaSmartBridge: fix part of code
diff --git a/fhem/MAINTAINER.txt b/fhem/MAINTAINER.txt
index 4f1db7592..5641b0633 100644
--- a/fhem/MAINTAINER.txt
+++ b/fhem/MAINTAINER.txt
@@ -526,6 +526,10 @@ www/jscolor/* justme1968 Frontends
www/pgm2/* rudolfkoenig Frontends/FHEMWEB
www/pgm2/dashboard/* svenson08 Frontends
www/pgm2/fhemweb_fbcalllist.js markusbloch Frontends
+www/pgm2/fhemweb_iconButtons.js Ellert Frontends
+www/pgm2/fhemweb_iconLabel.js Ellert Frontends
+www/pgm2/fhemweb_iconRadio.js Ellert Frontends
+www/pgm2/fhemweb_iconSwitch.js Ellert Frontends
www/pgm2/fhemweb_readingsGroup.js justme1968 Frontends/readingsGroup readingsHistory
www/pgm2/fhemweb_readingsHistory.js justme1968 Frontends/readingsGroup readingsHistory
www/pgm2/fhemweb_sortable.js markusbloch Frontends
diff --git a/fhem/www/pgm2/fhemweb_iconButtons.js b/fhem/www/pgm2/fhemweb_iconButtons.js
new file mode 100644
index 000000000..050856553
--- /dev/null
+++ b/fhem/www/pgm2/fhemweb_iconButtons.js
@@ -0,0 +1,122 @@
+
+FW_version["fhemweb_iconButtons.js"] = "$Id$";
+
+FW_widgets['iconButtons'] = {
+ createFn:FW_iconButtonsCreate,
+};
+
+/********* iconButtons *********/
+function
+FW_iconButtonsCreate(elName, devName, vArr, currVal, set, params, cmd)
+{
+ if( 0 ) {
+ console.log( "elName: "+elName );
+ console.log( "devName: "+devName );
+ console.log( "vArr: "+vArr );
+ console.log( "currVal: "+currVal );
+ console.log( "set: "+set );
+ console.log( "params: "+params );
+ console.log( "cmd: "+cmd );
+ }
+
+ if(!vArr.length || vArr[0] != "iconButtons")
+ return undefined;
+ var ipar = 2;
+
+ if( vArr[1].match(/^[A-F0-9]{6}$/))
+ vArr[1] = "#"+vArr[1];
+
+ var newEl = $("
").get(0);
+ $(newEl).addClass(vArr[0]);
+
+ var hidden;
+ if(elName)
+ hidden = $('
');
+ $(newEl).append(hidden);
+
+ var clicked = function(arg) { var new_val=newEl.getValueFn(arg);
+ newEl.setValueFn( new_val );
+ if( cmd )
+ cmd(new_val);
+ };
+
+ var buttons = [];
+ for( var i = 2; i < (vArr.length); i+=ipar ) {
+ var button = $('
').uniqueId();
+ var label = $('
');
+ buttons.push(button);
+
+ $(newEl).append(button);
+ $(newEl).append(label);
+
+ $(button).change(clicked);
+ }
+
+ $(newEl).buttonset();
+ $(newEl).find("label").css({"margin":"0","border":"0","border-radius":"4px","background":"inherit"});
+ $(newEl).find("span").css({"padding":"0.0em 0.3em"});
+
+ $(newEl).find("Label").each(function(ind,val){
+ $(val).addClass("iconButtons_widget")
+
+ var ico = vArr[ind*ipar+3];
+ FW_cmd(FW_root+"?cmd={FW_makeImage('"+ico+"')}&XHR=1",function(data){
+ data = data.replace(/\n$/,'');
+ $(newEl).find("label").each(function(ind,val){
+ var re = new RegExp("\"\s?"+$(val).attr("name")+"(\s?|\")","i");
+ if (!(data.match(re) === null) && ($(val).find("span").html().match(re) === null)) {
+ $(val).find("span").addClass("iconButtons_widget").html(data);
+ return false;
+ }
+ });
+
+ });
+
+ });
+ if( !currVal )
+ currVal = ",";
+
+ newEl.getValueFn = function(arg) { var new_val="";
+ for( var i = 0; i < buttons.length; ++i ) {
+ var button = buttons[i];
+ if( $(button).prop("checked") ) {
+ button.next().css({"background-color":vArr[1]});
+ if( new_val ) new_val += ',';
+ new_val += $(button).button( "option", "label")
+ }
+ }
+ if( !new_val ) return ',';
+ return new_val;
+ };
+
+ newEl.setValueFn = function(arg){ if( !arg ) arg = ',';
+ if( hidden )
+ hidden.attr("value", arg);
+ for( var i = 0; i < buttons.length; ++i ) {
+ var button = buttons[i];
+ button.prop("checked", arg.match(new RegExp('(^|,)'+vArr[i*ipar+2]+'($|,)') ) );
+ if (button.prop("checked")==true){
+ button.next().css({"background-color":vArr[1]});
+ } else {
+ button.next().css({"background-color":"inherit"});
+ }
+ button.button("refresh");
+ }
+ };
+
+ newEl.setValueFn( currVal );
+
+ return newEl;
+}
+
+/*
+=pod
+=begin html
+
+=end html
+
+=begin html_DE
+
+=end html_DE
+=cut
+*/
diff --git a/fhem/www/pgm2/fhemweb_iconLabel.js b/fhem/www/pgm2/fhemweb_iconLabel.js
new file mode 100644
index 000000000..57047d1c1
--- /dev/null
+++ b/fhem/www/pgm2/fhemweb_iconLabel.js
@@ -0,0 +1,105 @@
+
+FW_version["fhemweb_iconLabel.js"] = "$Id$";
+
+FW_widgets['iconLabel'] = {
+ createFn:FW_IconLabelCreate,
+};
+
+/********* iconLabel *********/
+function
+FW_IconLabelCreate(elName, devName, vArr, currVal, set, params, cmd)
+{
+ if( 0 ) {
+ console.log( "elName: "+elName );
+ console.log( "devName: "+devName );
+ console.log( "vArr: "+vArr );
+ console.log( "currVal: "+currVal );
+ console.log( "set: "+set );
+ console.log( "params: "+params );
+ console.log( "cmd: "+cmd );
+ }
+
+ if(vArr.length<1 || vArr[0] != "iconLabel")
+ return undefined;
+ var newEl = $("
").get(0);
+
+ var ipar = 2;
+ for( var i = 1; i < (vArr.length); i+=ipar ) {
+ vArr[i] = vArr[i].replace(/#/g," ");
+ }
+ var hidden;
+ if(elName)
+ hidden = $('
');
+ $(newEl).append(hidden);
+
+ var button = $('
').uniqueId();
+
+ var label = $('