diff --git a/README.md b/README.md
index 6fb5732..eea9ee1 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,8 @@ Download zip package, extract the onetopic folder and upload this folder into co
### 2024050905:
* New tab styles editor when editing each section.
+* Select icon by tab and tab state.
+* New background option by section.
### 2024050904:
* New "sectionname" parameter to navigate to a tab directly using its name.
diff --git a/amd/build/onetopicbackground.min.js b/amd/build/onetopicbackground.min.js
new file mode 100644
index 0000000..d10cd6f
--- /dev/null
+++ b/amd/build/onetopicbackground.min.js
@@ -0,0 +1,10 @@
+define("format_onetopic/onetopicbackground",["exports","jquery","core/modal_factory","core/modal_save_cancel","core/modal_events"],(function(_exports,_jquery,_modal_factory,_modal_save_cancel,_modal_events){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
+/**
+ * Onetopic background selector.
+ *
+ * @module format_onetopic/onetopicbackground
+ * @copyright 2021 David Herney Bernal - cirano
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_jquery=_interopRequireDefault(_jquery),_modal_factory=_interopRequireDefault(_modal_factory),_modal_save_cancel=_interopRequireDefault(_modal_save_cancel),_modal_events=_interopRequireDefault(_modal_events);_exports.init=controlid=>{var $controlinput=(0,_jquery.default)("#"+controlid),$control=$controlinput.parent(".backgroundpicker"),$controlwindow=$control.find(".backgroundpickerwindow"),$controlbutton=$control.find(".backgroundpickerselector"),$colorpickerinput=$controlwindow.find('input.form-control[type="text"]'),title=$controlwindow.attr("title"),buttons=[];buttons.save=$controlwindow.data("savelabel");_modal_factory.default.create({title:title,body:$controlwindow,type:_modal_save_cancel.default.TYPE,large:!0,buttons:buttons}).done((function(modal){modal.getBody().append($controlwindow),$control.data("modal",modal),function(modal){modal.getRoot().on(_modal_events.default.cancel,(()=>{modal.hide()})),modal.getRoot().on(_modal_events.default.save,(()=>{var newcolor=$colorpickerinput.val(),val=$controlinput.val(),color=readColor(val);color?val=val.replace(color,newcolor):""===val.trim()?val=newcolor:val+=" "+newcolor,$controlinput.val(val),modal.hide()}))}(modal)})),$controlbutton.on("click",(function(e){e.preventDefault(),$controlwindow.removeClass("hidden");var currentval=$controlinput.val(),color=readColor(currentval);$colorpickerinput.val(color),$control.data("modal").show()}))};var readColor=function(text){var regexcolor=new RegExp(/#[0-9a-fA-F]{6}/.source+/|#[0-9a-fA-F]{3}/.source+/|rgba?\(\s*([0-9]{1,3}\s*,\s*){2}[0-9]{1,3}\s*(,\s*[0-9.]+\s*)?\)/.source+/|hsla?\(\s*([0-9]{1,3}\s*,\s*){2}[0-9]{1,3}\s*(,\s*[0-9.]+\s*)?\)/.source),color=text.match(regexcolor);return color&&(color=color[0]),color}}));
+
+//# sourceMappingURL=onetopicbackground.min.js.map
\ No newline at end of file
diff --git a/amd/build/onetopicbackground.min.js.map b/amd/build/onetopicbackground.min.js.map
new file mode 100644
index 0000000..b158520
--- /dev/null
+++ b/amd/build/onetopicbackground.min.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"onetopicbackground.min.js","sources":["../src/onetopicbackground.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Onetopic background selector.\n *\n * @module format_onetopic/onetopicbackground\n * @copyright 2021 David Herney Bernal - cirano\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport $ from 'jquery';\nimport ModalFactory from 'core/modal_factory';\nimport ModalSaveCancel from 'core/modal_save_cancel';\nimport ModalEvents from 'core/modal_events';\n\n/**\n * Component initialization.\n *\n * @method init\n * @param {String} controlid The control id.\n */\nexport const init = (controlid) => {\n\n var $controlinput = $('#' + controlid);\n var $control = $controlinput.parent('.backgroundpicker');\n var $controlwindow = $control.find('.backgroundpickerwindow');\n var $controlbutton = $control.find('.backgroundpickerselector');\n var $colorpickerinput = $controlwindow.find('input.form-control[type=\"text\"]');\n\n // Initialize the modal window.\n var title = $controlwindow.attr('title');\n var buttons = [];\n buttons['save'] = $controlwindow.data('savelabel');\n\n var setEvents = function(modal) {\n modal.getRoot().on(ModalEvents.cancel, () => {\n modal.hide();\n });\n\n modal.getRoot().on(ModalEvents.save, () => {\n var newcolor = $colorpickerinput.val();\n var val = $controlinput.val();\n var color = readColor(val);\n if (color) {\n val = val.replace(color, newcolor);\n } else if (val.trim() === '') {\n val = newcolor;\n } else {\n val += ' ' + newcolor;\n }\n $controlinput.val(val);\n modal.hide();\n });\n };\n\n ModalFactory.create({\n 'title': title,\n 'body': $controlwindow,\n 'type': ModalSaveCancel.TYPE,\n 'large': true,\n 'buttons': buttons\n })\n .done(function(modal) {\n var $modalBody = modal.getBody();\n $modalBody.append($controlwindow);\n $control.data('modal', modal);\n setEvents(modal);\n });\n\n // Color picker control.\n $controlbutton.on('click', function(e) {\n e.preventDefault();\n $controlwindow.removeClass('hidden');\n var currentval = $controlinput.val();\n\n var color = readColor(currentval);\n\n $colorpickerinput.val(color);\n $control.data('modal').show();\n });\n\n};\n\n/**\n * Extracts the first color from a text string. Recognizes hexadecimal, rgba and hsla.\n *\n * @param {string} text\n * @returns\n */\nvar readColor = function(text) {\n var regexcolor = new RegExp(\n /#[0-9a-fA-F]{6}/.source\n + /|#[0-9a-fA-F]{3}/.source\n + /|rgba?\\(\\s*([0-9]{1,3}\\s*,\\s*){2}[0-9]{1,3}\\s*(,\\s*[0-9.]+\\s*)?\\)/.source\n + /|hsla?\\(\\s*([0-9]{1,3}\\s*,\\s*){2}[0-9]{1,3}\\s*(,\\s*[0-9.]+\\s*)?\\)/.source);\n\n var color = text.match(regexcolor);\n if (color) {\n color = color[0];\n }\n\n return color;\n};\n"],"names":["controlid","$controlinput","$control","parent","$controlwindow","find","$controlbutton","$colorpickerinput","title","attr","buttons","data","create","ModalSaveCancel","TYPE","done","modal","getBody","append","getRoot","on","ModalEvents","cancel","hide","save","newcolor","val","color","readColor","replace","trim","setEvents","e","preventDefault","removeClass","currentval","show","text","regexcolor","RegExp","source","match"],"mappings":";;;;;;;gTAiCqBA,gBAEbC,eAAgB,mBAAE,IAAMD,WACxBE,SAAWD,cAAcE,OAAO,qBAChCC,eAAiBF,SAASG,KAAK,2BAC/BC,eAAiBJ,SAASG,KAAK,6BAC/BE,kBAAoBH,eAAeC,KAAK,mCAGxCG,MAAQJ,eAAeK,KAAK,SAC5BC,QAAU,GACdA,QAAO,KAAWN,eAAeO,KAAK,oCAuBzBC,OAAO,OACPJ,WACDJ,oBACAS,2BAAgBC,YACf,UACEJ,UAEdK,MAAK,SAASC,OACMA,MAAMC,UACZC,OAAOd,gBAClBF,SAASS,KAAK,QAASK,OA/BX,SAASA,OACrBA,MAAMG,UAAUC,GAAGC,sBAAYC,QAAQ,KACnCN,MAAMO,UAGVP,MAAMG,UAAUC,GAAGC,sBAAYG,MAAM,SAC7BC,SAAWlB,kBAAkBmB,MAC7BA,IAAMzB,cAAcyB,MACpBC,MAAQC,UAAUF,KAClBC,MACAD,IAAMA,IAAIG,QAAQF,MAAOF,UACH,KAAfC,IAAII,OACXJ,IAAMD,SAENC,KAAO,IAAMD,SAEjBxB,cAAcyB,IAAIA,KAClBV,MAAMO,UAeVQ,CAAUf,UAIdV,eAAec,GAAG,SAAS,SAASY,GAChCA,EAAEC,iBACF7B,eAAe8B,YAAY,cACvBC,WAAalC,cAAcyB,MAE3BC,MAAQC,UAAUO,YAEtB5B,kBAAkBmB,IAAIC,OACtBzB,SAASS,KAAK,SAASyB,eAW3BR,UAAY,SAASS,UACjBC,WAAa,IAAIC,OACjB,kBAAkBC,OAChB,mBAAmBA,OACnB,oEAAoEA,OACpE,oEAAoEA,QAEtEb,MAAQU,KAAKI,MAAMH,mBACnBX,QACAA,MAAQA,MAAM,IAGXA"}
\ No newline at end of file
diff --git a/amd/build/tabstyles.min.js b/amd/build/tabstyles.min.js
index e52a0c1..4ea45cb 100644
--- a/amd/build/tabstyles.min.js
+++ b/amd/build/tabstyles.min.js
@@ -5,6 +5,6 @@ define("format_onetopic/tabstyles",["exports","jquery","core/modal_factory"],(fu
* @module format_onetopic/tabstyles
* @copyright 2021 David Herney Bernal - cirano
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_jquery=_interopRequireDefault(_jquery),_modal_factory=_interopRequireDefault(_modal_factory);var $tabstyles=null,$styleswindow=null,currenttype="default",globalstyles={},$inputtosave=null;_exports.init=()=>{if($tabstyles=(0,_jquery.default)("#onetopic-tabstyles"),$inputtosave=$tabstyles.find("textarea.savecontrol"),$styleswindow=(0,_jquery.default)("#onetopic-styleswindow"),(0,_jquery.default)("#onetopic-tabstyles .tpl-tabdefault .tabicon").each((function(){var $tabicon=(0,_jquery.default)(this);$tabicon.append(''),$tabicon.append('')})),(0,_jquery.default)("#onetopic-tabstyles .tpl-tabactive .tabicon").each((function(){var $tabicon=(0,_jquery.default)(this);$tabicon.append(''),$tabicon.append('')})),(0,_jquery.default)("#onetopic-tabstyles .tpl-tabparent .tabicon").each((function(){var $tabicon=(0,_jquery.default)(this);$tabicon.append(''),$tabicon.append(''),$tabicon.append('')})),(0,_jquery.default)("#onetopic-tabstyles .tpl-tabchildindex .tabicon").each((function(){var $tabicon=(0,_jquery.default)(this);$tabicon.append(''),$tabicon.append(''),$tabicon.append(''),$tabicon.append('')})),(0,_jquery.default)("#onetopic-tabstyles .tpl-tabchild .tabicon").each((function(){var $tabicon=(0,_jquery.default)(this);$tabicon.append(''),$tabicon.append(''),$tabicon.append('')})),(0,_jquery.default)("#onetopic-tabstyles .tpl-tabhighlighted .tabicon").each((function(){var $tabicon=(0,_jquery.default)(this);$tabicon.append(''),$tabicon.append(''),$tabicon.append('')})),(0,_jquery.default)("#onetopic-tabstyles .tpl-tabdisabled .tabicon").each((function(){(0,_jquery.default)(this).append('')})),(0,_jquery.default)("#onetopic-tabstyles .tabicon").each((function(){(0,_jquery.default)(this).removeClass("hidden")})),""!==$inputtosave.val().trim()){try{null===(globalstyles=JSON.parse($inputtosave.val()))&&(globalstyles={})}catch(e){console.error(e),globalstyles={}}applyStyles()}var $colorpicker=$styleswindow.find(".colorpicker"),$setcolor=$colorpicker.find('[data-action="setcolor"]'),$colorpickerinput=$colorpicker.find("input");$styleswindow.find('[data-control="colorpicker"]').on("click",(function(){var $node=(0,_jquery.default)(this);$colorpicker.show(),$colorpickerinput.val($node.val()),$setcolor.data("target",$node)})).on("change",(function(){var $node=(0,_jquery.default)(this),color=$node.val().trim();$node.css("background-color",color)})),$setcolor.on("click",(function(e){e.preventDefault(),$colorpicker.hide(),$setcolor.data("target").val($colorpickerinput.val()).trigger("change")})),$colorpicker.find('[data-action="cancel"]').on("click",(function(){$colorpicker.hide()}));var title=$styleswindow.data("title");_modal_factory.default.create({title:title,body:""}).done((function(modal){var $modalBody=modal.getBody();$styleswindow.show(),$modalBody.append($styleswindow),$styleswindow.data("modal",modal)})),$styleswindow.find('[data-action="cancelstyles"]').on("click",(function(){$styleswindow.data("modal").hide()})),$styleswindow.find('[data-action="setstyles"]').on("click",(function(){var modal=$styleswindow.data("modal"),newstyles={};$styleswindow.find("[data-style]").each((function(){var $node=(0,_jquery.default)(this),key=$node.data("style"),value=$node.val();""!==value&&(newstyles[key]=value)})),globalstyles[currenttype]=newstyles,$inputtosave.val(JSON.stringify(globalstyles)),applyStyles(),modal.hide()}));["default","active","parent","highlighted","disabled","hover","childs","childindex"].forEach((type=>{(0,_jquery.default)("#onetopic-tabstyles #tabstyleset"+type).on("click",(function(e){e.preventDefault(),showStylesWindow(type)}))})),(0,_jquery.default)("#onetopic-tabstyles #tabstyleclear").on("click",(function(e){e.preventDefault(),globalstyles={},$inputtosave.val(""),applyStyles()})),(0,_jquery.default)("#tabstylesdisplay").on("click",(function(e){e.preventDefault(),$tabstyles.toggleClass("hidden")})),(0,_jquery.default)("#onetopic-styleswindow .onetopic-selecticon").each((function(){var $selecticon=(0,_jquery.default)(this);$selecticon.find("button").on("click",(function(e){e.preventDefault(),$selecticon.find(".listicons").removeClass("hidden")})),$selecticon.find(".listicons span").on("click",(function(e){e.preventDefault();var $icon=(0,_jquery.default)(this);$selecticon.find(".iconselected").html($icon.html()),$selecticon.find('[data-style="tabicon"]').val($icon.data("value")),$selecticon.find(".listicons").addClass("hidden")})),$selecticon.find('[data-style="tabicon"]').on("change",(function(){var $node=(0,_jquery.default)(this);if(""!==$node.val()){var $icon=$selecticon.find('.listicons span[data-value="'+$node.val()+'"]');$icon.length>0&&$selecticon.find(".iconselected").html($icon.html())}else $selecticon.find(".iconselected").html("")}))}))};var showStylesWindow=function(type){if(currenttype=type,$styleswindow.find("[data-style]").each((function(){var $node=(0,_jquery.default)(this);$node.is('input[type="text"]')||$node.is('input[type="hidden"]')?($node.val(""),$node.trigger("change")):$node.is("select")&&$node.find("option").first().prop("selected",!0)})),void 0!==globalstyles[type]){var currentstyles=globalstyles[type];Object.entries(currentstyles).forEach((_ref=>{let[key,value]=_ref;$styleswindow.find('[data-style="'+key+'"]').val(value),$styleswindow.find('[data-control="colorpicker"]').trigger("change"),$styleswindow.find('[data-style="tabicon"]').trigger("change")}))}$styleswindow.data("modal").show()},applyStyles=function(){var withunits=["font-size","line-height","margin","padding","border-width","border-radius"],csscontent="";Object.entries(globalstyles).forEach((_ref2=>{let[type,styles]=_ref2;switch(type){case"active":csscontent+="#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item a.nav-link.active, ",csscontent+="#onetopic-tabstyles .nav-tabs a.nav-link.active, ",csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs a.nav-link.active, ",csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic a.nav-link.active";break;case"parent":csscontent+="#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item.haschilds a.nav-link, ",csscontent+="#onetopic-tabstyles .nav-tabs .nav-item.haschilds a.nav-link";break;case"highlighted":csscontent+="#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item.marker a.nav-link, ",csscontent+="#onetopic-tabstyles .nav-tabs .nav-item.marker a.nav-link, ",csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.marker a.nav-link, ",csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic.marker a.nav-link";break;case"disabled":csscontent+="#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item.disabled a.nav-link, ",csscontent+="#onetopic-tabstyles .nav-tabs .nav-item.disabled a.nav-link, ",csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.disabled a.nav-link, ",csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic.disabled a.nav-link";break;case"hover":csscontent+="#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item a.nav-link:hover, ",csscontent+="#onetopic-tabstyles .nav-tabs .nav-item a.nav-link:hover, ",csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item a.nav-link:hover, ",csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic a.nav-link:hover";break;case"childs":csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic a.nav-link";break;case"childindex":csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic.tab_initial a.nav-link";break;default:csscontent+="#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item a.nav-link, ",csscontent+="#onetopic-tabstyles .nav-tabs a.nav-link"}csscontent+="{";var units=[],stylesarray=Object.entries(styles);stylesarray.forEach((_ref3=>{let[key,value]=_ref3;if(0===key.indexOf("unit-"))key=key.replace("unit-",""),units[key]=value;else if("tabicon"==key&&""!==value){console.log(value);var icon=(0,_jquery.default)('#onetopic-styleswindow .listicons span[data-value="'+value+'"]').html();console.log(icon),(0,_jquery.default)("#onetopic-tabstyles .tabicon-"+type).html(icon).removeClass("hidden")}})),stylesarray.forEach((_ref4=>{let[key,value]=_ref4;0!==key.indexOf("unit-")&&"tabicon"!=key&&(void 0!==units[key]?value+=units[key]:-1!==withunits.indexOf(key)&&(value+="px"),csscontent+="others"==key?value+";":key+":"+value+";")})),csscontent+="}"}));var $stylecontainer=$tabstyles.find("style");$stylecontainer.length>0&&$stylecontainer.remove(),$stylecontainer=(0,_jquery.default)('"),$tabstyles.append($stylecontainer)}}));
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_jquery=_interopRequireDefault(_jquery),_modal_factory=_interopRequireDefault(_modal_factory);var $tabstyles=null,$styleswindow=null,currenttype="default",globalstyles={},$inputtosave=null;_exports.init=()=>{if($tabstyles=(0,_jquery.default)("#onetopic-tabstyles"),$inputtosave=$tabstyles.find("textarea.savecontrol"),$styleswindow=(0,_jquery.default)("#onetopic-styleswindow"),(0,_jquery.default)("#onetopic-tabstyles .tpl-tabdefault .tabicon").each((function(){var $tabicon=(0,_jquery.default)(this);$tabicon.append(''),$tabicon.append('')})),(0,_jquery.default)("#onetopic-tabstyles .tpl-tabactive .tabicon").each((function(){var $tabicon=(0,_jquery.default)(this);$tabicon.append(''),$tabicon.append('')})),(0,_jquery.default)("#onetopic-tabstyles .tpl-tabparent .tabicon").each((function(){var $tabicon=(0,_jquery.default)(this);$tabicon.append(''),$tabicon.append(''),$tabicon.append('')})),(0,_jquery.default)("#onetopic-tabstyles .tpl-tabchildindex .tabicon").each((function(){var $tabicon=(0,_jquery.default)(this);$tabicon.append(''),$tabicon.append(''),$tabicon.append(''),$tabicon.append('')})),(0,_jquery.default)("#onetopic-tabstyles .tpl-tabchild .tabicon").each((function(){var $tabicon=(0,_jquery.default)(this);$tabicon.append(''),$tabicon.append(''),$tabicon.append('')})),(0,_jquery.default)("#onetopic-tabstyles .tpl-tabhighlighted .tabicon").each((function(){var $tabicon=(0,_jquery.default)(this);$tabicon.append(''),$tabicon.append(''),$tabicon.append('')})),(0,_jquery.default)("#onetopic-tabstyles .tpl-tabdisabled .tabicon").each((function(){(0,_jquery.default)(this).append('')})),(0,_jquery.default)("#onetopic-tabstyles .tabicon").each((function(){(0,_jquery.default)(this).removeClass("hidden")})),""!==$inputtosave.val().trim()){try{null===(globalstyles=JSON.parse($inputtosave.val()))&&(globalstyles={})}catch(e){console.error(e),globalstyles={}}applyStyles()}var $colorpicker=$styleswindow.find(".colorpicker"),$setcolor=$colorpicker.find('[data-action="setcolor"]'),$colorpickerinput=$colorpicker.find("input");$styleswindow.find('[data-control="colorpicker"]').on("click",(function(){var $node=(0,_jquery.default)(this);$colorpicker.show(),$colorpickerinput.val($node.val()),$setcolor.data("target",$node)})).on("change",(function(){var $node=(0,_jquery.default)(this),color=$node.val().trim();$node.css("background-color",color)})),$setcolor.on("click",(function(e){e.preventDefault(),$colorpicker.hide(),$setcolor.data("target").val($colorpickerinput.val()).trigger("change")})),$colorpicker.find('[data-action="cancel"]').on("click",(function(){$colorpicker.hide()}));var title=$styleswindow.data("title");_modal_factory.default.create({title:title,body:""}).done((function(modal){var $modalBody=modal.getBody();$styleswindow.show(),$modalBody.append($styleswindow),$styleswindow.data("modal",modal)})),$styleswindow.find('[data-action="cancelstyles"]').on("click",(function(){$styleswindow.data("modal").hide()})),$styleswindow.find('[data-action="setstyles"]').on("click",(function(){var modal=$styleswindow.data("modal"),newstyles={};$styleswindow.find("[data-style]").each((function(){var $node=(0,_jquery.default)(this),key=$node.data("style"),value=$node.val();""!==value&&(newstyles[key]=value)})),globalstyles[currenttype]=newstyles,$inputtosave.val(JSON.stringify(globalstyles)),applyStyles(),modal.hide()}));["default","active","parent","highlighted","disabled","hover","childs","childindex"].forEach((type=>{(0,_jquery.default)("#onetopic-tabstyles #tabstyleset"+type).on("click",(function(e){e.preventDefault(),showStylesWindow(type)}))})),(0,_jquery.default)("#onetopic-tabstyles #tabstyleclear").on("click",(function(e){e.preventDefault(),globalstyles={},$inputtosave.val(""),applyStyles()})),(0,_jquery.default)("#tabstylesdisplay").on("click",(function(e){e.preventDefault(),$tabstyles.toggleClass("hidden")})),(0,_jquery.default)("#onetopic-styleswindow .onetopic-selecticon").each((function(){var $selecticon=(0,_jquery.default)(this);$selecticon.find("button").on("click",(function(e){e.preventDefault(),$selecticon.find(".listicons").removeClass("hidden")})),$selecticon.find(".listicons span").on("click",(function(e){e.preventDefault();var $icon=(0,_jquery.default)(this);$selecticon.find(".iconselected").html($icon.html()),$selecticon.find('[data-style="tabicon"]').val($icon.data("value")),$selecticon.find(".listicons").addClass("hidden")})),$selecticon.find('[data-style="tabicon"]').on("change",(function(){var $node=(0,_jquery.default)(this);if(""!==$node.val()){var $icon=$selecticon.find('.listicons span[data-value="'+$node.val()+'"]');$icon.length>0&&$selecticon.find(".iconselected").html($icon.html())}else $selecticon.find(".iconselected").html("")}))}))};var showStylesWindow=function(type){if(currenttype=type,$styleswindow.find("[data-style]").each((function(){var $node=(0,_jquery.default)(this);$node.is('input[type="text"]')||$node.is('input[type="hidden"]')?($node.val(""),$node.trigger("change")):$node.is("select")&&$node.find("option").first().prop("selected",!0)})),void 0!==globalstyles[type]){var currentstyles=globalstyles[type];Object.entries(currentstyles).forEach((_ref=>{let[key,value]=_ref;$styleswindow.find('[data-style="'+key+'"]').val(value),$styleswindow.find('[data-control="colorpicker"]').trigger("change"),$styleswindow.find('[data-style="tabicon"]').trigger("change")}))}$styleswindow.data("modal").show()},applyStyles=function(){var withunits=["font-size","line-height","margin","padding","border-width","border-radius"],csscontent="";Object.entries(globalstyles).forEach((_ref2=>{let[type,styles]=_ref2;switch(type){case"active":csscontent+="#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item a.nav-link.active, ",csscontent+="#onetopic-tabstyles .nav-tabs a.nav-link.active, ",csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs a.nav-link.active, ",csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic a.nav-link.active";break;case"parent":csscontent+="#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item.haschilds a.nav-link, ",csscontent+="#onetopic-tabstyles .nav-tabs .nav-item.haschilds a.nav-link";break;case"highlighted":csscontent+="#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item.marker a.nav-link, ",csscontent+="#onetopic-tabstyles .nav-tabs .nav-item.marker a.nav-link, ",csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.marker a.nav-link, ",csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic.marker a.nav-link";break;case"disabled":csscontent+="#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item.disabled a.nav-link, ",csscontent+="#onetopic-tabstyles .nav-tabs .nav-item.disabled a.nav-link, ",csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.disabled a.nav-link, ",csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic.disabled a.nav-link";break;case"hover":csscontent+="#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item a.nav-link:hover, ",csscontent+="#onetopic-tabstyles .nav-tabs .nav-item a.nav-link:hover, ",csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item a.nav-link:hover, ",csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic a.nav-link:hover";break;case"childs":csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic a.nav-link";break;case"childindex":csscontent+="#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic.tab_initial a.nav-link";break;default:csscontent+="#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item a.nav-link, ",csscontent+="#onetopic-tabstyles .nav-tabs a.nav-link"}csscontent+="{";var units=[],stylesarray=Object.entries(styles);stylesarray.forEach((_ref3=>{let[key,value]=_ref3;if(0===key.indexOf("unit-"))key=key.replace("unit-",""),units[key]=value;else if("tabicon"==key&&""!==value){var icon=(0,_jquery.default)('#onetopic-styleswindow .listicons span[data-value="'+value+'"]').html();(0,_jquery.default)("#onetopic-tabstyles .tabicon-"+type).html(icon).removeClass("hidden")}})),stylesarray.forEach((_ref4=>{let[key,value]=_ref4;0!==key.indexOf("unit-")&&"tabicon"!=key&&(void 0!==units[key]?value+=units[key]:-1!==withunits.indexOf(key)&&(value+="px"),csscontent+="others"==key?value+";":key+":"+value+";")})),csscontent+="}"}));var $stylecontainer=$tabstyles.find("style");$stylecontainer.length>0&&$stylecontainer.remove(),$stylecontainer=(0,_jquery.default)('"),$tabstyles.append($stylecontainer)}}));
//# sourceMappingURL=tabstyles.min.js.map
\ No newline at end of file
diff --git a/amd/build/tabstyles.min.js.map b/amd/build/tabstyles.min.js.map
index 790756d..230b11b 100644
--- a/amd/build/tabstyles.min.js.map
+++ b/amd/build/tabstyles.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"tabstyles.min.js","sources":["../src/tabstyles.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Tab editor in site settings.\n *\n * @module format_onetopic/tabstyles\n * @copyright 2021 David Herney Bernal - cirano\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport $ from 'jquery';\nimport ModalFactory from 'core/modal_factory';\n\nvar $tabstyles = null;\nvar $styleswindow = null;\nvar currenttype = 'default';\nvar globalstyles = {};\nvar $inputtosave = null;\n\n/**\n * Component initialization.\n *\n * @method init\n */\nexport const init = () => {\n\n $tabstyles = $('#onetopic-tabstyles');\n $inputtosave = $tabstyles.find('textarea.savecontrol');\n $styleswindow = $('#onetopic-styleswindow');\n\n // Define the tab icons.\n $('#onetopic-tabstyles .tpl-tabdefault .tabicon').each(function() {\n var $tabicon = $(this);\n $tabicon.append('');\n $tabicon.append('');\n });\n\n $('#onetopic-tabstyles .tpl-tabactive .tabicon').each(function() {\n var $tabicon = $(this);\n $tabicon.append('');\n $tabicon.append('');\n });\n\n $('#onetopic-tabstyles .tpl-tabparent .tabicon').each(function() {\n var $tabicon = $(this);\n $tabicon.append('');\n $tabicon.append('');\n $tabicon.append('');\n });\n\n $('#onetopic-tabstyles .tpl-tabchildindex .tabicon').each(function() {\n var $tabicon = $(this);\n $tabicon.append('');\n $tabicon.append('');\n $tabicon.append('');\n $tabicon.append('');\n });\n\n $('#onetopic-tabstyles .tpl-tabchild .tabicon').each(function() {\n var $tabicon = $(this);\n $tabicon.append('');\n $tabicon.append('');\n $tabicon.append('');\n });\n\n $('#onetopic-tabstyles .tpl-tabhighlighted .tabicon').each(function() {\n var $tabicon = $(this);\n $tabicon.append('');\n $tabicon.append('');\n $tabicon.append('');\n });\n\n $('#onetopic-tabstyles .tpl-tabdisabled .tabicon').each(function() {\n var $tabicon = $(this);\n $tabicon.append('');\n });\n\n $('#onetopic-tabstyles .tabicon').each(function() {\n $(this).removeClass('hidden');\n });\n // End of Define the tab icons.\n\n if ($inputtosave.val().trim() !== '') {\n\n try {\n globalstyles = JSON.parse($inputtosave.val());\n\n if (globalstyles === null) {\n globalstyles = {};\n }\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(e);\n globalstyles = {};\n }\n\n applyStyles();\n }\n\n var $colorpicker = $styleswindow.find('.colorpicker');\n var $setcolor = $colorpicker.find('[data-action=\"setcolor\"]');\n var $colorpickerinput = $colorpicker.find('input');\n\n // Color picker control.\n $styleswindow.find('[data-control=\"colorpicker\"]').on('click', function() {\n var $node = $(this);\n\n $colorpicker.show();\n $colorpickerinput.val($node.val());\n $setcolor.data('target', $node);\n }).on('change', function() {\n var $node = $(this);\n var color = $node.val().trim();\n\n $node.css('background-color', color);\n });\n\n $setcolor.on('click', function(e) {\n e.preventDefault();\n\n $colorpicker.hide();\n $setcolor.data('target').val($colorpickerinput.val()).trigger('change');\n });\n\n $colorpicker.find('[data-action=\"cancel\"]').on('click', function() {\n $colorpicker.hide();\n });\n\n var title = $styleswindow.data('title');\n\n // Initialize the modal window.\n ModalFactory.create({\n 'title': title,\n 'body': ''\n }).done(function(modal) {\n var $modalBody = modal.getBody();\n $styleswindow.show();\n $modalBody.append($styleswindow);\n $styleswindow.data('modal', modal);\n });\n\n // Save the styles.\n $styleswindow.find('[data-action=\"cancelstyles\"]').on('click', function() {\n $styleswindow.data('modal').hide();\n });\n\n $styleswindow.find('[data-action=\"setstyles\"]').on('click', function() {\n var modal = $styleswindow.data('modal');\n var newstyles = {};\n\n $styleswindow.find('[data-style]').each(function() {\n var $node = $(this);\n var key = $node.data('style');\n var value = $node.val();\n\n if (value !== '') {\n newstyles[key] = value;\n }\n });\n\n globalstyles[currenttype] = newstyles;\n $inputtosave.val(JSON.stringify(globalstyles));\n applyStyles();\n\n modal.hide();\n });\n\n var types = ['default', 'active', 'parent', 'highlighted', 'disabled', 'hover', 'childs', 'childindex'];\n types.forEach(type => {\n $('#onetopic-tabstyles #tabstyleset' + type).on('click', function(e) {\n e.preventDefault();\n showStylesWindow(type);\n });\n });\n\n $('#onetopic-tabstyles #tabstyleclear').on('click', function(e) {\n e.preventDefault();\n globalstyles = {};\n $inputtosave.val('');\n applyStyles();\n });\n\n $('#tabstylesdisplay').on('click', function(e) {\n e.preventDefault();\n $tabstyles.toggleClass('hidden');\n });\n\n $('#onetopic-styleswindow .onetopic-selecticon').each(function() {\n var $selecticon = $(this);\n $selecticon.find('button').on('click', function(e) {\n e.preventDefault();\n $selecticon.find('.listicons').removeClass('hidden');\n });\n\n $selecticon.find('.listicons span').on('click', function(e) {\n e.preventDefault();\n var $icon = $(this);\n $selecticon.find('.iconselected').html($icon.html());\n $selecticon.find('[data-style=\"tabicon\"]').val($icon.data('value'));\n $selecticon.find('.listicons').addClass('hidden');\n });\n\n $selecticon.find('[data-style=\"tabicon\"]').on('change', function() {\n var $node = $(this);\n\n if ($node.val() === '') {\n $selecticon.find('.iconselected').html('');\n return;\n }\n\n var $icon = $selecticon.find('.listicons span[data-value=\"' + $node.val() + '\"]');\n\n if ($icon.length > 0) {\n $selecticon.find('.iconselected').html($icon.html());\n }\n });\n });\n\n};\n\n/**\n * Show the styles window.\n *\n * @param {string} type\n */\nvar showStylesWindow = function(type) {\n\n currenttype = type;\n $styleswindow.find('[data-style]').each(function() {\n var $node = $(this);\n\n if ($node.is('input[type=\"text\"]') || $node.is('input[type=\"hidden\"]')) {\n $node.val('');\n $node.trigger('change');\n } else if ($node.is('select')) {\n $node.find('option').first().prop('selected', true);\n }\n });\n\n if (globalstyles[type] !== undefined) {\n var currentstyles = globalstyles[type];\n\n Object.entries(currentstyles).forEach(([key, value]) => {\n $styleswindow.find('[data-style=\"' + key + '\"]').val(value);\n\n // Apply the color.\n $styleswindow.find('[data-control=\"colorpicker\"]').trigger('change');\n\n // Change the icon.\n $styleswindow.find('[data-style=\"tabicon\"]').trigger('change');\n });\n }\n\n $styleswindow.data('modal').show();\n\n};\n\n/**\n * Apply the styles to the tabs for check current visualization.\n */\nvar applyStyles = function() {\n\n var withunits = ['font-size', 'line-height', 'margin', 'padding', 'border-width', 'border-radius'];\n var csscontent = '';\n\n Object.entries(globalstyles).forEach(([type, styles]) => {\n\n switch (type) {\n case 'active':\n csscontent += '#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item a.nav-link.active, ';\n csscontent += '#onetopic-tabstyles .nav-tabs a.nav-link.active, ';\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs a.nav-link.active, ';\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic a.nav-link.active';\n break;\n case 'parent':\n csscontent += '#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item.haschilds a.nav-link, ';\n csscontent += '#onetopic-tabstyles .nav-tabs .nav-item.haschilds a.nav-link';\n break;\n case 'highlighted':\n csscontent += '#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item.marker a.nav-link, ';\n csscontent += '#onetopic-tabstyles .nav-tabs .nav-item.marker a.nav-link, ';\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.marker a.nav-link, ';\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic.marker a.nav-link';\n break;\n case 'disabled':\n csscontent += '#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item.disabled a.nav-link, ';\n csscontent += '#onetopic-tabstyles .nav-tabs .nav-item.disabled a.nav-link, ';\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.disabled a.nav-link, ';\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic.disabled a.nav-link';\n break;\n case 'hover':\n csscontent += '#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item a.nav-link:hover, ';\n csscontent += '#onetopic-tabstyles .nav-tabs .nav-item a.nav-link:hover, ';\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item a.nav-link:hover, ';\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic a.nav-link:hover';\n break;\n case 'childs':\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic a.nav-link';\n break;\n case 'childindex':\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic.tab_initial a.nav-link';\n break;\n default:\n csscontent += '#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item a.nav-link, ';\n csscontent += '#onetopic-tabstyles .nav-tabs a.nav-link';\n }\n\n csscontent += '{';\n var units = [];\n var stylesarray = Object.entries(styles);\n\n // Check if exist units for some rules.\n stylesarray.forEach(([key, value]) => {\n // Check if the key start with the units prefix.\n if (key.indexOf('unit-') === 0) {\n\n // Remove the prefix.\n key = key.replace('unit-', '');\n units[key] = value;\n } else if (key == 'tabicon') {\n if (value !== '') {\n console.log(value);\n var icon = $('#onetopic-styleswindow .listicons span[data-value=\"' + value + '\"]').html();\n console.log(icon);\n $('#onetopic-tabstyles .tabicon-' + type).html(icon).removeClass('hidden');\n }\n }\n });\n\n stylesarray.forEach(([key, value]) => {\n\n // Exclude the tab icons and units rules.\n if (key.indexOf('unit-') === 0) {\n return;\n } else if (key == 'tabicon') {\n return;\n }\n\n // If exist a unit for the rule, apply it.\n if (units[key] !== undefined) {\n value = value + units[key];\n } else if (withunits.indexOf(key) !== -1) {\n // If the rule need units, apply px by default.\n value = value + 'px';\n }\n\n if (key == 'others') {\n csscontent += value + ';';\n } else {\n csscontent += key + ':' + value + ';';\n }\n });\n csscontent += '}';\n });\n\n var $stylecontainer = $tabstyles.find('style');\n\n if ($stylecontainer.length > 0) {\n $stylecontainer.remove();\n }\n\n $stylecontainer = $('');\n $tabstyles.append($stylecontainer);\n\n};\n"],"names":["$tabstyles","$styleswindow","currenttype","globalstyles","$inputtosave","find","each","$tabicon","this","append","removeClass","val","trim","JSON","parse","e","console","error","applyStyles","$colorpicker","$setcolor","$colorpickerinput","on","$node","show","data","color","css","preventDefault","hide","trigger","title","create","done","modal","$modalBody","getBody","newstyles","key","value","stringify","forEach","type","showStylesWindow","toggleClass","$selecticon","$icon","html","addClass","length","is","first","prop","undefined","currentstyles","Object","entries","_ref","withunits","csscontent","_ref2","styles","units","stylesarray","_ref3","indexOf","replace","log","icon","_ref4","$stylecontainer","remove"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"tabstyles.min.js","sources":["../src/tabstyles.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Tab editor in site settings.\n *\n * @module format_onetopic/tabstyles\n * @copyright 2021 David Herney Bernal - cirano\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport $ from 'jquery';\nimport ModalFactory from 'core/modal_factory';\n\nvar $tabstyles = null;\nvar $styleswindow = null;\nvar currenttype = 'default';\nvar globalstyles = {};\nvar $inputtosave = null;\n\n/**\n * Component initialization.\n *\n * @method init\n */\nexport const init = () => {\n\n $tabstyles = $('#onetopic-tabstyles');\n $inputtosave = $tabstyles.find('textarea.savecontrol');\n $styleswindow = $('#onetopic-styleswindow');\n\n // Define the tab icons.\n $('#onetopic-tabstyles .tpl-tabdefault .tabicon').each(function() {\n var $tabicon = $(this);\n $tabicon.append('');\n $tabicon.append('');\n });\n\n $('#onetopic-tabstyles .tpl-tabactive .tabicon').each(function() {\n var $tabicon = $(this);\n $tabicon.append('');\n $tabicon.append('');\n });\n\n $('#onetopic-tabstyles .tpl-tabparent .tabicon').each(function() {\n var $tabicon = $(this);\n $tabicon.append('');\n $tabicon.append('');\n $tabicon.append('');\n });\n\n $('#onetopic-tabstyles .tpl-tabchildindex .tabicon').each(function() {\n var $tabicon = $(this);\n $tabicon.append('');\n $tabicon.append('');\n $tabicon.append('');\n $tabicon.append('');\n });\n\n $('#onetopic-tabstyles .tpl-tabchild .tabicon').each(function() {\n var $tabicon = $(this);\n $tabicon.append('');\n $tabicon.append('');\n $tabicon.append('');\n });\n\n $('#onetopic-tabstyles .tpl-tabhighlighted .tabicon').each(function() {\n var $tabicon = $(this);\n $tabicon.append('');\n $tabicon.append('');\n $tabicon.append('');\n });\n\n $('#onetopic-tabstyles .tpl-tabdisabled .tabicon').each(function() {\n var $tabicon = $(this);\n $tabicon.append('');\n });\n\n $('#onetopic-tabstyles .tabicon').each(function() {\n $(this).removeClass('hidden');\n });\n // End of Define the tab icons.\n\n if ($inputtosave.val().trim() !== '') {\n\n try {\n globalstyles = JSON.parse($inputtosave.val());\n\n if (globalstyles === null) {\n globalstyles = {};\n }\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(e);\n globalstyles = {};\n }\n\n applyStyles();\n }\n\n var $colorpicker = $styleswindow.find('.colorpicker');\n var $setcolor = $colorpicker.find('[data-action=\"setcolor\"]');\n var $colorpickerinput = $colorpicker.find('input');\n\n // Color picker control.\n $styleswindow.find('[data-control=\"colorpicker\"]').on('click', function() {\n var $node = $(this);\n\n $colorpicker.show();\n $colorpickerinput.val($node.val());\n $setcolor.data('target', $node);\n }).on('change', function() {\n var $node = $(this);\n var color = $node.val().trim();\n\n $node.css('background-color', color);\n });\n\n $setcolor.on('click', function(e) {\n e.preventDefault();\n\n $colorpicker.hide();\n $setcolor.data('target').val($colorpickerinput.val()).trigger('change');\n });\n\n $colorpicker.find('[data-action=\"cancel\"]').on('click', function() {\n $colorpicker.hide();\n });\n\n var title = $styleswindow.data('title');\n\n // Initialize the modal window.\n ModalFactory.create({\n 'title': title,\n 'body': ''\n }).done(function(modal) {\n var $modalBody = modal.getBody();\n $styleswindow.show();\n $modalBody.append($styleswindow);\n $styleswindow.data('modal', modal);\n });\n\n // Save the styles.\n $styleswindow.find('[data-action=\"cancelstyles\"]').on('click', function() {\n $styleswindow.data('modal').hide();\n });\n\n $styleswindow.find('[data-action=\"setstyles\"]').on('click', function() {\n var modal = $styleswindow.data('modal');\n var newstyles = {};\n\n $styleswindow.find('[data-style]').each(function() {\n var $node = $(this);\n var key = $node.data('style');\n var value = $node.val();\n\n if (value !== '') {\n newstyles[key] = value;\n }\n });\n\n globalstyles[currenttype] = newstyles;\n $inputtosave.val(JSON.stringify(globalstyles));\n applyStyles();\n\n modal.hide();\n });\n\n var types = ['default', 'active', 'parent', 'highlighted', 'disabled', 'hover', 'childs', 'childindex'];\n types.forEach(type => {\n $('#onetopic-tabstyles #tabstyleset' + type).on('click', function(e) {\n e.preventDefault();\n showStylesWindow(type);\n });\n });\n\n $('#onetopic-tabstyles #tabstyleclear').on('click', function(e) {\n e.preventDefault();\n globalstyles = {};\n $inputtosave.val('');\n applyStyles();\n });\n\n $('#tabstylesdisplay').on('click', function(e) {\n e.preventDefault();\n $tabstyles.toggleClass('hidden');\n });\n\n $('#onetopic-styleswindow .onetopic-selecticon').each(function() {\n var $selecticon = $(this);\n $selecticon.find('button').on('click', function(e) {\n e.preventDefault();\n $selecticon.find('.listicons').removeClass('hidden');\n });\n\n $selecticon.find('.listicons span').on('click', function(e) {\n e.preventDefault();\n var $icon = $(this);\n $selecticon.find('.iconselected').html($icon.html());\n $selecticon.find('[data-style=\"tabicon\"]').val($icon.data('value'));\n $selecticon.find('.listicons').addClass('hidden');\n });\n\n $selecticon.find('[data-style=\"tabicon\"]').on('change', function() {\n var $node = $(this);\n\n if ($node.val() === '') {\n $selecticon.find('.iconselected').html('');\n return;\n }\n\n var $icon = $selecticon.find('.listicons span[data-value=\"' + $node.val() + '\"]');\n\n if ($icon.length > 0) {\n $selecticon.find('.iconselected').html($icon.html());\n }\n });\n });\n\n};\n\n/**\n * Show the styles window.\n *\n * @param {string} type\n */\nvar showStylesWindow = function(type) {\n\n currenttype = type;\n $styleswindow.find('[data-style]').each(function() {\n var $node = $(this);\n\n if ($node.is('input[type=\"text\"]') || $node.is('input[type=\"hidden\"]')) {\n $node.val('');\n $node.trigger('change');\n } else if ($node.is('select')) {\n $node.find('option').first().prop('selected', true);\n }\n });\n\n if (globalstyles[type] !== undefined) {\n var currentstyles = globalstyles[type];\n\n Object.entries(currentstyles).forEach(([key, value]) => {\n $styleswindow.find('[data-style=\"' + key + '\"]').val(value);\n\n // Apply the color.\n $styleswindow.find('[data-control=\"colorpicker\"]').trigger('change');\n\n // Change the icon.\n $styleswindow.find('[data-style=\"tabicon\"]').trigger('change');\n });\n }\n\n $styleswindow.data('modal').show();\n\n};\n\n/**\n * Apply the styles to the tabs for check current visualization.\n */\nvar applyStyles = function() {\n\n var withunits = ['font-size', 'line-height', 'margin', 'padding', 'border-width', 'border-radius'];\n var csscontent = '';\n\n Object.entries(globalstyles).forEach(([type, styles]) => {\n\n switch (type) {\n case 'active':\n csscontent += '#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item a.nav-link.active, ';\n csscontent += '#onetopic-tabstyles .nav-tabs a.nav-link.active, ';\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs a.nav-link.active, ';\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic a.nav-link.active';\n break;\n case 'parent':\n csscontent += '#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item.haschilds a.nav-link, ';\n csscontent += '#onetopic-tabstyles .nav-tabs .nav-item.haschilds a.nav-link';\n break;\n case 'highlighted':\n csscontent += '#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item.marker a.nav-link, ';\n csscontent += '#onetopic-tabstyles .nav-tabs .nav-item.marker a.nav-link, ';\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.marker a.nav-link, ';\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic.marker a.nav-link';\n break;\n case 'disabled':\n csscontent += '#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item.disabled a.nav-link, ';\n csscontent += '#onetopic-tabstyles .nav-tabs .nav-item.disabled a.nav-link, ';\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.disabled a.nav-link, ';\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic.disabled a.nav-link';\n break;\n case 'hover':\n csscontent += '#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item a.nav-link:hover, ';\n csscontent += '#onetopic-tabstyles .nav-tabs .nav-item a.nav-link:hover, ';\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item a.nav-link:hover, ';\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic a.nav-link:hover';\n break;\n case 'childs':\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic a.nav-link';\n break;\n case 'childindex':\n csscontent += '#onetopic-tabstyles .onetopic-tab-body .nav-tabs .nav-item.subtopic.tab_initial a.nav-link';\n break;\n default:\n csscontent += '#onetopic-tabstyles .verticaltabs .format_onetopic-tabs .nav-item a.nav-link, ';\n csscontent += '#onetopic-tabstyles .nav-tabs a.nav-link';\n }\n\n csscontent += '{';\n var units = [];\n var stylesarray = Object.entries(styles);\n\n // Check if exist units for some rules.\n stylesarray.forEach(([key, value]) => {\n // Check if the key start with the units prefix.\n if (key.indexOf('unit-') === 0) {\n\n // Remove the prefix.\n key = key.replace('unit-', '');\n units[key] = value;\n } else if (key == 'tabicon') {\n if (value !== '') {\n var icon = $('#onetopic-styleswindow .listicons span[data-value=\"' + value + '\"]').html();\n $('#onetopic-tabstyles .tabicon-' + type).html(icon).removeClass('hidden');\n }\n }\n });\n\n stylesarray.forEach(([key, value]) => {\n\n // Exclude the tab icons and units rules.\n if (key.indexOf('unit-') === 0) {\n return;\n } else if (key == 'tabicon') {\n return;\n }\n\n // If exist a unit for the rule, apply it.\n if (units[key] !== undefined) {\n value = value + units[key];\n } else if (withunits.indexOf(key) !== -1) {\n // If the rule need units, apply px by default.\n value = value + 'px';\n }\n\n if (key == 'others') {\n csscontent += value + ';';\n } else {\n csscontent += key + ':' + value + ';';\n }\n });\n csscontent += '}';\n });\n\n var $stylecontainer = $tabstyles.find('style');\n\n if ($stylecontainer.length > 0) {\n $stylecontainer.remove();\n }\n\n $stylecontainer = $('');\n $tabstyles.append($stylecontainer);\n\n};\n"],"names":["$tabstyles","$styleswindow","currenttype","globalstyles","$inputtosave","find","each","$tabicon","this","append","removeClass","val","trim","JSON","parse","e","console","error","applyStyles","$colorpicker","$setcolor","$colorpickerinput","on","$node","show","data","color","css","preventDefault","hide","trigger","title","create","done","modal","$modalBody","getBody","newstyles","key","value","stringify","forEach","type","showStylesWindow","toggleClass","$selecticon","$icon","html","addClass","length","is","first","prop","undefined","currentstyles","Object","entries","_ref","withunits","csscontent","_ref2","styles","units","stylesarray","_ref3","indexOf","replace","icon","_ref4","$stylecontainer","remove"],"mappings":"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"}
\ No newline at end of file
diff --git a/amd/src/onetopicbackground.js b/amd/src/onetopicbackground.js
new file mode 100644
index 0000000..3efa302
--- /dev/null
+++ b/amd/src/onetopicbackground.js
@@ -0,0 +1,115 @@
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see .
+
+/**
+ * Onetopic background selector.
+ *
+ * @module format_onetopic/onetopicbackground
+ * @copyright 2021 David Herney Bernal - cirano
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+import $ from 'jquery';
+import ModalFactory from 'core/modal_factory';
+import ModalSaveCancel from 'core/modal_save_cancel';
+import ModalEvents from 'core/modal_events';
+
+/**
+ * Component initialization.
+ *
+ * @method init
+ * @param {String} controlid The control id.
+ */
+export const init = (controlid) => {
+
+ var $controlinput = $('#' + controlid);
+ var $control = $controlinput.parent('.backgroundpicker');
+ var $controlwindow = $control.find('.backgroundpickerwindow');
+ var $controlbutton = $control.find('.backgroundpickerselector');
+ var $colorpickerinput = $controlwindow.find('input.form-control[type="text"]');
+
+ // Initialize the modal window.
+ var title = $controlwindow.attr('title');
+ var buttons = [];
+ buttons['save'] = $controlwindow.data('savelabel');
+
+ var setEvents = function(modal) {
+ modal.getRoot().on(ModalEvents.cancel, () => {
+ modal.hide();
+ });
+
+ modal.getRoot().on(ModalEvents.save, () => {
+ var newcolor = $colorpickerinput.val();
+ var val = $controlinput.val();
+ var color = readColor(val);
+ if (color) {
+ val = val.replace(color, newcolor);
+ } else if (val.trim() === '') {
+ val = newcolor;
+ } else {
+ val += ' ' + newcolor;
+ }
+ $controlinput.val(val);
+ modal.hide();
+ });
+ };
+
+ ModalFactory.create({
+ 'title': title,
+ 'body': $controlwindow,
+ 'type': ModalSaveCancel.TYPE,
+ 'large': true,
+ 'buttons': buttons
+ })
+ .done(function(modal) {
+ var $modalBody = modal.getBody();
+ $modalBody.append($controlwindow);
+ $control.data('modal', modal);
+ setEvents(modal);
+ });
+
+ // Color picker control.
+ $controlbutton.on('click', function(e) {
+ e.preventDefault();
+ $controlwindow.removeClass('hidden');
+ var currentval = $controlinput.val();
+
+ var color = readColor(currentval);
+
+ $colorpickerinput.val(color);
+ $control.data('modal').show();
+ });
+
+};
+
+/**
+ * Extracts the first color from a text string. Recognizes hexadecimal, rgba and hsla.
+ *
+ * @param {string} text
+ * @returns
+ */
+var readColor = function(text) {
+ var regexcolor = new RegExp(
+ /#[0-9a-fA-F]{6}/.source
+ + /|#[0-9a-fA-F]{3}/.source
+ + /|rgba?\(\s*([0-9]{1,3}\s*,\s*){2}[0-9]{1,3}\s*(,\s*[0-9.]+\s*)?\)/.source
+ + /|hsla?\(\s*([0-9]{1,3}\s*,\s*){2}[0-9]{1,3}\s*(,\s*[0-9.]+\s*)?\)/.source);
+
+ var color = text.match(regexcolor);
+ if (color) {
+ color = color[0];
+ }
+
+ return color;
+};
diff --git a/amd/src/tabstyles.js b/amd/src/tabstyles.js
index 200824a..52205f2 100644
--- a/amd/src/tabstyles.js
+++ b/amd/src/tabstyles.js
@@ -331,9 +331,7 @@ var applyStyles = function() {
units[key] = value;
} else if (key == 'tabicon') {
if (value !== '') {
- console.log(value);
var icon = $('#onetopic-styleswindow .listicons span[data-value="' + value + '"]').html();
- console.log(icon);
$('#onetopic-tabstyles .tabicon-' + type).html(icon).removeClass('hidden');
}
}
diff --git a/classes/header.php b/classes/header.php
index 0a45788..0a7cb98 100644
--- a/classes/header.php
+++ b/classes/header.php
@@ -61,20 +61,20 @@ public function export_for_template(\renderer_base $output) {
global $PAGE, $CFG, $OUTPUT;
$format = $this->format;
- $course = $this->format->get_course();
+ $course = $format->get_course();
// Onetopic format is always multipage.
$course->realcoursedisplay = property_exists($course, 'coursedisplay') ? $course->coursedisplay : false;
$firstsection = ($course->realcoursedisplay == COURSE_DISPLAY_MULTIPAGE) ? 1 : 0;
- $currentsection = $this->format->get_sectionnum();
+ $currentsection = $format->get_sectionnum();
$tabslist = [];
$secondtabslist = null;
$tabscssstyles = '';
if ($course->tabsview != \format_onetopic::TABSVIEW_COURSEINDEX &&
($format->show_editor() || !$course->hidetabsbar)) {
- $tabs = $this->get_tabs($this->format->get_modinfo(), $output);
+ $tabs = $this->get_tabs($format->get_modinfo(), $output);
$tabslist = $tabs->get_list();
$secondtabslist = $tabs->get_secondlist($firstsection ? $currentsection - 1 : $currentsection);
$tabscssstyles = $tabs->get_allcssstyles();
@@ -112,11 +112,19 @@ public function export_for_template(\renderer_base $output) {
$hassecondrow = is_object($secondtabslist) && count($secondtabslist->tabs) > 0;
}
+ $formatoptions = course_get_format($course)->get_format_options($currentsection);
+ $tabsectionbackground = $formatoptions['tabsectionbackground'] ?? '';
+
+ if (!empty($tabsectionbackground)) {
+ $tabsectionbackground = clean_param($tabsectionbackground, PARAM_NOTAGS);
+ $tabsectionbackground = 'background: ' . $tabsectionbackground . ';';
+ }
+
$data = (object)[
'uniqid' => $format->uniqid,
'baseurl' => $CFG->wwwroot,
- 'title' => $this->format->page_title(), // This method should be in the course_format class.
- 'format' => $this->format->get_format(),
+ 'title' => $format->page_title(), // This method should be in the course_format class.
+ 'format' => $format->get_format(),
'templatetopic' => $course->templatetopic,
'withicons' => $course->templatetopic_icons,
'hastopictabs' => $hastopictabs,
@@ -131,6 +139,7 @@ public function export_for_template(\renderer_base $output) {
'sectionclasses' => '',
'courseindex' => $courseindex,
'cssstyles' => $tabscssstyles,
+ 'tabsectionbackground' => $tabsectionbackground,
];
$initialsection = null;
@@ -139,10 +148,10 @@ public function export_for_template(\renderer_base $output) {
if ($course->realcoursedisplay == COURSE_DISPLAY_MULTIPAGE) {
// Load the section 0 and export data for template.
- $modinfo = $this->format->get_modinfo();
+ $modinfo = $format->get_modinfo();
$section0 = $modinfo->get_section_info(0);
- $sectionclass = $this->format->get_output_classname('content\\section');
- $section = new $sectionclass($this->format, $section0);
+ $sectionclass = $format->get_output_classname('content\\section');
+ $section = new $sectionclass($format, $section0);
$sectionoutput = new \format_onetopic\output\renderer($PAGE, null);
$initialsection = $section->export_for_template($sectionoutput);
diff --git a/classes/local/formelement_background.php b/classes/local/formelement_background.php
new file mode 100644
index 0000000..7d0dc1a
--- /dev/null
+++ b/classes/local/formelement_background.php
@@ -0,0 +1,147 @@
+.
+
+/**
+ * Form element to select a background.
+ *
+ * @package format_onetopic
+ * @copyright 2024 David Herney - https://bambuco.co
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->libdir . '/form/text.php');
+require_once($CFG->libdir . '/adminlib.php');
+
+/**
+ * Display a tab styles form field.
+ *
+ * @package format_onetopic
+ * @copyright 2024 David Herney - https://bambuco.co
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class format_onetopic_background_form_element extends MoodleQuickForm_text {
+ use templatable_form_element {
+ export_for_template as export_for_template_base;
+ }
+
+ /**
+ * Constructor
+ *
+ * @param string $name Element name
+ * @param mixed $label Label(s) for an element
+ * @param mixed $attributes Either a typical HTML attribute string or an associative array.
+ */
+ public function __construct($name = null, $label = null, $attributes = null) {
+
+ parent::__construct($name, $label, $attributes);
+
+ // The type is used to determine the template to use.
+ // I did not find any conflict when handling a type different from the parent class but further review is needed.
+ $this->_type = 'static';
+ }
+
+ /**
+ * Returns HTML for this form element.
+ *
+ * The uppercase in the function name needs to be ignored because it is required in the core.
+ *
+ * @return string
+ */
+ // @codingStandardsIgnoreLine moodle.NamingConventions.ValidFunctionName.LowercaseMethod
+ public function toHtml() {
+ return $this->to_html();
+ }
+
+ /**
+ * Returns HTML for this form element.
+ *
+ * @return string
+ */
+ public function to_html() {
+ global $PAGE;
+
+ static $loadedcounter = 0;
+ $loadedcounter++;
+
+ $colorpickerid = 'colorpicker' . $loadedcounter;
+ $cp = new \admin_setting_configcolourpicker($colorpickerid,
+ get_string('colorpicker', 'format_onetopic'),
+ get_string('colorpicker_help', 'format_onetopic'),
+ '',
+ );
+
+ $html = parent::toHtml();
+
+ $attrs = ['class' => 'backgroundpickerselector btn btn-secondary'];
+ $html .= html_writer::tag('a', get_string('selectcolor', 'format_onetopic'), $attrs);
+
+ $attrs = [
+ 'class' => 'backgroundpickerwindow hidden',
+ 'title' => get_string('colorpicker', 'format_onetopic'),
+ 'data-savelabel' => get_string('setcolor', 'format_onetopic'),
+ ];
+ $html .= html_writer::tag('div', $cp->output_html(''), $attrs);
+
+ $attrs = ['class' => 'backgroundpicker'];
+ $html = html_writer::tag('div', $html, $attrs);
+
+ $PAGE->requires->js_call_amd('format_onetopic/onetopicbackground', 'init', [$this->getAttribute('id')]);
+
+ return $html;
+
+ }
+
+ /**
+ * Export this element for template renderer.
+ *
+ * @param renderer_base $output
+ * @return array
+ */
+ public function export_for_template(renderer_base $output) {
+ $context = $this->export_for_template_base($output);
+
+ $context['html'] = $this->to_html();
+ return $context;
+ }
+
+ /**
+ * Check that all files have the allowed type.
+ *
+ * The uppercase in the function name needs to be ignored because it is required in the core.
+ *
+ * @param int $value Draft item id with the uploaded files.
+ * @return string|null Validation error message or null.
+ */
+ // @codingStandardsIgnoreLine moodle.NamingConventions.ValidFunctionName.LowercaseMethod
+ public function validateSubmitValue($value) {
+
+ if (empty($value)) {
+ return;
+ }
+
+ $cleaned = clean_param($value, PARAM_NOTAGS);
+
+ if ($cleaned !== $value) {
+ return get_string('backgroundpickerinvalid', 'format_onetopic');
+ }
+
+ return;
+ }
+
+}
diff --git a/lang/en/format_onetopic.php b/lang/en/format_onetopic.php
index 756bd41..d4d4245 100644
--- a/lang/en/format_onetopic.php
+++ b/lang/en/format_onetopic.php
@@ -113,15 +113,21 @@
$string['sectionsnavigation_sitelevel'] = 'Use the default site value';
$string['sectionsnavigation_slides'] = 'Like slides';
$string['sectionsnavigation_support'] = 'Only if theme not support the "uses course index" feature';
+$string['selectcolor'] = 'Select color';
$string['settingsheaderdefault'] = 'Default course settings';
$string['settingsheaderstyles'] = 'Default tabs styles';
$string['showfromothers'] = 'Show topic';
$string['subtopictoright'] = 'Move to right as subtopic';
+$string['tabicon'] = 'Icon';
+$string['tabiconselect'] = 'Select icon';
$string['tablabelactive'] = 'Active tab';
$string['tablabeldefault'] = 'Default tab {$a}';
$string['tablabeldisabled'] = 'Disabled';
$string['tablabelhighlighted'] = 'Highlighted';
$string['tablabelparent'] = 'Parent tab';
+$string['tabsectionbackground'] = 'Section content background';
+$string['tabsectionbackground_help'] = 'Used to change the background of the section content. The value can be a color in a CSS valid representation, for example:
- Hexadecimal: #ffffff
- RGB: rgb(0,255,0)
- Name: green
+It can also be a URL attribute and other CSS background options.';
$string['tabstylebuttons_help'] = 'Click on each button to configure the appearance of the tab in each of its possible states.';
$string['tabstyleclear'] = 'Clear styles';
$string['tabstyles'] = 'Tab styles';
@@ -162,11 +168,8 @@
$string['usessectionsnavigation'] = 'Uses sections navigation';
$string['usessectionsnavigation_help'] = 'Show buttons for navigate to next or previous section.';
-$string['tabicon'] = 'Icon';
-$string['tabiconselect'] = 'Select icon';
-$string['tabsectionbackground'] = 'Section content background';
-$string['tabsectionbackground_help'] = 'Used to change the background of the section content. The value can be a color in a CSS valid representation, for example: - Hexadecimal: #ffffff
- RGB: rgb(0,255,0)
- Name: green
-It can also be a URL attribute and other CSS background options.';
+$string['setcolor'] = 'Set color';
+$string['backgroundpickerinvalid'] = 'Invalid background value';
// Deprecated since Moodle 4.0.
$string['disable'] = 'Disable';
diff --git a/lib.php b/lib.php
index 3aef54e..91dc7b7 100644
--- a/lib.php
+++ b/lib.php
@@ -726,14 +726,26 @@ public function create_edit_form_elements(&$mform, $forsection = false) {
if ($forsection) {
$onetopicconfig = get_config('format_onetopic');
- if ($onetopicconfig->enablecustomstyles && empty($onetopicconfig->useoldstylescontrol)) {
- $mform->removeElement('tabstyles');
- MoodleQuickForm::registerElementType('tabstyles',
- $CFG->dirroot . '/course/format/onetopic/classes/local/formelement_tabstyles.php',
- 'format_onetopic_tabstyles_form_element');
- $element = $mform->addElement('tabstyles', 'tabstyles', get_string('tabstyles', 'format_onetopic'));
+ if ($onetopicconfig->enablecustomstyles) {
+
+ $mform->removeElement('tabsectionbackground');
+ MoodleQuickForm::registerElementType('tabsectionbackground',
+ $CFG->dirroot . '/course/format/onetopic/classes/local/formelement_background.php',
+ 'format_onetopic_background_form_element');
+ $element = $mform->addElement('tabsectionbackground', 'tabsectionbackground',
+ get_string('tabsectionbackground', 'format_onetopic'));
$elements[] = $element;
+
+ if (empty($onetopicconfig->useoldstylescontrol)) {
+ $mform->removeElement('tabstyles');
+ MoodleQuickForm::registerElementType('tabstyles',
+ $CFG->dirroot . '/course/format/onetopic/classes/local/formelement_tabstyles.php',
+ 'format_onetopic_tabstyles_form_element');
+ $element = $mform->addElement('tabstyles', 'tabstyles', get_string('tabstyles', 'format_onetopic'));
+
+ $elements[] = $element;
+ }
}
}
@@ -827,6 +839,11 @@ public function section_format_options($foreditform = false) {
];
if ($onetopicconfig->enablecustomstyles) {
+ $sectionformatoptions['tabsectionbackground'] = [
+ 'default' => '',
+ 'type' => PARAM_RAW,
+ ];
+
if ($onetopicconfig->useoldstylescontrol) {
$sectionformatoptions['fontcolor'] = [
'default' => '',
@@ -877,6 +894,16 @@ public function section_format_options($foreditform = false) {
];
if ($onetopicconfig->enablecustomstyles) {
+
+ $sectionformatoptionsedit['tabsectionbackground'] = [
+ 'default' => '',
+ 'type' => PARAM_RAW,
+ 'label' => new lang_string('tabsectionbackground', 'format_onetopic'),
+ 'element_type' => 'text',
+ 'help' => 'tabsectionbackground',
+ 'help_component' => 'format_onetopic',
+ ];
+
if ($onetopicconfig->useoldstylescontrol) {
$sectionformatoptionsedit['fontcolor'] = [
'default' => '',
diff --git a/styles.css b/styles.css
index 540ad85..d4c015d 100644
--- a/styles.css
+++ b/styles.css
@@ -35,6 +35,11 @@
margin: 0;
}
+.format-onetopic .onetopic-tab-body {
+ padding-top: 10px;
+ padding-bottom: 10px;
+}
+
/* Its a subtabs bar */
.format-onetopic .onetopic-tab-body .format_onetopic-tabs {
padding-left: 20px;
diff --git a/templates/courseformat/tabtree.mustache b/templates/courseformat/tabtree.mustache
index a207a9e..bd6aff0 100644
--- a/templates/courseformat/tabtree.mustache
+++ b/templates/courseformat/tabtree.mustache
@@ -38,7 +38,7 @@
{{#str}} hiddentabsbar, format_onetopic {{/str}}
{{/hidetabsbar}}
-