From e7dbea2da15c5dbae07cdc728a9c9614f1510377 Mon Sep 17 00:00:00 2001 From: ExtremeFiretop Date: Tue, 3 Mar 2026 11:19:07 -0500 Subject: [PATCH 1/6] Allow Disabling of Dropdown Submenus Initial commit to support disabling of Dropdown Sub-Menus from scMerlin --- README.md | 2 +- scmerlin.sh | 125 +++++++++++++++++++++++++++++++++++++---------- scmerlin_www.asp | 21 +++++++- scmerlin_www.js | 34 +++++++++++++ 4 files changed, 155 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 3e4777d..51a4740 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # scMerlin ## v2.5.48 -### Updated on 2026-Feb-18 +### Updated on 2026-Mar-03 ## About scMerlin allows you to easily control the most common services/scripts on your router. scMerlin also augments your router's WebUI with a Sitemap and dynamic submenus for the main left menu of Asuswrt-Merlin. diff --git a/scmerlin.sh b/scmerlin.sh index f845eac..87ea840 100644 --- a/scmerlin.sh +++ b/scmerlin.sh @@ -12,7 +12,7 @@ ## Forked from: https://github.com/jackyaz/scMerlin ## ## ## ###################################################### -# Last Modified: 2026-Feb-18 +# Last Modified: 2026-Mar-03 #----------------------------------------------------- ########## Shellcheck directives ########### @@ -46,6 +46,7 @@ readonly SHARED_WEB_DIR="$SCRIPT_WEBPAGE_DIR/shared-jy" readonly TEMP_MENU_TREE="/tmp/menuTree.js" readonly NTP_WATCHDOG_FILE="$SCRIPT_DIR/.watchdogenabled" readonly TAIL_TAINTED_FILE="$SCRIPT_DIR/.tailtaintdnsenabled" +readonly WEBUI_DROPDOWN_FILE="$SCRIPT_DIR/.webui_dropdown_submenus" ##----------------------------------------## ## Modified by Martinski W. [2024-Jun-07] ## @@ -1109,6 +1110,72 @@ function GenerateSiteMap(showurls) EOF } +##---------------------------------------## +## Added by ExtremeFiretop [2026-Mar-03] ## +##---------------------------------------## +WebUI_DropdownSubMenus() +{ + + case "$1" in + enable) + touch "$WEBUI_DROPDOWN_FILE" + WebUI_DropdownSubMenus apply >/dev/null 2>&1 + ;; + disable) + rm -f "$WEBUI_DROPDOWN_FILE" + WebUI_DropdownSubMenus apply >/dev/null 2>&1 + ;; + apply) + # Ensure we have a working copy to edit + if [ ! -f /tmp/index_style.css ]; then + cp -fp /www/index_style.css /tmp/ 2>/dev/null + fi + + # Remove any prior dropdown CSS rules (yours or legacy) + if [ -f /tmp/index_style.css ]; then + sed -i '/dropdown-content/d' /tmp/index_style.css + fi + + # Base dropdown CSS (always present) + { + echo ".dropdown-content {top: 0px; left: 185px; "\ +"visibility: hidden; position: absolute; "\ +"background-color: #3a4042; min-width: 165px; "\ +"box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); "\ +"z-index: 1000;}" + echo ".dropdown-content a {padding: 6px 8px; "\ +"text-decoration: none; display: block; height: 100%; "\ +"min-height: 20px; max-height: 40px; font-weight: bold; "\ +"text-shadow: 1px 1px 0px black; "\ +"font-family: Verdana, MS UI Gothic, MS P Gothic, "\ +"Microsoft Yahei UI, sans-serif; font-size: 12px; "\ +"border: 1px solid #6B7071;}" + echo ".dropdown-content a:hover {background-color: #77a5c6;}" + } >> /tmp/index_style.css + + # Enabled: show on hover + if [ -f "$WEBUI_DROPDOWN_FILE" ]; then + echo ".dropdown:hover .dropdown-content "\ +"{visibility: visible;}" >> /tmp/index_style.css + else + # Disabled: prevent click-toggle from making it appear + echo ".dropdown-content {display: none;}" >> /tmp/index_style.css + fi + + # Bind-mount updated CSS into WebUI + umount /www/index_style.css 2>/dev/null + mount -o bind /tmp/index_style.css /www/index_style.css + ;; + status) + if [ -f "$WEBUI_DROPDOWN_FILE" ]; then + echo "ENABLED" + else + echo "DISABLED" + fi + ;; + esac +} + ##----------------------------------------## ## Modified by Martinski W. [2025-May-17] ## ##----------------------------------------## @@ -1445,6 +1512,7 @@ Create_Symlinks() ln -s "$NTP_WATCHDOG_FILE" "$SCRIPT_WEB_DIR/watchdogenabled.htm" 2>/dev/null ln -s "$NTP_READY_CHECK_CONF" "$SCRIPT_WEB_DIR/${NTP_READY_CHECK_FILE}.htm" 2>/dev/null ln -s "$TAIL_TAINTED_FILE" "$SCRIPT_WEB_DIR/tailtaintdnsenabled.htm" 2>/dev/null + ln -s "$WEBUI_DROPDOWN_FILE" "$SCRIPT_WEB_DIR/webuidropdownenabled.htm" 2>/dev/null if [ ! -d "$SHARED_WEB_DIR" ]; then ln -s "$SHARED_DIR" "$SHARED_WEB_DIR" 2>/dev/null @@ -1699,30 +1767,13 @@ Mount_WebUI() cp -fp /www/index_style.css /tmp/ fi - if ! grep -q '.menu_Addons' /tmp/index_style.css ; then - echo ".menu_Addons { background: url(ext/shared-jy/addons.png); background-size: contain; }" >> /tmp/index_style.css - fi - - if grep -q '.menu_Addons' /tmp/index_style.css && ! grep -q 'url(ext/shared-jy/addons.png); background-size: contain;' /tmp/index_style.css; then - sed -i 's/addons.png);/addons.png); background-size: contain;/' /tmp/index_style.css - fi - - if grep -q '.dropdown-content {display: block;}' /tmp/index_style.css ; then - sed -i '/dropdown-content/d' /tmp/index_style.css - fi - - if ! grep -q '.dropdown-content {visibility: visible;}' /tmp/index_style.css - then - { - echo ".dropdown-content {top: 0px; left: 185px; visibility: hidden; position: absolute; background-color: #3a4042; min-width: 165px; box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); z-index: 1000;}" - echo ".dropdown-content a {padding: 6px 8px; text-decoration: none; display: block; height: 100%; min-height: 20px; max-height: 40px; font-weight: bold; text-shadow: 1px 1px 0px black; font-family: Verdana, MS UI Gothic, MS P Gothic, Microsoft Yahei UI, sans-serif; font-size: 12px; border: 1px solid #6B7071;}" - echo ".dropdown-content a:hover {background-color: #77a5c6;}" - echo ".dropdown:hover .dropdown-content {visibility: visible;}" - } >> /tmp/index_style.css - fi - - umount /www/index_style.css 2>/dev/null - mount -o bind /tmp/index_style.css /www/index_style.css + # Apply (enable/disable) WebUI dropdown sub-menus based on saved setting + # NOTE: This function handles: + # - Removing any prior dropdown CSS rules + # - Adding base dropdown CSS + # - Adding hover-to-show rule only when enabled + # - Bind-mounting /tmp/index_style.css to /www/index_style.css + WebUI_DropdownSubMenus apply if [ ! -f "$TEMP_MENU_TREE" ]; then cp -fp /www/require/modules/menuTree.js "$TEMP_MENU_TREE" @@ -3374,6 +3425,15 @@ _Menu_ToggleOptions_() printf " ${GRNct}dns${CLRct}. Toggle dnsmasq tainted watchdog script\n" printf " Currently: ${TAILTAINT_DNS_STATUS}\n\n" + if [ "$(WebUI_DropdownSubMenus status)" = "ENABLED" ] + then + WEBUI_DROPDOWN_STATUS="${GRNct}ENABLED${CLRct}" + else + WEBUI_DROPDOWN_STATUS="${REDct}DISABLED${CLRct}" + fi + printf " ${GRNct}wui${CLRct}. Toggle WebUI dropdown sub-menus\n" + printf " Currently: ${WEBUI_DROPDOWN_STATUS}\n\n" + printf " ${GRNct}e${CLRct}. Return to Main Menu\n" printf "\n${menuSepStr}\n\n" @@ -3412,6 +3472,16 @@ _Menu_ToggleOptions_() fi break ;; + wui) + printf "\n" + WEBUI_DROPDOWN_STATUS="$(WebUI_DropdownSubMenus status)" + if [ "$WEBUI_DROPDOWN_STATUS" = "ENABLED" ] + then WebUI_DropdownSubMenus disable + elif [ "$WEBUI_DROPDOWN_STATUS" = "DISABLED" ] + then WebUI_DropdownSubMenus enable + fi + break + ;; e) exitMenu=true break ;; @@ -4005,6 +4075,11 @@ case "$1" in settingstate="$(echo "$3" | sed "s/${SCRIPT_NAME_LOWER}_DNSmasqWatchdog//")"; settingstate="$(echo "$settingstate" | tr 'A-Z' 'a-z')" TailTaintDNSmasq "$settingstate" + elif echo "$3" | grep -qE "^${SCRIPT_NAME_LOWER}_WebUIDropdowns" + then + settingstate="$(echo "$3" | sed "s/${SCRIPT_NAME_LOWER}_WebUIDropdowns//")"; + settingstate="$(echo "$settingstate" | tr 'A-Z' 'a-z')" + WebUI_DropdownSubMenus "$settingstate" elif echo "$3" | grep -qE "^${SCRIPT_NAME_LOWER}servicerestart" then rm -f "$SCRIPT_WEB_DIR/detect_service.js" diff --git a/scmerlin_www.asp b/scmerlin_www.asp index f55a307..766a1e0 100644 --- a/scmerlin_www.asp +++ b/scmerlin_www.asp @@ -531,7 +531,7 @@ function update_temperatures() } /* End firmware functions */ -var arrayproclistlines=[],sortnameproc="CPU%",sortdirproc="desc",arraycronjobs=[],sortnamecron="Name",sortdircron="asc",tmout=null;function SetCurrentPage(){document.form.next_page.value=window.location.pathname.substring(1),document.form.current_page.value=window.location.pathname.substring(1)}Chart.defaults.global.defaultFontColor="#CCC",Chart.Tooltip.positioners.cursor=function(e,t){return t};var srvnamelist=["dnsmasq","wan","httpd","wireless","vsftpd","samba","ddns","ntpd/chronyd"],srvdesclist=["DNS/DHCP Server","Internet Connection","Web Interface","WiFi","FTP Server","Samba","DDNS client","Timeserver"],srvnamevisiblelist=[!0,!1,!0,!1,!0,!1,!1,!0],sortedAddonPages=[];function initial(){SetCurrentPage(),LoadCustomSettings(),show_menu(),Draw_Chart_NoData("nvramUsage","Data loading..."),Draw_Chart_NoData("jffsUsage","Data loading..."),Draw_Chart_NoData("MemoryUsage","Data loading..."),Draw_Chart_NoData("SwapUsage","No swap file configured"),$("#sortTableCron").empty(),$("#sortTableCron").append(BuildSortTableHtmlNoData()),$("#sortTableProcesses").empty(),$("#sortTableProcesses").append(BuildSortTableHtmlNoData());let e="",t="";if(isWireGuard_Supported){e+=Build_WireGuardServer_Table(1),$("#table_config").after(e);for(var r=1;r<6;r++)t+=Build_WireGuardClient_Table(r);$("#table_config").after(t)}let s="";for(r=1;r<3;r++)s+=Build_OpenVPNServer_Table(r);$("#table_config").after(s);let a="";for(r=1;r<6;r++)a+=Build_OpenVPNClient_Table(r);$("#table_config").after(a);let n="";for(var i=0;i",'',"Data loading...","","","",'
Data loading...
'}function BuildSortTableHtml(e){var t='';if("sortTableProcesses"==e){t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+='';for(var r=0;r',t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+=""}else if("sortTableCron"==e){t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+='';for(r=0;r',t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+=""}return t+="",t+="
PIDPPIDUSERSTATVSZVSZ%CPUCPU%COMMAND
"+arrayproclistlines[r].PID+""+arrayproclistlines[r].PPID+""+arrayproclistlines[r].USER+""+arrayproclistlines[r].STAT+""+arrayproclistlines[r].VSZ+""+arrayproclistlines[r].VSZP+""+arrayproclistlines[r].CPU+""+arrayproclistlines[r].CPUP+""+arrayproclistlines[r].COMMAND+"
NameMinHourDayMMonthDayWCommand
"+arraycronjobs[r].Name+""+arraycronjobs[r].Min+""+arraycronjobs[r].Hour+""+arraycronjobs[r].DayM+""+arraycronjobs[r].Month+""+arraycronjobs[r].DayW+""+arraycronjobs[r].Command+"
"}function Get_NTPWatchdogEnabled_File(){$.ajax({url:"/ext/scmerlin/watchdogenabled.htm",dataType:"text",error:function(e){document.form.scMerlin_NTPwatchdog.value="Disable",$("#scMerlin_NTPwatchdog_Status").text("Currently: DISABLED")},success:function(e){document.form.scMerlin_NTPwatchdog.value="Enable",$("#scMerlin_NTPwatchdog_Status").text("Currently: ENABLED")}})}function Save_NTPWatchdog(){document.form.action_script.value="start_scmerlin_NTPwatchdog"+document.form.scMerlin_NTPwatchdog.value,document.form.action_wait.value=4,$("#auto_refresh").prop("checked",!1),null!=tmout&&clearTimeout(tmout),showLoading(),document.form.submit(),setTimeout(Get_NTPWatchdogEnabled_File,4e3)}function Get_DNSmasqWatchdogEnabled_File(){$.ajax({url:"/ext/scmerlin/tailtaintdnsenabled.htm",dataType:"text",error:function(e){document.form.scMerlin_DNSmasqWatchdog.value="Disable",$("#scMerlin_DNSmasqWatchdog_Status").text("Currently: DISABLED")},success:function(e){document.form.scMerlin_DNSmasqWatchdog.value="Enable",$("#scMerlin_DNSmasqWatchdog_Status").text("Currently: ENABLED")}})}function Save_DNSmasqWatchdog(){document.form.action_script.value="start_scmerlin_DNSmasqWatchdog"+document.form.scMerlin_DNSmasqWatchdog.value,document.form.action_wait.value=4,$("#auto_refresh").prop("checked",!1),null!=tmout&&clearTimeout(tmout),showLoading(),document.form.submit(),setTimeout(Get_DNSmasqWatchdogEnabled_File,4e3)}const WaitMsgPopupBox={waitCounter:0,waitMaxSecs:0,waitTimerOn:!1,waitTimerID:null,waitMsgBox:null,waitMsgTemp:"",waitMsgBoxID:"myWaitMsgPopupBoxID",CloseMsg:function(){this.waitTimerOn=!1,this.waitCounter=0,this.waitMaxSecs=0,this.waitMsgTemp="",null!=this.waitTimerID&&(clearTimeout(this.waitTimerID),this.waitTimerID=null),null!=this.waitMsgBox&&this.waitMsgBox.close()},StartMsg:function(e,t,r){this.waitTimerOn||(this.waitTimerOn=!0,this.waitCounter=0,this.waitMsgTemp="",this.waitMaxSecs=Math.round(t/1e3),this.ShowTimedMsg(e,r))},ShowTimedMsg:function(e,t){if(this.waitCounter>this.waitMaxSecs)return void this.CloseMsg();if(!this.waitTimerOn)return;this.waitMsgBox=document.getElementById(this.waitMsgBoxID),null==this.waitMsgBox&&(this.waitMsgBox=document.body.appendChild(document.createElement("dialog")),this.waitMsgBox.setAttribute("id",this.waitMsgBoxID));let r=this.waitCounter+1;0==this.waitCounter&&this.waitMsgBox.close(),t?t&&(this.waitMsgBox.innerText=e+` [${r}]`):(0==this.waitCounter?this.waitMsgTemp=e+"\n >":this.waitMsgTemp=this.waitMsgTemp+">",this.waitMsgBox.innerText=this.waitMsgTemp),0==this.waitCounter&&this.waitMsgBox.showModal(),this.waitCounter=r,this.waitTimerID=setTimeout((function(){WaitMsgPopupBox.ShowTimedMsg(e,t)}),1e3)},ShowMsg:function(e,t){this.waitMsgBox=document.getElementById(this.waitMsgBoxID),null==this.waitMsgBox&&(this.waitMsgBox=document.body.appendChild(document.createElement("dialog")),this.waitMsgBox.setAttribute("id",this.waitMsgBoxID)),this.waitMsgBox.close(),this.waitMsgBox.innerText=e,this.waitMsgBox.showModal(),setTimeout((function(){WaitMsgPopupBox.waitMsgBox.close()}),t)}},AlertMsgBox={alertMsgBox:null,alertMsgBoxID:"myAlertMsgPopupBoxID",BuildAlertBox:function(e){let t;const r=e.split("\n");t='
';for(var s=0;s"+r[s]+"

";return t+='
',t},CloseAlert:function(){null!=this.alertMsgBox&&this.alertMsgBox.close()},ShowAlert:function(e){this.alertMsgBox=document.getElementById(this.alertMsgBoxID),null==this.alertMsgBox&&(this.alertMsgBox=document.body.appendChild(document.createElement("dialog")),this.alertMsgBox.setAttribute("id",this.alertMsgBoxID)),this.alertMsgBox.close(),this.alertMsgBox.innerHTML=this.BuildAlertBox(e),this.alertMsgBox.showModal()}};var theButtonBackStyle=null;function SetButtonGenState(e,t,r){t?(document.getElementById(e).disabled=!1,document.getElementById(e).title=r,null!=theButtonBackStyle&&(document.getElementById(e).style.background=theButtonBackStyle)):(0==document.getElementById(e).disabled&&(theButtonBackStyle=document.getElementById(e).style.background),document.getElementById(e).disabled=!0,document.getElementById(e).title=r,document.getElementById(e).style.background="grey")}function SetNTPReadyCheckButtonState(e,t){let r;r=e?NTPReadyCheck.buttonHintMsg:t,SetButtonGenState("btnSaveNTPcheck",e,r)}function Get_NTPReadyCheck_Option(){$.ajax({url:"/ext/scmerlin/NTP_Ready_Config.htm",dataType:"text",error:function(e){document.form.scMerlin_NTPcheck.value="Disable",NTPReadyCheck.prevOptionValue="DISABLED",WaitMsgPopupBox.CloseMsg(),SetNTPReadyCheckButtonState(!0,null),$("#scMerlin_NTPcheck_Status").text("Currently: DISABLED")},success:function(e){let t=e.split("\n");t=t.filter(Boolean);let r,s,a,n,i,o=t.length,l="";for(var c=0;c (a."+sortfield+".toLowerCase() > b."+sortfield+".toLowerCase()) ? 1 : ((b."+sortfield+".toLowerCase() > a."+sortfield+".toLowerCase()) ? -1 : 0));"),window[sortdir]="asc"):(eval(arrayid+" = "+arrayid+".sort((a,b) => (a."+sortfield+".toLowerCase() < b."+sortfield+".toLowerCase()) ? 1 : ((b."+sortfield+".toLowerCase() < a."+sortfield+".toLowerCase()) ? -1 : 0));"),window[sortdir]="desc"):"number"==sorttype&&(-1==sorttext.indexOf("↓")&&-1==sorttext.indexOf("↑")||-1!=sorttext.indexOf("↓")?(eval(arrayid+" = "+arrayid+".sort((a,b) => parseFloat(getNum(a."+sortfield+'.replace("m","000"))) - parseFloat(getNum(b.'+sortfield+'.replace("m","000"))));'),window[sortdir]="asc"):(eval(arrayid+" = "+arrayid+".sort((a,b) => parseFloat(getNum(b."+sortfield+'.replace("m","000"))) - parseFloat(getNum(a.'+sortfield+'.replace("m","000"))));'),window[sortdir]="desc")),$("#"+tableid).empty(),$("#"+tableid).append(BuildSortTableHtml(tableid)),$("#"+tableid).find(".sortable").each((function(e,t){t.innerHTML==window[sortname]&&("asc"==window[sortdir]?t.innerHTML=window[sortname]+" ↑":t.innerHTML=window[sortname]+" ↓")}))}function getNum(e){if(isNaN(e)){if("*"==e)return-10;if(-1!=e.indexOf("*/"))return-5;if(-1!=e.indexOf("/"))return e.split("/")[0];if("Sun"==e)return 0;if("Mon"==e)return 1;if("Tue"==e)return 2;if("Wed"==e)return 3;if("Thu"==e)return 4;if("Fri"==e)return 5;if("Sat"==e)return 6}return e}function ToggleRefresh(){1==$("#auto_refresh").prop("checked")?get_proclist_file():null!=tmout&&clearTimeout(tmout)}function BuildAddonPageTable(e,t,r){var s="";if(0==r&&(s+='
 
',s+='',s+='',s+='',s+=""),0!=r&&r%4!=0||(s+=""),s+='",r>0&&(r+1)%4==0&&(s+=""),r==sortedAddonPages.length-1){if(sortedAddonPages.length%4!=0){for(var a=4-sortedAddonPages.length%4,n=0;n';s+=""}s+="
WebUI Addons (click to expand/collapse)
'+e+'
'+t.substring(t.lastIndexOf("/")+1)+"
"}return s}function BuildServiceTable(e,t,r,s){var a="";return 0==s&&(a+='
 
',a+='',a+='',a+='',a+=""),0!=s&&s%2!=0||(a+=""),a+=r?'":'",a+='",s>0&&(s+1)%2==0&&(a+=""),s==srvnamelist.length-1&&(a+="
Services (click to expand/collapse)
'+t+' ('+e+")'+t+"',a+='',a+='',a+='',a+='',a+="
"),a}function Build_OpenVPNClient_Table(theIndex){let vpnClientHTML="",vpnClientName="vpnclient"+theIndex,vpnClientDesc=eval("document.form.vpnc"+theIndex+"_desc").value;return 1==theIndex&&(vpnClientHTML+='
 
',vpnClientHTML+='',vpnClientHTML+='',vpnClientHTML+='',vpnClientHTML+=""),1!=theIndex&&(theIndex+1)%2!=0||(vpnClientHTML+=""),vpnClientHTML+='",vpnClientHTML+='",5==theIndex&&(vpnClientHTML+=''),theIndex>1&&theIndex%2==0&&(vpnClientHTML+=""),5==theIndex&&(vpnClientHTML+="
OpenVPN Clients (click to expand/collapse)
OpenVPN Client '+theIndex,vpnClientHTML+='
('+vpnClientDesc+")
',vpnClientHTML+='',vpnClientHTML+='',vpnClientHTML+='',vpnClientHTML+='',vpnClientHTML+="
"),vpnClientHTML}function Build_OpenVPNServer_Table(e){let t="",r="vpnserver"+e;return 1==e&&(t+='
 
',t+='',t+='',t+='',t+="",t+=""),t+='",t+='",2==e&&(t+="",t+="
OpenVPN Servers (click to expand/collapse)
OpenVPN Server '+e+"',t+='',t+='',t+='',t+='',t+="
"),t}function Build_WireGuardServer_Table(e){let t="",r="wgServer"+e;return 1==e&&(t+='
 
',t+='',t+='',t+='',t+="",t+=""),t+='",t+='",1==e&&(t+='',t+="
WireGuard Server (click to expand/collapse)
WireGuard Server '+e+"',t+='',t+='',t+='',t+='',t+="
"),t}function Build_WireGuardClient_Table(theIndex){let wgClientHTML="",wgClientName="wgClient"+theIndex,wgClientDesc=eval("document.form.wrgc"+theIndex+"_desc").value;return null!==wgClientDesc&&""!==wgClientDesc||(wgClientDesc="No description"),1==theIndex&&(wgClientHTML+='
 
',wgClientHTML+='',wgClientHTML+='',wgClientHTML+='',wgClientHTML+=""),1!=theIndex&&(theIndex+1)%2!=0||(wgClientHTML+=""),wgClientHTML+='",wgClientHTML+='",5==theIndex&&(wgClientHTML+=''),theIndex>1&&theIndex%2==0&&(wgClientHTML+=""),5==theIndex&&(wgClientHTML+="
WireGuard Clients (click to expand/collapse)
WireGuard Client '+theIndex,wgClientHTML+='
('+wgClientDesc+")
',wgClientHTML+='',wgClientHTML+='',wgClientHTML+='',wgClientHTML+='',wgClientHTML+="
"),wgClientHTML}function round(e,t){return Number(Math.round(e+"e"+t)+"e-"+t)}function Draw_Chart_NoData(e,t){document.getElementById("canvasChart"+e).width="265",document.getElementById("canvasChart"+e).height="250",document.getElementById("canvasChart"+e).style.width="265px",document.getElementById("canvasChart"+e).style.height="250px";var r=document.getElementById("canvasChart"+e).getContext("2d");r.save(),r.textAlign="center",r.textBaseline="middle",r.font="normal normal bolder 22px Arial",r.fillStyle="white",r.fillText(t,135,125),r.restore()}function Draw_Chart(e){var t=[],r=[],s=[],a="",n="";"MemoryUsage"==e?(t=[1*mem_stats_arr[0]-1*mem_stats_arr[1]-1*mem_stats_arr[2]-1*mem_stats_arr[3],mem_stats_arr[1],mem_stats_arr[2],mem_stats_arr[3]],r=["Used","Free","Buffers","Cache"],s=["#5eaec0","#12cf80","#ceca09","#9d12c4"],a="Memory Usage",n="MB"):"SwapUsage"==e?(t=[mem_stats_arr[4],1*mem_stats_arr[5]-1*mem_stats_arr[4]],r=["Used","Free"],s=["#135fee","#1aa658"],a="Swap Usage",n="MB"):"nvramUsage"==e?(t=[round(mem_stats_arr[6]/1024,2).toFixed(2),round(1*nvramtotal-1*mem_stats_arr[6]/1024,2).toFixed(2)],r=["Used","Free"],s=["#5eaec0","#12cf80"],a="NVRAM Usage",n="KB"):"jffsUsage"==e&&(t=[jffs_Used,jffs_Free],r=["Used","Free"],s=["#135fee","#1aa658"],a="JFFS Usage",n="MB");var i=window["Chart"+e];null!=i&&i.destroy();var o=document.getElementById("canvasChart"+e).getContext("2d");i=new Chart(o,{type:"pie",options:{segmentShowStroke:!1,segmentStrokeColor:"#000",maintainAspectRatio:!1,animation:{duration:0},hover:{animationDuration:0},responsiveAnimationDuration:0,legend:{onClick:null,display:!0,position:"left",labels:{fontColor:"#ffffff"}},title:{display:!0,text:a,position:"top"},tooltips:{callbacks:{title:function(e,t){return t.labels[e[0].index]},label:function(e,t){return round(t.datasets[e.datasetIndex].data[e.index],2).toFixed(2)+" "+n}},mode:"point",position:"cursor",intersect:!0},scales:{xAxes:[{display:!1,gridLines:{display:!1},scaleLabel:{display:!1},ticks:{display:!1}}],yAxes:[{display:!1,gridLines:{display:!1},scaleLabel:{display:!1},ticks:{display:!1}}]}},data:{labels:r,datasets:[{data:t,borderWidth:1,backgroundColor:s,borderColor:"#000000"}]}}),window["Chart"+e]=i} +var arrayproclistlines=[],sortnameproc="CPU%",sortdirproc="desc",arraycronjobs=[],sortnamecron="Name",sortdircron="asc",tmout=null;function SetCurrentPage(){document.form.next_page.value=window.location.pathname.substring(1),document.form.current_page.value=window.location.pathname.substring(1)}Chart.defaults.global.defaultFontColor="#CCC",Chart.Tooltip.positioners.cursor=function(e,t){return t};var srvnamelist=["dnsmasq","wan","httpd","wireless","vsftpd","samba","ddns","ntpd/chronyd"],srvdesclist=["DNS/DHCP Server","Internet Connection","Web Interface","WiFi","FTP Server","Samba","DDNS client","Timeserver"],srvnamevisiblelist=[!0,!1,!0,!1,!0,!1,!1,!0],sortedAddonPages=[];function initial(){SetCurrentPage(),LoadCustomSettings(),show_menu(),Draw_Chart_NoData("nvramUsage","Data loading..."),Draw_Chart_NoData("jffsUsage","Data loading..."),Draw_Chart_NoData("MemoryUsage","Data loading..."),Draw_Chart_NoData("SwapUsage","No swap file configured"),$("#sortTableCron").empty(),$("#sortTableCron").append(BuildSortTableHtmlNoData()),$("#sortTableProcesses").empty(),$("#sortTableProcesses").append(BuildSortTableHtmlNoData());let e="",t="";if(isWireGuard_Supported){e+=Build_WireGuardServer_Table(1),$("#table_config").after(e);for(var r=1;r<6;r++)t+=Build_WireGuardClient_Table(r);$("#table_config").after(t)}let s="";for(r=1;r<3;r++)s+=Build_OpenVPNServer_Table(r);$("#table_config").after(s);let a="";for(r=1;r<6;r++)a+=Build_OpenVPNClient_Table(r);$("#table_config").after(a);let n="";for(var i=0;i",'',"Data loading...","","","",'
Data loading...
'}function BuildSortTableHtml(e){var t='';if("sortTableProcesses"==e){t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+='';for(var r=0;r',t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+=""}else if("sortTableCron"==e){t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+='';for(r=0;r',t+="",t+="",t+="",t+="",t+="",t+="",t+="",t+=""}return t+="",t+="
PIDPPIDUSERSTATVSZVSZ%CPUCPU%COMMAND
"+arrayproclistlines[r].PID+""+arrayproclistlines[r].PPID+""+arrayproclistlines[r].USER+""+arrayproclistlines[r].STAT+""+arrayproclistlines[r].VSZ+""+arrayproclistlines[r].VSZP+""+arrayproclistlines[r].CPU+""+arrayproclistlines[r].CPUP+""+arrayproclistlines[r].COMMAND+"
NameMinHourDayMMonthDayWCommand
"+arraycronjobs[r].Name+""+arraycronjobs[r].Min+""+arraycronjobs[r].Hour+""+arraycronjobs[r].DayM+""+arraycronjobs[r].Month+""+arraycronjobs[r].DayW+""+arraycronjobs[r].Command+"
"}function Get_NTPWatchdogEnabled_File(){$.ajax({url:"/ext/scmerlin/watchdogenabled.htm",dataType:"text",error:function(e){document.form.scMerlin_NTPwatchdog.value="Disable",$("#scMerlin_NTPwatchdog_Status").text("Currently: DISABLED")},success:function(e){document.form.scMerlin_NTPwatchdog.value="Enable",$("#scMerlin_NTPwatchdog_Status").text("Currently: ENABLED")}})}function Save_NTPWatchdog(){document.form.action_script.value="start_scmerlin_NTPwatchdog"+document.form.scMerlin_NTPwatchdog.value,document.form.action_wait.value=4,$("#auto_refresh").prop("checked",!1),null!=tmout&&clearTimeout(tmout),showLoading(),document.form.submit(),setTimeout(Get_NTPWatchdogEnabled_File,4e3)}function Get_DNSmasqWatchdogEnabled_File(){$.ajax({url:"/ext/scmerlin/tailtaintdnsenabled.htm",dataType:"text",error:function(e){document.form.scMerlin_DNSmasqWatchdog.value="Disable",$("#scMerlin_DNSmasqWatchdog_Status").text("Currently: DISABLED")},success:function(e){document.form.scMerlin_DNSmasqWatchdog.value="Enable",$("#scMerlin_DNSmasqWatchdog_Status").text("Currently: ENABLED")}})}function Get_WebUIDropdownsEnabled_File(){$.ajax({url:"/ext/scmerlin/webuidropdownenabled.htm",dataType:"text",cache:false,error:function(){document.form.scMerlin_WebUIDropdowns.value="Disable",$("#scMerlin_WebUIDropdowns_Status").text("Currently: DISABLED")},success:function(){document.form.scMerlin_WebUIDropdowns.value="Enable",$("#scMerlin_WebUIDropdowns_Status").text("Currently: ENABLED")}})}function Save_WebUIDropdowns(){document.form.action_script.value="start_scmerlin_WebUIDropdowns"+document.form.scMerlin_WebUIDropdowns.value,document.form.action_wait.value=4,$("#auto_refresh").prop("checked",false),null!=tmout&&clearTimeout(tmout),showLoading(),document.form.submit(),setTimeout(Get_WebUIDropdownsEnabled_File,4e3)}function Save_DNSmasqWatchdog(){document.form.action_script.value="start_scmerlin_DNSmasqWatchdog"+document.form.scMerlin_DNSmasqWatchdog.value,document.form.action_wait.value=4,$("#auto_refresh").prop("checked",!1),null!=tmout&&clearTimeout(tmout),showLoading(),document.form.submit(),setTimeout(Get_DNSmasqWatchdogEnabled_File,4e3)}const WaitMsgPopupBox={waitCounter:0,waitMaxSecs:0,waitTimerOn:!1,waitTimerID:null,waitMsgBox:null,waitMsgTemp:"",waitMsgBoxID:"myWaitMsgPopupBoxID",CloseMsg:function(){this.waitTimerOn=!1,this.waitCounter=0,this.waitMaxSecs=0,this.waitMsgTemp="",null!=this.waitTimerID&&(clearTimeout(this.waitTimerID),this.waitTimerID=null),null!=this.waitMsgBox&&this.waitMsgBox.close()},StartMsg:function(e,t,r){this.waitTimerOn||(this.waitTimerOn=!0,this.waitCounter=0,this.waitMsgTemp="",this.waitMaxSecs=Math.round(t/1e3),this.ShowTimedMsg(e,r))},ShowTimedMsg:function(e,t){if(this.waitCounter>this.waitMaxSecs)return void this.CloseMsg();if(!this.waitTimerOn)return;this.waitMsgBox=document.getElementById(this.waitMsgBoxID),null==this.waitMsgBox&&(this.waitMsgBox=document.body.appendChild(document.createElement("dialog")),this.waitMsgBox.setAttribute("id",this.waitMsgBoxID));let r=this.waitCounter+1;0==this.waitCounter&&this.waitMsgBox.close(),t?t&&(this.waitMsgBox.innerText=e+` [${r}]`):(0==this.waitCounter?this.waitMsgTemp=e+"\n >":this.waitMsgTemp=this.waitMsgTemp+">",this.waitMsgBox.innerText=this.waitMsgTemp),0==this.waitCounter&&this.waitMsgBox.showModal(),this.waitCounter=r,this.waitTimerID=setTimeout((function(){WaitMsgPopupBox.ShowTimedMsg(e,t)}),1e3)},ShowMsg:function(e,t){this.waitMsgBox=document.getElementById(this.waitMsgBoxID),null==this.waitMsgBox&&(this.waitMsgBox=document.body.appendChild(document.createElement("dialog")),this.waitMsgBox.setAttribute("id",this.waitMsgBoxID)),this.waitMsgBox.close(),this.waitMsgBox.innerText=e,this.waitMsgBox.showModal(),setTimeout((function(){WaitMsgPopupBox.waitMsgBox.close()}),t)}},AlertMsgBox={alertMsgBox:null,alertMsgBoxID:"myAlertMsgPopupBoxID",BuildAlertBox:function(e){let t;const r=e.split("\n");t='
';for(var s=0;s"+r[s]+"

";return t+='
',t},CloseAlert:function(){null!=this.alertMsgBox&&this.alertMsgBox.close()},ShowAlert:function(e){this.alertMsgBox=document.getElementById(this.alertMsgBoxID),null==this.alertMsgBox&&(this.alertMsgBox=document.body.appendChild(document.createElement("dialog")),this.alertMsgBox.setAttribute("id",this.alertMsgBoxID)),this.alertMsgBox.close(),this.alertMsgBox.innerHTML=this.BuildAlertBox(e),this.alertMsgBox.showModal()}};var theButtonBackStyle=null;function SetButtonGenState(e,t,r){t?(document.getElementById(e).disabled=!1,document.getElementById(e).title=r,null!=theButtonBackStyle&&(document.getElementById(e).style.background=theButtonBackStyle)):(0==document.getElementById(e).disabled&&(theButtonBackStyle=document.getElementById(e).style.background),document.getElementById(e).disabled=!0,document.getElementById(e).title=r,document.getElementById(e).style.background="grey")}function SetNTPReadyCheckButtonState(e,t){let r;r=e?NTPReadyCheck.buttonHintMsg:t,SetButtonGenState("btnSaveNTPcheck",e,r)}function Get_NTPReadyCheck_Option(){$.ajax({url:"/ext/scmerlin/NTP_Ready_Config.htm",dataType:"text",error:function(e){document.form.scMerlin_NTPcheck.value="Disable",NTPReadyCheck.prevOptionValue="DISABLED",WaitMsgPopupBox.CloseMsg(),SetNTPReadyCheckButtonState(!0,null),$("#scMerlin_NTPcheck_Status").text("Currently: DISABLED")},success:function(e){let t=e.split("\n");t=t.filter(Boolean);let r,s,a,n,i,o=t.length,l="";for(var c=0;c (a."+sortfield+".toLowerCase() > b."+sortfield+".toLowerCase()) ? 1 : ((b."+sortfield+".toLowerCase() > a."+sortfield+".toLowerCase()) ? -1 : 0));"),window[sortdir]="asc"):(eval(arrayid+" = "+arrayid+".sort((a,b) => (a."+sortfield+".toLowerCase() < b."+sortfield+".toLowerCase()) ? 1 : ((b."+sortfield+".toLowerCase() < a."+sortfield+".toLowerCase()) ? -1 : 0));"),window[sortdir]="desc"):"number"==sorttype&&(-1==sorttext.indexOf("↓")&&-1==sorttext.indexOf("↑")||-1!=sorttext.indexOf("↓")?(eval(arrayid+" = "+arrayid+".sort((a,b) => parseFloat(getNum(a."+sortfield+'.replace("m","000"))) - parseFloat(getNum(b.'+sortfield+'.replace("m","000"))));'),window[sortdir]="asc"):(eval(arrayid+" = "+arrayid+".sort((a,b) => parseFloat(getNum(b."+sortfield+'.replace("m","000"))) - parseFloat(getNum(a.'+sortfield+'.replace("m","000"))));'),window[sortdir]="desc")),$("#"+tableid).empty(),$("#"+tableid).append(BuildSortTableHtml(tableid)),$("#"+tableid).find(".sortable").each((function(e,t){t.innerHTML==window[sortname]&&("asc"==window[sortdir]?t.innerHTML=window[sortname]+" ↑":t.innerHTML=window[sortname]+" ↓")}))}function getNum(e){if(isNaN(e)){if("*"==e)return-10;if(-1!=e.indexOf("*/"))return-5;if(-1!=e.indexOf("/"))return e.split("/")[0];if("Sun"==e)return 0;if("Mon"==e)return 1;if("Tue"==e)return 2;if("Wed"==e)return 3;if("Thu"==e)return 4;if("Fri"==e)return 5;if("Sat"==e)return 6}return e}function ToggleRefresh(){1==$("#auto_refresh").prop("checked")?get_proclist_file():null!=tmout&&clearTimeout(tmout)}function BuildAddonPageTable(e,t,r){var s="";if(0==r&&(s+='
 
',s+='',s+='',s+='',s+=""),0!=r&&r%4!=0||(s+=""),s+='",r>0&&(r+1)%4==0&&(s+=""),r==sortedAddonPages.length-1){if(sortedAddonPages.length%4!=0){for(var a=4-sortedAddonPages.length%4,n=0;n';s+=""}s+="
WebUI Addons (click to expand/collapse)
'+e+'
'+t.substring(t.lastIndexOf("/")+1)+"
"}return s}function BuildServiceTable(e,t,r,s){var a="";return 0==s&&(a+='
 
',a+='',a+='',a+='',a+=""),0!=s&&s%2!=0||(a+=""),a+=r?'":'",a+='",s>0&&(s+1)%2==0&&(a+=""),s==srvnamelist.length-1&&(a+="
Services (click to expand/collapse)
'+t+' ('+e+")'+t+"',a+='',a+='',a+='',a+='',a+="
"),a}function Build_OpenVPNClient_Table(theIndex){let vpnClientHTML="",vpnClientName="vpnclient"+theIndex,vpnClientDesc=eval("document.form.vpnc"+theIndex+"_desc").value;return 1==theIndex&&(vpnClientHTML+='
 
',vpnClientHTML+='',vpnClientHTML+='',vpnClientHTML+='',vpnClientHTML+=""),1!=theIndex&&(theIndex+1)%2!=0||(vpnClientHTML+=""),vpnClientHTML+='",vpnClientHTML+='",5==theIndex&&(vpnClientHTML+=''),theIndex>1&&theIndex%2==0&&(vpnClientHTML+=""),5==theIndex&&(vpnClientHTML+="
OpenVPN Clients (click to expand/collapse)
OpenVPN Client '+theIndex,vpnClientHTML+='
('+vpnClientDesc+")
',vpnClientHTML+='',vpnClientHTML+='',vpnClientHTML+='',vpnClientHTML+='',vpnClientHTML+="
"),vpnClientHTML}function Build_OpenVPNServer_Table(e){let t="",r="vpnserver"+e;return 1==e&&(t+='
 
',t+='',t+='',t+='',t+="",t+=""),t+='",t+='",2==e&&(t+="",t+="
OpenVPN Servers (click to expand/collapse)
OpenVPN Server '+e+"',t+='',t+='',t+='',t+='',t+="
"),t}function Build_WireGuardServer_Table(e){let t="",r="wgServer"+e;return 1==e&&(t+='
 
',t+='',t+='',t+='',t+="",t+=""),t+='",t+='",1==e&&(t+='',t+="
WireGuard Server (click to expand/collapse)
WireGuard Server '+e+"',t+='',t+='',t+='',t+='',t+="
"),t}function Build_WireGuardClient_Table(theIndex){let wgClientHTML="",wgClientName="wgClient"+theIndex,wgClientDesc=eval("document.form.wrgc"+theIndex+"_desc").value;return null!==wgClientDesc&&""!==wgClientDesc||(wgClientDesc="No description"),1==theIndex&&(wgClientHTML+='
 
',wgClientHTML+='',wgClientHTML+='',wgClientHTML+='',wgClientHTML+=""),1!=theIndex&&(theIndex+1)%2!=0||(wgClientHTML+=""),wgClientHTML+='",wgClientHTML+='",5==theIndex&&(wgClientHTML+=''),theIndex>1&&theIndex%2==0&&(wgClientHTML+=""),5==theIndex&&(wgClientHTML+="
WireGuard Clients (click to expand/collapse)
WireGuard Client '+theIndex,wgClientHTML+='
('+wgClientDesc+")
',wgClientHTML+='',wgClientHTML+='',wgClientHTML+='',wgClientHTML+='',wgClientHTML+="
"),wgClientHTML}function round(e,t){return Number(Math.round(e+"e"+t)+"e-"+t)}function Draw_Chart_NoData(e,t){document.getElementById("canvasChart"+e).width="265",document.getElementById("canvasChart"+e).height="250",document.getElementById("canvasChart"+e).style.width="265px",document.getElementById("canvasChart"+e).style.height="250px";var r=document.getElementById("canvasChart"+e).getContext("2d");r.save(),r.textAlign="center",r.textBaseline="middle",r.font="normal normal bolder 22px Arial",r.fillStyle="white",r.fillText(t,135,125),r.restore()}function Draw_Chart(e){var t=[],r=[],s=[],a="",n="";"MemoryUsage"==e?(t=[1*mem_stats_arr[0]-1*mem_stats_arr[1]-1*mem_stats_arr[2]-1*mem_stats_arr[3],mem_stats_arr[1],mem_stats_arr[2],mem_stats_arr[3]],r=["Used","Free","Buffers","Cache"],s=["#5eaec0","#12cf80","#ceca09","#9d12c4"],a="Memory Usage",n="MB"):"SwapUsage"==e?(t=[mem_stats_arr[4],1*mem_stats_arr[5]-1*mem_stats_arr[4]],r=["Used","Free"],s=["#135fee","#1aa658"],a="Swap Usage",n="MB"):"nvramUsage"==e?(t=[round(mem_stats_arr[6]/1024,2).toFixed(2),round(1*nvramtotal-1*mem_stats_arr[6]/1024,2).toFixed(2)],r=["Used","Free"],s=["#5eaec0","#12cf80"],a="NVRAM Usage",n="KB"):"jffsUsage"==e&&(t=[jffs_Used,jffs_Free],r=["Used","Free"],s=["#135fee","#1aa658"],a="JFFS Usage",n="MB");var i=window["Chart"+e];null!=i&&i.destroy();var o=document.getElementById("canvasChart"+e).getContext("2d");i=new Chart(o,{type:"pie",options:{segmentShowStroke:!1,segmentStrokeColor:"#000",maintainAspectRatio:!1,animation:{duration:0},hover:{animationDuration:0},responsiveAnimationDuration:0,legend:{onClick:null,display:!0,position:"left",labels:{fontColor:"#ffffff"}},title:{display:!0,text:a,position:"top"},tooltips:{callbacks:{title:function(e,t){return t.labels[e[0].index]},label:function(e,t){return round(t.datasets[e.datasetIndex].data[e.index],2).toFixed(2)+" "+n}},mode:"point",position:"cursor",intersect:!0},scales:{xAxes:[{display:!1,gridLines:{display:!1},scaleLabel:{display:!1},ticks:{display:!1}}],yAxes:[{display:!1,gridLines:{display:!1},scaleLabel:{display:!1},ticks:{display:!1}}]}},data:{labels:r,datasets:[{data:t,borderWidth:1,backgroundColor:s,borderColor:"#000000"}]}}),window["Chart"+e]=i} @@ -660,6 +660,25 @@ var arrayproclistlines=[],sortnameproc="CPU%",sortdirproc="desc",arraycronjobs=[ + + + +Enable WebUI dropdown sub-menus
+ +Yes +No +       + +      + + + diff --git a/scmerlin_www.js b/scmerlin_www.js index 074caef..629505f 100644 --- a/scmerlin_www.js +++ b/scmerlin_www.js @@ -88,6 +88,7 @@ function initial() Get_NTPWatchdogEnabled_File(); Get_NTPReadyCheck_Option(); Get_DNSmasqWatchdogEnabled_File(); + Get_WebUIDropdownsEnabled_File(); update_temperatures(); update_wanuptime(); update_sysinfo(); @@ -377,6 +378,39 @@ function Get_DNSmasqWatchdogEnabled_File() }); } +function Get_WebUIDropdownsEnabled_File() +{ + $.ajax({ + url: "/ext/scmerlin/webuidropdownenabled.htm", + dataType: "text", + cache: false, + error: function(){ + document.form.scMerlin_WebUIDropdowns.value = "Disable"; + $("#scMerlin_WebUIDropdowns_Status").text("Currently: DISABLED"); + }, + success: function(){ + document.form.scMerlin_WebUIDropdowns.value = "Enable"; + $("#scMerlin_WebUIDropdowns_Status").text("Currently: ENABLED"); + } + }); +} + +function Save_WebUIDropdowns() +{ + document.form.action_script.value = + "start_scmerlin_WebUIDropdowns" + document.form.scMerlin_WebUIDropdowns.value; + + document.form.action_wait.value = 4; + + $("#auto_refresh").prop("checked", false); + if (tmout != null) clearTimeout(tmout); + + showLoading(); + document.form.submit(); + + setTimeout(Get_WebUIDropdownsEnabled_File, 4000); +} + /**-------------------------------------**/ /** Added by Martinski W. [2024-Apr-29] **/ /**-------------------------------------**/ From 725b694433b33667a64b48987a1f42731d37f18d Mon Sep 17 00:00:00 2001 From: ExtremeFiretop Date: Tue, 3 Mar 2026 21:16:03 -0500 Subject: [PATCH 2/6] Actually detach state.js modifications Actually detach state.js modifications --- scmerlin.sh | 275 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 202 insertions(+), 73 deletions(-) diff --git a/scmerlin.sh b/scmerlin.sh index 87ea840..9d2b69a 100644 --- a/scmerlin.sh +++ b/scmerlin.sh @@ -770,42 +770,14 @@ Update_Check() echo "$doupdate,$localver,$serverver" } -##----------------------------------------## -## Modified by Martinski W. [2025-May-17] ## -##----------------------------------------## -AppendTo_statejs_3004_() +##------------------------------------------## +## Modified by ExtremeFiretop [2026-Mar-03] ## +##------------------------------------------## +AppendTo_statejs_Sitemap_3004_() { - cat << 'EOF' + cat << 'EOF' +/*BEGIN:SCMERLIN_SITEMAP*/ var myMenu = []; -function AddDropdowns() -{ - if (myMenu.length == 0) - { - setTimeout(AddDropdowns,1000); - return; - } - for (var i = 0; i < myMenu.length; i++) - { - var sitemapstring = '