├── LICENSE.md ├── README.md ├── _redirects ├── altervp ├── README.md ├── altervp.js └── altervp.min.js ├── cpanel-logo-to-copyright ├── cpanel-logo-to-copyright.js ├── cpanel-logo-to-copyright.min.js └── readme.md ├── dropdown-bug-fix ├── README.md ├── dropdown-bug-fix.js └── dropdown-bug-fix.min.js ├── element-changer ├── README.md ├── element-changer.js ├── element-changer.min.js └── tools.element-changer.js ├── menu-item-changer ├── README.md ├── menu-item-changer.js └── menu-item-changer.min.js ├── responsive-domain-search ├── README.md ├── responsive-domain-search.js └── responsive-domain-search.min.js ├── sidebar-bug-fix ├── README.md ├── sidebar-bug-fix.js └── sidebar-bug-fix.min.js ├── theme-switcher ├── readme.md ├── theme-switcher.js └── theme-switcher.min.js ├── translations └── README_el.md └── vpanel-alerts ├── README.md ├── vpanel-alerts.js └── vpanel-alerts.min.js /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT ATTRIBUTION License 2 | 3 | Copyright (c) 2018-2023 Wybe Network 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | You may not modify the credits. 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | Except as contained in this notice, the name(s) of the above copyright holders 18 | shall not be used in advertising or otherwise to promote the sale, use or other 19 | dealings in this Software without prior written authorization. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | 29 | CREDITS TO THE AUTHORS SHALL NOT BE REMOVED WITHOUT WRITTEN AUTHORIZATION BY THE 30 | AUTHORS THEMSELVES. BY REMOVING THE CREDITS WITHOUT WRITTEN AUTHORIZATION, YOU ARE 31 | NOT ALLOWED TO USE THE SOFTWARE. 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VistaPanel Customizations 2 | [![Available in Greek](https://img.shields.io/badge/Available%20In-Greek-blue.svg?longcache=true&style=for-the-badge&colorA=2abbea)](translations/README_el.md) 3 | 4 | **A repository filled with JS and CSS scripts for customizing VistaPanel.** 5 | 6 | You **MUST** read and follow the LICENSE file before using any of the scripts here. 7 | Developed by Wybe Network for the MOFH community. 8 | 9 | Everything here is **FREE** as long as you follow the [LICENSE](LICENSE.md). 10 | 11 | Request permission to remove credits from our scripts on our [Discord Server](https://discord.gg/TCspBav). 12 | 13 | # Is something not working? 14 | Please check the issues tab to see what's currently buggy or not working. 15 | 16 | If you find an issue and want to fix it, submit a PR and we will check it. If it helps, we will merge it. 17 | 18 | # How to use the scripts provided here? 19 | Go to each script's folder and find the script you want to use. There will be instructions on how to do so. 20 | 21 | Read the instructions file first, after understanding it go ahead and 22 | use jsDelivr / our CDN with the method described in the article, 23 | or download the file and upload it to your site / CDN. 24 | 25 | You can make use of our CDN at https://vpc.cdn.wybenetwork.com/{scriptname}/{scriptfilename.js}. 26 | 27 | # Documentation 28 | 29 | You can find the documentation for VistaPanel customizations at https://docs.wybenetwork.com. 30 | 31 | # Copyright Info 32 | Copyright 2018-2023 © Wybe Network. All Rights Reserved, check the [LICENSE](LICENSE.md) for more details. 33 | -------------------------------------------------------------------------------- /_redirects: -------------------------------------------------------------------------------- 1 | / https://cdn.wybenetwork.com/ 302 2 | -------------------------------------------------------------------------------- /altervp/README.md: -------------------------------------------------------------------------------- 1 | # AlterVP 2 | 3 | ## Haven't I heard of this? 4 | You may have, indeed! It was a [tool created by xpde/woxly](https://www.byet.net/index.php?/topic/2705-altervp/), that unfortunately disappeared. 5 | There was no archive of it available, so I [(Anyx)](https://github.com/4yx) recreated it from scratch. 6 | 7 | ## What does it do? 8 | It has the following features: 9 | * Change the Title 10 | * Change the Protocol 11 | * Change the Logo 12 | * Change the Theme 13 | * Add your own Credits 14 | * Organized Code 15 | * Clean Setup usage 16 | 17 | ## Where should I put it? 18 | Put it in the Footer Advert Area. 19 | 20 | ## How can I install it? 21 | Apply this code anywhere, within a script tag: 22 | ```js 23 | const AlterVP = { 24 | title: "AlterVP - vPanel", 25 | logo: "logo.png", 26 | protocol: "https", 27 | theme: "dark", 28 | category: "normal", // normal, lite, lightspace 29 | credits: { 30 | desc: "AlterVP", 31 | logo: "small-logo.png" 32 | } 33 | }; 34 | ``` 35 | Replace the values inside with the ones you want for your panel. You can comment out the lines of the features you do not wish to use. 36 | 37 | Afterwards, create a script tag with `src` pointing to `altervp.js` or `altervp.min.js` for the minified version. 38 | 39 | We have also provided a ready code below, along with an explanation as to why GitHub's RAW file output cannot be used. 40 | 41 | ### Content-Type Header Errors 42 | The RAW option on GitHub can return an incorrect Content-Type header which makes the code not load at all. 43 | To solve this, we need an external service which adds the correct type, like jsDelivr, or our CDN. 44 | 45 | The full code, using jsDelivr: 46 | ```html 47 | 60 | 61 | ``` 62 | Alternatively, you can use our CDN: 63 | ```html 64 | 77 | 78 | ``` 79 | Feel free to remove the comment line symbol (``//``) that explains the type of theme categories you can have. 80 | 81 | ## Changelog 82 | * Created on 14 September 2018 by [woxly](https://github.com/woxly) 83 | * Modified on 14 September 2018 by [woxly](https://github.com/woxly) 84 | * Lost in time 85 | * Recreated on 30 August and modified on 03 September 2022 by [Anyx](https://github.com/4yx) 86 | * Last modified on 13 September 2022 by [Anyx](https://github.com/4yx) -------------------------------------------------------------------------------- /altervp/altervp.js: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Created on 14 September 2018 by woxly 3 | * Recreated on 30 August and modified on 03 September 2022 by Anyx 4 | * Last modified on 13 September 2022 by Anyx 5 | * DO NOT REMOVE CREDITS! 6 | * Created for: Wybe Network. 7 | */ 8 | document.addEventListener("DOMContentLoaded", function() { 9 | // Title 10 | if (AlterVP.title !== undefined) { 11 | document.title = AlterVP.title; 12 | } 13 | // Protocol 14 | if (AlterVP.protocol !== undefined) { 15 | if (window.location.protocol.replace(/:/g,'') !== AlterVP.protocol) { 16 | location.protocol = AlterVP.protocol; 17 | } 18 | } 19 | // Logo 20 | if (AlterVP.logo !== undefined) { 21 | document.getElementById("imgLogo").src = AlterVP.logo; 22 | } 23 | // Themes 24 | if (AlterVP.theme !== undefined && AlterVP.category !== undefined) { 25 | if (AlterVP.category !== "lightspace") { 26 | themeURL = ['https://vpt.cdn.wybenetwork.com', AlterVP.theme, 'styles.css'].join("/"); 27 | if (AlterVP.category == "normal") { 28 | iconURL = ['https://vpt.cdn.wybenetwork.com', AlterVP.theme, 'icon_spritemap.css'].join("/"); 29 | icon = document.createElement('link'); 30 | icon.type = 'text/css'; 31 | icon.rel = 'stylesheet'; 32 | icon.href = iconURL; 33 | document.head.appendChild(icon); 34 | } 35 | } else { 36 | themeURL = ['https://vpt.cdn.wybenetwork.com', AlterVP.theme, 'panel.css'].join("/"); 37 | } 38 | theme = document.createElement('link'); 39 | theme.type = 'text/css'; 40 | theme.rel = 'stylesheet'; 41 | theme.href = themeURL; 42 | document.head.appendChild(theme); 43 | } 44 | // Credits 45 | if (AlterVP.credits.logo !== undefined) { 46 | script = document.createElement('script') 47 | script.setAttribute('type', 'text/javascript') 48 | script.innerHTML = "window.addEventListener('load',function(){document.getElementById('imgPoweredByCpanel').src=AlterVP.credits.logo})" 49 | document.body.appendChild(script) 50 | } 51 | if (AlterVP.credits.desc !== undefined) { 52 | document.getElementById("txtCpanelVersion").innerHTML = AlterVP.credits.desc; 53 | } 54 | }); -------------------------------------------------------------------------------- /altervp/altervp.min.js: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Created on 14 September 2018 by woxly 3 | * Recreated on 30 August and modified on 03 September 2022 by Anyx 4 | * Last modified on 13 September 2022 by Anyx 5 | * DO NOT REMOVE CREDITS! 6 | * Created for: Wybe Network. 7 | */ 8 | document.addEventListener("DOMContentLoaded",function(){void 0!==AlterVP.title&&(document.title=AlterVP.title),void 0!==AlterVP.protocol&&window.location.protocol.replace(/:/g,"")!==AlterVP.protocol&&(location.protocol=AlterVP.protocol),void 0!==AlterVP.logo&&(document.getElementById("imgLogo").src=AlterVP.logo),void 0!==AlterVP.theme&&void 0!==AlterVP.category&&("lightspace"!==AlterVP.category?(themeURL=["https://vpt.cdn.wybenetwork.com",AlterVP.theme,"styles.css"].join("/"),"normal"==AlterVP.category&&(iconURL=["https://vpt.cdn.wybenetwork.com",AlterVP.theme,"icon_spritemap.css"].join("/"),icon=document.createElement("link"),icon.type="text/css",icon.rel="stylesheet",icon.href=iconURL,document.head.appendChild(icon))):themeURL=["https://vpt.cdn.wybenetwork.com",AlterVP.theme,"panel.css"].join("/"),theme=document.createElement("link"),theme.type="text/css",theme.rel="stylesheet",theme.href=themeURL,document.head.appendChild(theme)),void 0!==AlterVP.credits.logo&&(script=document.createElement("script"),script.setAttribute("type","text/javascript"),script.innerHTML="window.addEventListener('load',function(){document.getElementById('imgPoweredByCpanel').src=AlterVP.credits.logo})",document.body.appendChild(script)),void 0!==AlterVP.credits.desc&&(document.getElementById("txtCpanelVersion").innerHTML=AlterVP.credits.desc)}); -------------------------------------------------------------------------------- /cpanel-logo-to-copyright/cpanel-logo-to-copyright.js: -------------------------------------------------------------------------------- 1 | /* @preserve 2 | * Created at 10 July 2018 by PlanetCloud 3 | * Last modified at 02 November 2018 by PlanetCloud 4 | * DO NOT REMOVE CREDITS! 5 | * Created for: Wybe Network. 6 | */ 7 | document.addEventListener("DOMContentLoaded", function() { 8 | if ("undefined" !== typeof b) { 9 | var a = document.getElementById("lnkPoweredByCpanel"), 10 | d = document.getElementById("txtCpanelVersion"), 11 | c = (new Date).getFullYear(); 12 | b.company_started = Number(b.company_started); 13 | a.href = b.prm_site; 14 | a.target = "_blank"; 15 | a.title = b.company_name; 16 | a.innerHTML = '' + b.company_name +
17 |             ''; 18 | d.innerHTML = b.company_started < c ? "\u00a9 " + b.company_started + "-" + c + " " + b.company_name + "." : "\u00a9 " + c + " " + b.company_name + "." 19 | } 20 | }); -------------------------------------------------------------------------------- /cpanel-logo-to-copyright/cpanel-logo-to-copyright.min.js: -------------------------------------------------------------------------------- 1 | /* @preserve 2 | * Created at 10 July 2018 by PlanetCloud 3 | * Last modified at 02 November 2018 by PlanetCloud 4 | * DO NOT REMOVE CREDITS! 5 | * Created for: Wybe Network. 6 | */ 7 | document.addEventListener("DOMContentLoaded",function(){if("undefined"!=typeof b){var e=document.getElementById("lnkPoweredByCpanel"),n=document.getElementById("txtCpanelVersion"),a=(new Date).getFullYear();b.company_started=Number(b.company_started),e.href=b.prm_site,e.target="_blank",e.title=b.company_name,e.innerHTML=''+b.company_name+'',n.innerHTML=b.company_started Company Name 18 | * company_logo -> Company Logo 19 | * company_started -> Year Company Started Exsisting or Publicablly Announced 20 | * prm_site -> Primary site URL (With HTTP:// or HTTPS://) 21 | 22 | Example : 23 | ``` 24 | var b = { 25 | company_name : "Planet Cloud Hosting", 26 | company_logo : "http://planetcloudhosting.cf/images/logo.png", 27 | company_started : "2017", 28 | prm_site : "http://planetcloudhosting.cf", 29 | } 30 | ``` 31 | 32 | ### Content-Type Header Errors 33 | The RAW option on GitHub can return an incorrect Content-Type header which makes the code not load at all. 34 | To solve this, we need an external service which adds the correct type, like jsDelivr, or our CDN. 35 | 36 | The full code, using jsDelivr: 37 | 38 | ```html 39 | 49 | 50 | ``` 51 | Alternatively, you can use our CDN: 52 | ```html 53 | 63 | 64 | ``` -------------------------------------------------------------------------------- /dropdown-bug-fix/README.md: -------------------------------------------------------------------------------- 1 | # Dropdown Bug Fix 2 | 3 | ## What does it do? 4 | It makes the user options dropdown work in all pages! 5 | 6 | ## Where should I put it? 7 | Put it in the Footer Advert Area (Bottom advert). 8 | The code will not run if you put it elsewhere. It may run in the left advert area, but it will break the sidebar. 9 | 10 | ## How can I install it? 11 | Create a script tag with `src` pointing to `dropdown-bug-fix.js`. 12 | 13 | In case you do not know how to do that or prefer to use a ready code, we have provided it below. 14 | 15 | ### Content-Type Header Errors 16 | The RAW option on GitHub can return an incorrect Content-Type header which makes the code not load at all. 17 | To solve this, we need an external service which adds the correct type, like jsDelivr, or our CDN. 18 | 19 | The full code, using jsDelivr: 20 | ```html 21 | 22 | ``` 23 | Alternatively, you can use our CDN: 24 | ```html 25 | 26 | ``` 27 | ## Changelog 28 | * Created on 06 August 2022 by [Anyx](https://github.com/4yx) -------------------------------------------------------------------------------- /dropdown-bug-fix/dropdown-bug-fix.js: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Created at 06 August 2022 by Anyx. 3 | * DO NOT REMOVE CREDITS! 4 | * Created for: Wybe Network. 5 | */ 6 | check = document.getElementById("main"); 7 | if (check == null) { 8 | dropdown = document.getElementById("btnUserPref"); 9 | dropdown.onclick = function() { 10 | if (dropdown.parentElement.classList.contains("open")) { 11 | dropdown.parentElement.classList.remove("open"); 12 | } else { 13 | dropdown.parentElement.classList.add("open"); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /dropdown-bug-fix/dropdown-bug-fix.min.js: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Created at 06 August 2022 by Anyx. 3 | * DO NOT REMOVE CREDITS! 4 | * Created for: Wybe Network. 5 | */ 6 | check=document.getElementById("main"),null==check&&(dropdown=document.getElementById("btnUserPref"),dropdown.onclick=function(){dropdown.parentElement.classList.contains("open")?dropdown.parentElement.classList.remove("open"):dropdown.parentElement.classList.add("open")}); -------------------------------------------------------------------------------- /element-changer/README.md: -------------------------------------------------------------------------------- 1 | # Element Changer 2 | 3 | ## What does it do? 4 | As the name might suggest, it allows you to modify any VistaPanel widget element! _(Well, aside from the right sidebar ones.)_ 5 | You are able to add, change and remove elements. 6 | 7 | ## Where should I put it? 8 | You can put it anywhere! We recommend avoiding the left advert area, as it will break the sidebar. 9 | 10 | ## How can I install it? 11 | You'll first need to declare an array with the name ``changeElements`` within a script tag. 12 | 13 | To add an element, you will need to create an object with the following properties that we'll analyze afterwards: 14 | ```js 15 | {action: "add", name: "Element name", group: "Group name", link: "#link", icon: "URL to icon", search_text: "words for the search bar divided with spaces"} 16 | ``` 17 | To change an element, you will need to create an object with the following properties that we'll analyze afterwards: 18 | ```js 19 | {action: "modify", name: "Element identifier", attr: "attribute", value: "new value"} 20 | ``` 21 | To remove an element, the object will be structured like this: 22 | ```js 23 | {action: "remove", name: "Element identifier"} 24 | ``` 25 | 26 | ### Properties 27 | 28 | #### Common Properties 29 | The action you wish to perform will be defined in ``action``. There are three actions supported, ``add``, ``modify`` and ``remove``. 30 | If you declare no action in your object the script will assume ``modify`` to be the intended action. 31 | 32 | #### Adding Elements 33 | In ``name``, you'll assign a value that corresponds with the name of the element exactly as you want it to appear on the panel. 34 | 35 | In ``group``, you'll need to enter the name of the group in which you desire to add the new element in. 36 | The names might be different than the ones appearing on the panel, so we are listing them below: 37 | 38 | |How they appear on the panel| What you'll need to enter | 39 | |----------------------------|----------------------------| 40 | | Preferences | preferences | 41 | | Files | files | 42 | | Databases | databases | 43 | | Domains | domains | 44 | | Email | email | 45 | | Metrics | metrics | 46 | | Security | security | 47 | | Software | software | 48 | | Advanced | advanced | 49 | | Softaculous Apps Installer | soft_div | 50 | | Support | support | 51 | 52 | ``link`` contains the URL you wish for your new element to have. 53 | 54 | ``icon`` holds the full URL to the image you wish your new element to have as an icon. 55 | 56 | Finally, you can enter any text in ``search_text`` that will be used for the search utility the panel offers (to locate your element). Words are divided by spaces. 57 | 58 | #### Changing Elements 59 | In `name`, you'll assign an identifier that corresponds with the table below. 60 | Look up the name of the item you want to change _as it appears on the panel_, then assign the **identifier** of said item name to the `name` property. 61 | 62 | | Group | Item name | Identifier | 63 | |-------------|----------------------------|---------------------------| 64 | | preferences | Change Password | change_password | 65 | | preferences | Change Language | change_language | 66 | | preferences | Update Contact Email | contact_information | 67 | | preferences | Getting Started | backup_wizard | 68 | | preferences | Account Upgrades | two_factor_authentication | 69 | | preferences | Account Settings | user_manager | 70 | | files | Online File Manager | file_manager | 71 | | files | Directory Privacy | directory_privacy | 72 | | files | Disk Usage | disk_usage | 73 | | files | FTP Accounts | ftp_accounts | 74 | | files | Free FTP Software | ftp_connections | 75 | | files | Backups | backup | 76 | | databases | phpMyAdmin | php_my_admin | 77 | | databases | MySQL Databases | mysql_databases | 78 | | databases | Remote MySQL | remote_mysql | 79 | | databases | PostgreSQL Databases | postgresql_databases | 80 | | domains | Addon Domains | addon_domains | 81 | | domains | Sub Domains | subdomains | 82 | | domains | Aliases (Parked Domains) | aliases | 83 | | domains | Redirects | redirects | 84 | | email | Email Accounts | accounts | 85 | | email | Forwarders | forwarders | 86 | | email | MX Entry | mx_entry | 87 | | email | SPF Records | advanced_zone_editor | 88 | | email | Webmail | email_filters | 89 | | metrics | Account Statistics | awstats | 90 | | metrics | Error Logs | errors | 91 | | metrics | General PHP Info | php | 92 | | metrics | Access Logs | raw_access | 93 | | security | IP Blocker | ip_blocker | 94 | | security | SSL/TLS | ssl_tls | 95 | | software | SiteBuilder | sitereptile | 96 | | software | Softaculous Apps Installer | softaculous | 97 | | software | SEO Tools | attracta_seotips | 98 | | software | Alter PHP Config | multiphp_configuration | 99 | | software | Select PHP Version | lvephpsel | 100 | | advanced | Cron Jobs | cron_jobs | 101 | | advanced | CNAME Records | simple_zone_editor | 102 | | advanced | Error Pages | error_pages | 103 | | soft_div | Softaculous Apps Installer | soft_div_icons | 104 | | support | Domain Types | cloudflare_performance | 105 | | support | Tutorials | cloudflare_analytics | 106 | | support | Support Forum | attracta_seotools | 107 | | support | Create New Ticket | createticket | 108 | | support | Open Support Tickets | ShowTickets | 109 | | support | Closed Support Tickets | api_shell | 110 | 111 | ##### Modifying Elements 112 | ``attr`` is the attribute you wish to modify. There are two main attributes: 113 | ``itemdesc`` and ``url``. 114 | The first defines the name the element will have on the panel, while the second, as you can tell by the name, defines the URL for it. 115 | 116 | Finally, ``value`` holds the new value of the element you'll be changing, for example if your ``attr`` is ``url``, it would probably contain a value of ``"https://yourdomain.com"``. 117 | 118 | ### Examples 119 | #### Adding Elements 120 | An example that adds an element named ``Custom`` in ``Databases`` linking to ``https://yourdomain.com`` with an image and ``custom`` as its search text can be seen below: 121 | ```js 122 | var changeElements = [ 123 | {name: "Custom", action: "add", group: "databases", link: "https://yourdomain.com", icon: "https://seekicon.com/free-icon-download/database-cloud_1.png", search_text: "custom"} 124 | ]; 125 | ``` 126 | 127 | #### Modifying Elements 128 | An example of the code modifying the name and URL of ``Change Password`` to ``Your Domain`` and ``https://yourdomain.com`` respectively can be seen below: 129 | ```js 130 | var changeElements = [ 131 | {name: "change_password", action: "modify", attr: "itemdesc", value: "Your Domain"}, 132 | {name: "change_password", action: "modify", attr: "url", value: "https://yourdomain.com"} 133 | ]; 134 | 135 | ``` 136 | #### Removing Elements 137 | Likewise, an example of removing ``MX Entry`` and ``CNAME Records`` is provided here: 138 | ```js 139 | var changeElements = [ 140 | {name: "mx_entry", action: "remove"}, // Removes "MX Entry" 141 | {name: "simple_zone_editor", action: "remove"} // Removes "CNAME Records 142 | ]; 143 | ``` 144 | 145 | > **Note** 146 | > Objects are separated by commas, so don't forget to include them when adding a new one. 147 | 148 | ### So where's that script, anyway? 149 | Create a script tag with `src` pointing to `element-changer.js` or ``element-changer.min.js`` for the minified version. 150 | 151 | In case you do not know how to do that or prefer to use a ready code, we have provided it below, along with an explanation as to the reason why GitHub's RAW file output cannot be used. 152 | 153 | ### Content-Type Header Errors 154 | The RAW option on GitHub can return an incorrect Content-Type header which makes the code not load at all. 155 | To solve this, we need an external service which adds the correct type, like jsDelivr, or our CDN. 156 | 157 | The code, using jsDelivr: 158 | ```html 159 | 160 | ``` 161 | 162 | Alternatively, you can use our CDN: 163 | ```html 164 | 165 | ``` 166 | 167 | #### What is all of this? Where is my ready-to-use code? 168 | Please read the Properties section before attempting to make your own modifications. 169 | 170 | We'll provide two ready code examples: 171 | 172 | ##### Example 1: Ability Demonstration 173 | A ready code for adding our custom element from above, modifying the names and URLs of ``SiteBuilder`` and ``Softaculous Apps Installer``, and removing ``Access Logs`` and ``Remote MySQL``. Try it out in your panel (with the script, of course) to be able to better understand the process in adding your own objects. 174 | 175 | The full code utilizing our example and our CDN: 176 | ```html 177 | 190 | 191 | ``` 192 | ##### Example 2: Remove unneeded elements 193 | A ready code for removing all elements that are not needed, usually because the features they describe have been deprecated and are no longer offered or were never offered to begin with. 194 | 195 | The full code utilizing our example and our CDN: 196 | ```html 197 | 212 | 213 | ``` 214 | 215 | ## Changelog 216 | * Created on 15th September 2022 by [Anyx](https://github.com/4yx) 217 | * Modified on 15th September 2022 by [PlanetCloud](https://github.com/PlanetTheCloud) 218 | * Modified on 19th September 2022 by [PlanetCloud](https://github.com/PlanetTheCloud) 219 | * Last modified on 1st May 2022 by [PlanetCloud](https://github.com/PlanetTheCloud) 220 | -------------------------------------------------------------------------------- /element-changer/element-changer.js: -------------------------------------------------------------------------------- 1 | /** @preserve 2 | * Created at 15th September 2022 by Anyx and modified by PlanetCloud. 3 | * Modified at 19th September 2022 by PlanetCloud. 4 | * Modified at 25th September 2022 by PlanetCloud. 5 | * Last modified at 1st May 2023 by PlanetTheCloud (PlanetCloud). 6 | * DO NOT REMOVE CREDITS! 7 | * Created for: Wybe Network. 8 | */ 9 | function indexAppGroups() { 10 | let elementsIndex = [], 11 | groupsIndex = [], 12 | g = i = 0; 13 | PAGE.appGroups.forEach(group => { 14 | group.items.forEach(item => { 15 | if (typeof elementsIndex[item.file] == 'undefined') { 16 | elementsIndex[item.file] = []; 17 | } 18 | elementsIndex[item.file].push({ 19 | group: g, 20 | item: i 21 | }); 22 | i++; 23 | }); 24 | groupsIndex[group.group] = g; 25 | g++; 26 | i = 0; 27 | }); 28 | return { 29 | panelElements: elementsIndex, 30 | groups: groupsIndex 31 | }; 32 | } 33 | 34 | (() => { 35 | if (typeof changeElements == "undefined") { 36 | return console.log("ElementChanger: changeElements variable is not defined. No elements changed."); 37 | } 38 | if (changeElements.length == 0) { 39 | return console.log('ElementChanger: Nothing to modify.'); 40 | } 41 | 42 | // Index changeElements 43 | var toChange = { 44 | // Remove first, then modify, then add 45 | remove: [], 46 | modify: [], 47 | add: [] 48 | }; 49 | changeElements.forEach(e => { 50 | if (typeof e.action == 'undefined') { 51 | e.action = 'modify'; 52 | } 53 | if (!['modify', 'remove', 'add'].includes(e.action)) { 54 | console.log(`ElementChanger: Illegal action ${e.action} specified for the following element:`, e); 55 | return; 56 | } 57 | toChange[e.action].push(e); 58 | }); 59 | 60 | // Remove elements 61 | if (toChange.remove.length > 0) { 62 | let elementsIndex = indexAppGroups().panelElements; 63 | toChange.remove.forEach(r => { 64 | if (typeof elementsIndex[r.name] == 'undefined') { 65 | return console.log(`ElementChanger: Trying to remove element "${r.name}" which does not exist.`) 66 | } 67 | elementsIndex[r.name].forEach(e => { 68 | PAGE.appGroups[e.group].items = PAGE.appGroups[e.group].items.filter(i => i.file != r.name); 69 | }); 70 | }); 71 | } 72 | 73 | // Modify elements 74 | let elementsIndex = indexAppGroups().panelElements; 75 | toChange.modify.forEach(c => { 76 | if (typeof elementsIndex[c.name] == 'undefined') { 77 | return console.log(`ElementChanger: Trying to change element "${c.name}" which does not exist.`); 78 | } 79 | elementsIndex[c.name].forEach(e => { 80 | PAGE.appGroups[e.group].items[e.item][c.attr] = c.value; 81 | }) 82 | }); 83 | 84 | // Add elements 85 | let groupsIndex = indexAppGroups().groups; 86 | var addedElementsIcon = []; 87 | toChange.add.forEach(a => { 88 | if (typeof groupsIndex[a.group] == 'undefined') { 89 | return console.log(`ElementChanger: Trying to add an element to "${a.group}" group which does not exist.`) 90 | } 91 | let file_id = `added_${a.name.replace(/\s+/g, '_')}${Math.floor(Math.random() * 100)}`; 92 | PAGE.appGroups[groupsIndex[a.group]].items.push({ 93 | "file": file_id, 94 | "imgtype": "icon", 95 | "group": a.group, 96 | "itemdesc": a.name, 97 | "url": a.link, 98 | "type": "image", 99 | "height": "48", 100 | "width": "48", 101 | "searchtext": a.search_text ?? "" 102 | }); 103 | addedElementsIcon.push({ 104 | target: `icon-${file_id}`, 105 | icon: a.icon 106 | }); 107 | }); 108 | 109 | // Add icons to added elements 110 | function ElementChanger_AddMissingIcons() { 111 | if (document.getElementById('preferences-group') === null) { 112 | return setTimeout(() => { 113 | ElementChanger_AddMissingIcons(); 114 | }, 100); 115 | } 116 | if (addedElementsIcon.length < 1) { 117 | return; 118 | } 119 | console.log('ElementChanger: Adding icons...'); 120 | addedElementsIcon.forEach(e => { 121 | document.getElementById(e.target).innerHTML = `` 122 | }); 123 | return console.log('ElementChanger: All modifications have been made.'); 124 | } 125 | document.addEventListener("DOMContentLoaded", () => { 126 | ElementChanger_AddMissingIcons(); 127 | }); 128 | 129 | // Done! 130 | if (addedElementsIcon.length < 1) { 131 | return console.log('ElementChanger: All modifications have been made.'); 132 | } 133 | })(); -------------------------------------------------------------------------------- /element-changer/element-changer.min.js: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Created at 15 September 2022 by Anyx and modified by PlanetCloud. 3 | * Modified at 19 September 2022 by PlanetCloud. 4 | * Last modified at 25 September 2022 by PlanetCloud. 5 | * DO NOT REMOVE CREDITS! 6 | * Created for: Wybe Network. 7 | */ 8 | var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.createTemplateTagFirstArg=function(b){return b.raw=b};$jscomp.createTemplateTagFirstArgWithRaw=function(b,c){b.raw=c;return b};function indexAppGroups(){var b=[],c=[],e=i=0;PAGE.appGroups.forEach(function(g){g.items.forEach(function(f){"undefined"==typeof b[f.file]&&(b[f.file]=[]);b[f.file].push({group:e,item:i});i++});c[g.group]=e;e++;i=0});return{panelElements:b,groups:c}} 9 | (function(){function b(){if(null===document.getElementById("preferences-group"))return setTimeout(function(){b()},100);if(!(1>h.length))return console.log("ElementChanger: Adding icons..."),h.forEach(function(a){document.getElementById(a.target).innerHTML=''}),console.log("ElementChanger: All modifications have been made.")}if("undefined"==typeof changeElements)return console.log("ElementChanger: changeElements variable is not defined. No elements changed."); 10 | if(0==changeElements.length)return console.log("ElementChanger: Nothing to modify.");var c={remove:[],modify:[],add:[]};changeElements.forEach(function(a){"undefined"==typeof a.action&&(a.action="modify");["modify","remove","add"].includes(a.action)?c[a.action].push(a):console.log("ElementChanger: Illegal action "+a.action+" specified for the following element:",a)});if(0h.length)return console.log("ElementChanger: All modifications have been made.")})(); -------------------------------------------------------------------------------- /element-changer/tools.element-changer.js: -------------------------------------------------------------------------------- 1 | /** @preserve 2 | * Created at 1st May 2023 by PlanetTheCloud (PlanetCloud). 3 | * DO NOT REMOVE CREDITS! 4 | * Created for: Wybe Network. 5 | */ 6 | 7 | /** 8 | * Generates an array list of PAGE.appGroups 9 | * Items along with it's file and group. 10 | * Handy for updating the documentation when changes were made 11 | * @return object 12 | */ 13 | function associateFileDesc() { 14 | let result = { 15 | group: [], 16 | file: [], 17 | desc: [] 18 | }; 19 | PAGE.appGroups.forEach(group => { 20 | group.items.forEach(item => { 21 | result.group.push(group.group); 22 | result.file.push(item.file); 23 | result.desc.push(item.itemdesc); 24 | }); 25 | }); 26 | return result; 27 | } -------------------------------------------------------------------------------- /menu-item-changer/README.md: -------------------------------------------------------------------------------- 1 | # Menu Item Changer 2 | This script enables you to add, modify and delete items in user navigation dropdown menu. This script make use of default styling so it is compatible with all the themes you can found at [VistaPanel Themes](https://github.com/WybeNetwork/VistaPanel-Themes). Currently, this script only supports removing and modification of default menu items. 3 | 4 | ## Features 5 | - Add new menu item with icon, title and link 6 | - Modify default menu items icon, title or link 7 | - Remove default menu items 8 | - Compatible with all themes available at [VistaPanel Themes](https://github.com/WybeNetwork/VistaPanel-Themes) 9 | - Default Icons (Added by default [Font Awesome](https://fontawesome.com/v4/icons/)) 10 | 11 | ## How to Install? 12 | Add this code in the footer advert area to load the script, 13 | 14 | You can use one of the two options to load script 15 | 16 | ### Our CDN 17 | ```html 18 | 19 | ``` 20 | 21 | ### Manual 22 | Download the latest available version of this script and place it on your website in your desired directory. 23 | 24 | In this code example, I have added the script to the root directory of my website. 25 | ```html 26 | 27 | ``` 28 | 29 | Now instantiate an object with options to add, modify or remove a menu item. 30 | 31 | Example configuration 32 | ```html 33 | 62 | ``` 63 | 64 | You can add new fontawesome icons by loading the stylesheet of fontawesome new version through their CDN and then you can use the unicode of new icons. 65 | 66 | ## Items `array` 67 | Array of objects with different properties 68 | 69 | ### Add Item `Object` 70 | | Properties | Priority | Values | 71 | |-----------------|----------|--------------------------------| 72 | | name `string` | required | 'New Item' | 73 | | url `string` | required | 'https://example.tld/new-item' | 74 | | icon `string` | required | 'f1f2' | 75 | | order `int` | optional | 0 | 76 | | action `string` | required | 'add' | 77 | 78 | 79 | The value for **order** property specifies where that item should be added. If it is not specified then by default the item will be added at the end. 80 | If **0** is specified then element will be added at first position and If **n** (n is any integer) is specified than it will be added after the element at nth position. 81 | 82 | ### Modify Item `Object` 83 | | Properties | Priority | Values | 84 | |------------------|----------|--------------------------------| 85 | | name `string` | required | 'Change Password' | 86 | | newName `string` | Optional | 'New Item Name' | 87 | | url `string` | Optional | 'https://example.tld/new' | 88 | | icon `string` | Optional | 'f1f2' | 89 | | action `string` | required | 'modify' | 90 | 91 | To modify an item at least one of the three options must be modified. 92 | 93 | ### Remove Item `Object` 94 | | Properties | Priority | Values | 95 | |------------------|----------|-------------------| 96 | | name `string` | Optional | 'Change Password' | 97 | | action `string` | required | 'remove' | 98 | 99 | ## Changelog 100 | ```html 101 | Version 1.0.0 | October 19th, 2020 102 | - Initial Release 103 | - Modify default menu items icon, title or link 104 | - Remove default menu items 105 | - Compatible with all themes available at https://github.com/WybeNetwork/VistaPanel-Themes 106 | - Default Icons (available at https://fontawesome.com/v4/icons/) 107 | ``` 108 | 109 | -------------------------------------------------------------------------------- /menu-item-changer/menu-item-changer.js: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Project: Menu Item Changer 3 | * Version: 1.0.0 4 | * Description: Enable you to add, modify or remove menu items 5 | * Author: Wybe Network (https://wybenetwork.com/) 6 | * Created: AA22Dev (October 19th, 2022) 7 | * Docs: https://docs.wybenetwork.com/ 8 | * 9 | * DO NOT REMOVE CREDITS 10 | * */ 11 | 12 | class MenuitemChanger { 13 | #items; 14 | #defaultItems = ['Change Password', 'Change Language', 'Update Contact Email', 'Reset Page Settings']; 15 | 16 | constructor(args) { 17 | this.#items = args; 18 | 19 | document.addEventListener('readystatechange', event => { 20 | if (event.target.readyState === "complete") { 21 | if (this.#items.length === 0) throw "Nothing to add, remove or modify!"; 22 | 23 | Object.entries(this.#items).forEach(([k, val]) => { 24 | if (!val.name) throw "Error: Name value must be specified"; 25 | 26 | const el = document.getElementById('btnUserPref').nextElementSibling; 27 | 28 | if (val.action === 'remove') { 29 | this.#removeItem(val, el); 30 | } else if (val.action === 'add') { 31 | this.#addItem(val, el); 32 | } else if (val.action === 'modify') { 33 | this.#modifyItem(val, el); 34 | } 35 | }); 36 | } 37 | }); 38 | } 39 | 40 | #modifyItem(val, el) { 41 | // text, link, order 42 | const index = this.#defaultItems.findIndex(v => { 43 | return v === val.name; 44 | }); 45 | 46 | if (index === -1) throw "Invalid element name to modify"; 47 | if (!val.url && !val.newName) throw "Options to modify doesn't specified"; 48 | 49 | if (val.url) el.children.item(index).children.item(0).setAttribute('href', val.url); 50 | if (val.newName) el.children.item(index).children.item(0).innerHTML = val.newName; 51 | } 52 | 53 | #addItem(val, el) { 54 | if (!val.icon || !val.url || !val.order) throw "Arguments for adding element are not sufficient"; 55 | 56 | const id = `wn_${val.name.toLowerCase().replace(/ /g,"_")}`; 57 | 58 | const style = document.createElement('style'); 59 | 60 | style.innerHTML = `#${id} #lnkUserPrefChangePwd:before { 61 | content: "\\${val.icon}"!important; 62 | }`; 63 | 64 | document.head.appendChild(style); 65 | 66 | const html = `
  • 67 | ${val.name} 68 |
  • `; 69 | 70 | (el.children.item(val.order)) ? el.children.item(val.order).insertAdjacentHTML('beforebegin', html) : el.insertAdjacentHTML('beforeend', html); 71 | } 72 | 73 | #removeItem(val, el) { 74 | const index = this.#defaultItems.findIndex(v => { 75 | return v === val.name; 76 | }); 77 | 78 | if (index === -1) throw "Invalid name specified"; 79 | 80 | this.#defaultItems.splice(index, 1); 81 | el.children.item(index).remove(); 82 | } 83 | } -------------------------------------------------------------------------------- /menu-item-changer/menu-item-changer.min.js: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Project: Menu Item Changer 3 | * Version: 1.0.0 4 | * Description: Enable you to add, modify or remove menu items 5 | * Author: Wybe Network (https://wybenetwork.com/) 6 | * Created: AA22Dev (October 19th, 2022) 7 | * Docs: https://docs.wybenetwork.com/ 8 | * 9 | * DO NOT REMOVE CREDITS 10 | * */class MenuitemChanger{#a;#b=["Change Password","Change Language","Update Contact Email","Reset Page Settings"];constructor(e){this.#a=e,document.addEventListener("readystatechange",e=>{if("complete"===e.target.readyState){if(0===this.#a.length)throw"Nothing to add, remove or modify!";Object.entries(this.#a).forEach(([e,t])=>{if(!t.name)throw"Error: Name value must be specified";let i=document.getElementById("btnUserPref").nextElementSibling;"remove"===t.action?this.#c(t,i):"add"===t.action?this.#d(t,i):"modify"===t.action&&this.#e(t,i)})}})}#e(e,t){let i=this.#b.findIndex(t=>t===e.name);if(-1===i)throw"Invalid element name to modify";if(!e.url&&!e.newName)throw"Options to modify doesn't specified";e.url&&t.children.item(i).children.item(0).setAttribute("href",e.url),e.newName&&(t.children.item(i).children.item(0).innerHTML=e.newName)}#d(n,r){if(!n.icon||!n.url||!n.order)throw"Arguments for adding element are not sufficient";let a=`wn_${n.name.toLowerCase().replace(/ /g,"_")}`,d=document.createElement("style");d.innerHTML=`#${a} #lnkUserPrefChangePwd:before { 11 | content: "\\${n.icon}"!important; 12 | }`,document.head.appendChild(d);let m=`
  • 13 | ${n.name} 14 |
  • `;r.children.item(n.order)?r.children.item(n.order).insertAdjacentHTML("beforebegin",m):r.insertAdjacentHTML("beforeend",m)}#c(o,s){let l=this.#b.findIndex(e=>e===o.name);if(-1===l)throw"Invalid name specified";this.#b.splice(l,1),s.children.item(l).remove()}} -------------------------------------------------------------------------------- /responsive-domain-search/README.md: -------------------------------------------------------------------------------- 1 | # Responsive Domain Search 2 | 3 | ## What does it do? 4 | It makes the VistaPanel search form responsive, so that it does not break the vP theme(s). 5 | 6 | ## Where should I put it? 7 | Put it in the Header Advert Area (IMPORTANT). 8 | Due to [this issue](https://github.com/VPTOfficial/VistaPanel-Customizations/issues/4) reported by [AA22Dev](https://github.com/aa22dev), the code doesn't seem to run properly if you put it elsewhere. Thanks for reporting it. 9 | 10 | ## How can I install it? 11 | Create a script tag with `src` pointing to `responsive-domain-search.js` or `responsive-domain-search.min.js` for the minified version. 12 | 13 | In case you do not know how to do that or are too lazy to do it, we have provided a ready code below. 14 | 15 | ### How to initialize an affiliate code into the search form? 16 | A variable "affiliate code" can be defined to put your own affiliate code on the domain search, but, according to iFastNet, this will not give you any money. 17 | 18 | Variable: 19 | * affCode -> 5 digit affiliate code. 20 | 21 | **If the variable is not declared, an affiliate code for my account (PlanetCloud) will be used.** 22 | **In case this method does actually pay money, the money will go into my account and I will appreciate it as a donation :)** 23 | 24 | ### Content-Type Header Errors 25 | The RAW option on GitHub can return an incorrect Content-Type header which makes the code not load at all. 26 | To solve this, we need an external service which adds the correct type, like jsDelivr, or our CDN. 27 | 28 | The full code, using jsDelivr: 29 | ```html 30 | 35 | 36 | ``` 37 | Alternatively, you can use our CDN: 38 | ```html 39 | 44 | 45 | ``` 46 | Do not forget to remove the comment lines symbols (``/* OPTIONAL``and ``*/``) if you want your affiliate code to work. 47 | ## Changelog 48 | * Created on 10 July 2018 by [PlanetCloud](https://github.com/PlanetTheCloud) 49 | * Modified on 27 July 2018 by Christine (Cyrl) 50 | * Modified on 25 August 2018 by [Anyx](https://github.com/4yx) 51 | * Modified on 28 September 2018 by [AA22Dev](https://github.com/aa22dev) and [Anyx](https://github.com/4yx) 52 | * Modified on 30 September 2018 by [PlanetCloud](https://github.com/PlanetTheCloud) 53 | * Modified on 22 November 2018 by [Anyx](https://github.com/4yx) 54 | * Last modified on 06 August 2022 by [Anyx](https://github.com/4yx) -------------------------------------------------------------------------------- /responsive-domain-search/responsive-domain-search.js: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Created at 10 July and modified at 02 November 2018 by PlanetCloud. 3 | * Modified at 16 March 2019 by Dog2puppy. 4 | * Last modified at 06 August 2022 by Anyx. 5 | * DO NOT REMOVE CREDITS! 6 | * Created for: Wybe Network. 7 | */ 8 | document.addEventListener("DOMContentLoaded", function() { 9 | if ("undefined" == typeof affCode) affCode = "25147"; 10 | (function(b, a) { 11 | for (var c = 0; c < b.length; c++) a(b[c]) 12 | })(document.querySelectorAll('form[action^="https://ifastnet.com/portal/domainchecker.php"]'), function(b) { 13 | widget = b.parentElement; 14 | form = document.createElement("form"); 15 | form.setAttribute("class", "form-inline"); 16 | form.setAttribute("target", "_blank"); 17 | form.setAttribute("action", "https://ifastnet.com/portal/domainchecker.php?aff=" + affCode); 18 | form.setAttribute("method", "post"); 19 | form.innerHTML = '
    '; 20 | col = document.createElement("div"); 21 | col.setAttribute("class", "col-sm-12"); 22 | col.appendChild(form); 23 | row = document.createElement("div"); 24 | row.setAttribute("class", "row"); 25 | row.appendChild(col); 26 | widget.innerHTML = ""; 27 | widget.appendChild(row) 28 | }) 29 | }); -------------------------------------------------------------------------------- /responsive-domain-search/responsive-domain-search.min.js: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Created at 10 July and modified at 02 November 2018 by PlanetCloud. 3 | * Modified at 16 March 2019 by Dog2puppy. 4 | * Last modified at 06 August 2022 by Anyx. 5 | * DO NOT REMOVE CREDITS! 6 | * Created for: Wybe Network. 7 | */ 8 | document.addEventListener("DOMContentLoaded",function(){"undefined"==typeof affCode&&(affCode="25147"),function(o,t){for(var e=0;e
    ',col=document.createElement("div"),col.setAttribute("class","col-sm-12"),col.appendChild(form),row=document.createElement("div"),row.setAttribute("class","row"),row.appendChild(col),widget.innerHTML="",widget.appendChild(row)})}); -------------------------------------------------------------------------------- /sidebar-bug-fix/README.md: -------------------------------------------------------------------------------- 1 | # Sidebar Bug Fix 2 | 3 | ## What does it do? 4 | It makes the sidebar work in all pages! 5 | The sidebar wasn't being loaded correctly in other pages on mobile, which this script now fixes. 6 | 7 | ## Where should I put it? 8 | Put it in the Footer Advert Area (Bottom advert). 9 | The code will not run if you put it elsewhere. It may run in the left advert area, but it will break the sidebar. 10 | 11 | ## How can I install it? 12 | Create a script tag with `src` pointing to `sidebar-bug-fix.js` or `sidebar-bug-fix.min.js` for the minified version. 13 | 14 | In case you do not know how to do that or prefer to use a ready code, we have provided it below. 15 | 16 | ### Content-Type Header Errors 17 | The RAW option on GitHub can return an incorrect Content-Type header which makes the code not load at all. 18 | To solve this, we need an external service which adds the correct type, like jsDelivr, or our CDN. 19 | 20 | The full code, using jsDelivr: 21 | ```html 22 | 23 | ``` 24 | Alternatively, you can use our CDN: 25 | ```html 26 | 27 | ``` 28 | ## Changelog 29 | * Created on 15 August 2022 by [Anyx](https://github.com/4yx) -------------------------------------------------------------------------------- /sidebar-bug-fix/sidebar-bug-fix.js: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Created at 15 August 2022 by Anyx. 3 | * DO NOT REMOVE CREDITS! 4 | * Created for: Wybe Network. 5 | */ 6 | check = document.getElementById("main"); 7 | if (check == null) { 8 | sidebar = document.getElementById("sidebar"); 9 | sidebar.classList.add("ng-scope"); 10 | button = document.getElementById("btnSideBarToggle") 11 | button.onclick = function() { 12 | if (sidebar.classList.contains("active")) { 13 | sidebar.classList.remove("active"); 14 | } else { 15 | sidebar.classList.add("active"); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /sidebar-bug-fix/sidebar-bug-fix.min.js: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Created at 15 August 2022 by Anyx. 3 | * DO NOT REMOVE CREDITS! 4 | * Created for: Wybe Network. 5 | */ 6 | check=document.getElementById("main"),null==check&&(sidebar=document.getElementById("sidebar"),sidebar.classList.add("ng-scope"),button=document.getElementById("btnSideBarToggle"),button.onclick=function(){sidebar.classList.contains("active")?sidebar.classList.remove("active"):sidebar.classList.add("active")}); -------------------------------------------------------------------------------- /theme-switcher/readme.md: -------------------------------------------------------------------------------- 1 | # Theme Switcher 2 | 3 | ## What does it do? 4 | As the name suggests, it allows you to add vPanel themes, with an option for your user to switch between different ones. 5 | 6 | ## Features 7 | - Set a default theme 8 | - Use custom domain or our CDN for themes (Supports Normal, Special & Lite Themes) 9 | - Display in one of the two places (Footer OR User navbar) 10 | - Uses cookies to keep the user choice saved 11 | 12 | ## What Normal, Special & Lite Types Mean? 13 | **Normal themes** in our themes repository have two stylesheets `styles.css` & `icon_spritemap.css` 14 | 15 | **Lite & Special themes** have only one file. For **lite themes** the name of file is `styles.css` and for **Special themes** the name of file is `panel.css` 16 | 17 | ## How to install? 18 | First load the script in the footer advert area. 19 | 20 | You can use one of the two options for installing this script on your vPanel. 21 | 22 | ### Our CDN 23 | ```javascript 24 | 25 | ``` 26 | 27 | ### Manual 28 | Download the latest available version of this script and put it on your website. 29 | E.g., I place `theme-switcher.min.js` file in my root folder, then I'll add it like this: 30 | ```javascript 31 | 32 | ``` 33 | 34 | After that we must setup the script. 35 | 36 | Now, we will need to make an object named `wnThemeSwitcher`. 37 | 38 | Let's say I want `dark-discord` theme as default theme and allow users to switch between themes which are `gradient-blue (Normal Theme), light-lite (Lite Theme), lightspace-blue (Special Theme)`. You can check the type of any theme in our documentation at https://docs.wybenetwork.com/vistapanel-themes/#/themes-name 39 | 40 | Example Configuration: 41 | ```javascript 42 | 73 | ``` 74 | 75 | ## Options 76 | | Properties | Priority | Values | 77 | |---------------|------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 78 | | themeList | required | [
        {
            dir: 'theme-dirname',
            title: 'Theme Name',
            type: 'theme type'
        }
    ] | 79 | | options | optional | {
        baseURL: 'https://example.tld/'
        position: 'bottom'
        default: {
            dir: 'theme-dirname'
            type: 'theme type'
        }
    } | 80 | 81 | ## Properties 82 | ### themeList `(array), Required` 83 | 84 | check https://docs.wybenetwork.com/vistapanel-themes/#/themes-name for theme directory names and their types. 85 | 86 | #### dir `(Object)` 87 | Directory name of theme you want to add in theme selector options. 88 | 89 | #### title `(string)` 90 | Title can be any name you want to show to user on frontend. 91 | 92 | #### type `(string)` 93 | Type must be the type of the theme you are allowing user to choose. 94 | List of themes categorized into different types can be found at https://docs.wybenetwork.com/vistapanel-themes/#/themes-name 95 | 96 | ### options `(Object), Optional` 97 | These options are optional, if you don't set them then default one will be used. 98 | 99 | #### baseURL `(String)` 100 | By default it is pointing towards our CDN. You can use this option to serve themes from your custom domain. 101 | 102 | #### position `(String)` 103 | By default it is set to `bottom`. You can use this option to change the location of theme switcher. Only two values are supported 104 | `usernav` & `bottom`. 105 | 106 | - `usernav`, if position option is set to this value then theme switcher will be shown in user nav menu. 107 | - `bottom`, if position option is set to this value then theme switcher will be shown in footer area. 108 | 109 | #### default `(Object)` 110 | Only two properties should be provided for this object to set the default theme. 111 | 112 | ##### dir `(String)` 113 | Directory name of the theme you want to set as default. 114 | 115 | ##### type `(String)` 116 | The value set for this option should be the type of the theme. 117 | 118 | ## Changelog 119 | ```html 120 | Version 2.0.3 | October 16th, 2022 121 | - Bugs Fixes 122 | - Code Improved 123 | - Switched from Cookies to Local Storage 124 | - Added option for switching back to default theme 125 | ``` 126 | ```html 127 | Version 2.0.2 | October 15th, 2022 128 | - Code Optimization (Thanks to PlanetCloud for Suggestions) 129 | - Bugs Fixes 130 | ``` 131 | ```html 132 | Version 2.0.1 | October 15th, 2022 133 | - Code Optimization (Thanks to PlanetCloud for Suggestions) 134 | ``` 135 | ```html 136 | Version 2.0.0 | October 14th, 2022 137 | - Complete Re-write by AA22Dev 138 | - Added support for multiple positions 139 | - Improved support for themes 140 | - Added support for default theme. 141 | ``` 142 | 143 | ```html 144 | Version 1.0.1 | June 23rd, 2021 145 | - Bugs fixes by AA22Dev 146 | ``` 147 | 148 | ```html 149 | Version 1.0.0 | December 29th, 2018 150 | - Initial release by RanaKHAS 151 | ``` -------------------------------------------------------------------------------- /theme-switcher/theme-switcher.js: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Project: Theme Switcher 3 | * Version: 2.0.3 4 | * Description: Allows you to add an option in your MyOwnFreeHost vPanel to allow users to switch to any theme that they want 5 | * Author: Wybe Network (https://wybenetwork.com/) 6 | * Created: AA22Dev (October 14th, 2022) 7 | * Updated: AA22Dev (October 16th, 2022) 8 | * Thanks to PlanetCloud for Code Optimization tips 9 | * Docs: https://docs.wybenetwork.com/ 10 | * 11 | * DO NOT REMOVE CREDITS 12 | * */ 13 | 14 | class ThemeSwitcher { 15 | #position; 16 | #baseURL; 17 | #themeList; 18 | #defaultThemeName; 19 | curTheme = ''; 20 | 21 | constructor(themeList, args={}) { 22 | this.#themeList = themeList; 23 | this.#defaultThemeName = (args.default) ? `${args.default.dir}___${args.default.type}` : null; 24 | this.#position = args.position ?? 'bottom'; 25 | this.#baseURL = args.baseURL ?? 'https://vpt.cdn.wybenetwork.com/'; 26 | 27 | const cookie = localStorage.getItem("wnCurTheme"); 28 | 29 | this.curTheme = cookie ?? 'Default'; 30 | if (cookie || args.default) this.setActiveStyle((args.default && !cookie) ? this.#defaultThemeName : this.curTheme); 31 | 32 | document.addEventListener('readystatechange', event => { 33 | if (event.target.readyState === "complete") this.insertElement(); 34 | }); 35 | } 36 | 37 | #insertBottom() { 38 | let el = `
    `; 47 | document.getElementById("content").insertAdjacentHTML('beforeend', el); 48 | } 49 | 50 | #insertUserNav() { 51 | const style = document.createElement('style'); 52 | style.innerHTML = `#wnThemeSwitcher #lnkUserPrefChangePwd:before { 53 | content: "\\f1fc"!important; 54 | }`; 55 | document.head.appendChild(style); 56 | const el = document.getElementById('lnkUserPrefChangeLang').parentElement; 57 | const newEl = document.createElement('li'); 58 | newEl.setAttribute('id', 'wnThemeSwitcher') 59 | const newSub = document.createElement('a'); 60 | newSub.setAttribute('id', 'lnkUserPrefChangePwd'); 61 | newSub.setAttribute('href', '#'); 62 | newSub.setAttribute('onclick', `wnThemeSwitcher.themeOptions();`); 63 | newSub.innerHTML = 'Change Theme'; 64 | newEl.appendChild(newSub); 65 | el.parentNode.insertBefore(newEl, el.nextSibling); 66 | } 67 | 68 | themeOptions() { 69 | const el = document.getElementById('lnkUserPrefChangeLang').parentElement.parentElement; 70 | const newEl = document.createElement('ul'); 71 | newEl.setAttribute('id', 'wnThemeSwitcherOptions'); 72 | newEl.setAttribute('class', 'dropdown-menu dropdown-menu-right'); 73 | newEl.setAttribute('style', 'display: block;'); 74 | let html = ''; 75 | html += `
  • Default
  • `; 76 | this.#themeList.forEach((val) => { 77 | html += `
  • ${val.title}
  • `; 78 | }); 79 | newEl.innerHTML = html; 80 | el.parentNode.insertBefore(newEl, el.nextSibling); 81 | } 82 | 83 | insertElement() { 84 | (this.#position === 'bottom') ? this.#insertBottom() 85 | : (this.#position === 'usernav') ? this.#insertUserNav() : ''; 86 | } 87 | 88 | setActiveStyle(value) { 89 | const cookie = localStorage.getItem("wnCurTheme"); 90 | 91 | if (cookie) { 92 | try { 93 | document.getElementById(cookie).remove(); 94 | document.getElementById(cookie + '___icon').remove(); 95 | } catch (e) { 96 | console.log(e); 97 | } 98 | } 99 | 100 | if (this.#position === 'usernav') { 101 | try { 102 | document.getElementById('wnThemeSwitcherOptions').remove(); 103 | } catch(e) { 104 | console.log(e); 105 | } 106 | } 107 | 108 | if (value === 'default___normal') { 109 | localStorage.removeItem("wnCurTheme"); 110 | return; 111 | } 112 | 113 | const val = value.split('___'); 114 | const dir = val[0]; 115 | const type = val[1]; 116 | 117 | const theme = `` 118 | + `${(type === 'normal') ? `` : ''}` 119 | document.head.insertAdjacentHTML('beforeend', theme); 120 | 121 | localStorage.setItem("wnCurTheme", value); 122 | } 123 | } -------------------------------------------------------------------------------- /theme-switcher/theme-switcher.min.js: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Project: Theme Switcher 3 | * Version: 2.0.3 4 | * Description: Allows you to add an option in your MyOwnFreeHost vPanel to allow users to switch to any theme that they want 5 | * Author: Wybe Network (https://wybenetwork.com/) 6 | * Created: AA22Dev (October 14th, 2022) 7 | * Updated: AA22Dev (October 16th, 2022) 8 | * Thanks to PlanetCloud for Code Optimization tips 9 | * Docs: https://docs.wybenetwork.com/ 10 | * 11 | * DO NOT REMOVE CREDITS 12 | * */ class ThemeSwitcher{#a;#b;#c;#d;curTheme="";constructor(e,t={}){this.#c=e,this.#d=t.default?`${t.default.dir}___${t.default.type}`:null,this.#a=t.position??"bottom",this.#b=t.baseURL??"https://vpt.cdn.wybenetwork.com/";let i=localStorage.getItem("wnCurTheme");this.curTheme=i??"Default",(i||t.default)&&this.setActiveStyle(t.default&&!i?this.#d:this.curTheme),document.addEventListener("readystatechange",e=>{"complete"===e.target.readyState&&this.insertElement()})}#e(){let e='
    ",document.getElementById("content").insertAdjacentHTML("beforeend",e)}#f(){let t=document.createElement("style");t.innerHTML=`#wnThemeSwitcher #lnkUserPrefChangePwd:before { 13 | content: "\\f1fc"!important; 14 | }`,document.head.appendChild(t);let i=document.getElementById("lnkUserPrefChangeLang").parentElement,n=document.createElement("li");n.setAttribute("id","wnThemeSwitcher");let s=document.createElement("a");s.setAttribute("id","lnkUserPrefChangePwd"),s.setAttribute("href","#"),s.setAttribute("onclick","wnThemeSwitcher.themeOptions();"),s.innerHTML="Change Theme",n.appendChild(s),i.parentNode.insertBefore(n,i.nextSibling)}themeOptions(){let e=document.getElementById("lnkUserPrefChangeLang").parentElement.parentElement,t=document.createElement("ul");t.setAttribute("id","wnThemeSwitcherOptions"),t.setAttribute("class","dropdown-menu dropdown-menu-right"),t.setAttribute("style","display: block;");let i="";i+=`
  • Default
  • `,this.#c.forEach(e=>{i+=`
  • ${e.title}
  • `}),t.innerHTML=i,e.parentNode.insertBefore(t,e.nextSibling)}insertElement(){"bottom"===this.#a?this.#e():"usernav"===this.#a&&this.#f()}setActiveStyle(e){let t=localStorage.getItem("wnCurTheme");if(t)try{document.getElementById(t).remove(),document.getElementById(t+"___icon").remove()}catch(i){console.log(i)}if("usernav"===this.#a)try{document.getElementById("wnThemeSwitcherOptions").remove()}catch(n){console.log(n)}if("default___normal"===e){localStorage.removeItem("wnCurTheme");return}let s=e.split("___"),r=s[0],l=s[1],h=`${"normal"===l?``:""}`;document.head.insertAdjacentHTML("beforeend",h),localStorage.setItem("wnCurTheme",e)}} -------------------------------------------------------------------------------- /translations/README_el.md: -------------------------------------------------------------------------------- 1 | # Τροποποιήσεις του VistaPanel (VistaPanel Scripts) 2 | [![Διαθέσιμο στα Αγγλικά](https://img.shields.io/badge/ΔΙΑΘΕΣΙΜΟ%20ΣΤΑ-ΑΓΓΛΙΚΑ-red.svg?longcache=true&style=for-the-badge&colorA=2abbea)](../README.md) 3 | 4 | **Το αποθετήριο περιέχει τροποποιήσεις JS και CSS για την εξατομίκευση του VistaPanel.** 5 | 6 | **ΠΡΕΠΕΙ** να διαβάσετε και να τηρήσετε τους όρους χρήσης προτού χρησιμοποιήσετε κάτι που περιλαμβάνεται εδώ. 7 | Δημιουργήθηκε από το Wybe Network για την κοινότητα MOFH. 8 | 9 | Όλα είναι **ΔΩΡΕΑΝ και ΕΛΕΥΘΕΡΑ** αρκεί να τηρείτε τους [όρους χρήσης](LICENSE.md). 10 | 11 | Ζητήστε άδεια για την αφαίρεση των credits στο [Discord](https://discord.gg/TCspBav). 12 | 13 | # Υπάρχει κάτι που δεν λειτουργεί; 14 | Παρακαλώ δείτε στην καρτέλα Issues τι δεν λειτουργεί σωστά ή και καθόλου. 15 | 16 | Αν βρείτε κάποιο πρόβλημα και μπορείτε να το φτιάξετε, υποβάλετε ένα PR και θα το δούμε. Αν είναι καλό, θα το ενσωματώσουμε. 17 | 18 | # Πώς να χρησιμοποιήσω τα script εδώ; 19 | Πηγαίντε στον φάκελο του κάθε script και βρείτε αυτό που θέλετε να χρησιμοποιήσετε. Εκεί θα βρείτε οδηγίες (μέχρι στιγμής μόνο στα Αγγλικά). 20 | 21 | Διαβάστε τις οδηγίες πρώτα, και αφού τις καταλάβετε 22 | κάντε χρήση του jsDelivr / του CDN μας με τη μέθοδο που περιγράφεται στο άρθρο ή 23 | κατεβάστε το αρχείο και ανεβάστε το στο site / CDN σας. 24 | 25 | Το CDN μας είναι διαθέσιμο στο https://vpc.cdn.wybenetwork.com/{scriptname}/{scriptfilename.js}. 26 | 27 | # Οδηγίες 28 | 29 | Μπορείτε να βρείτε αναλυτικές οδηγίες στο https://docs.wybenetwork.com **(ΜΟΝΟ ΑΓΓΛΙΚΑ)**. 30 | 31 | # Πνευματικά δικαιώματα 32 | Copyright 2019-2023 © Wybe Network. Με επιφύλαξη παντός δικαιώματος, δείτε την [άδεια χρήσης](../LICENSE.md) για περισσότερα. -------------------------------------------------------------------------------- /vpanel-alerts/README.md: -------------------------------------------------------------------------------- 1 | # vPanel Alerts 2 | Alert system for MyOwnFreeHost users to send notifications or alerts with clickable action to users who are logged into vPanel. This system is compatible with all of the [vPanel Themes](https://github.com/WybeNetwork/VistaPanel-Themes) and also adds some extra CSS. 3 | 4 | ## Features 5 | - Send alerts to logged-in users 6 | - Set delay in milliseconds to display alert after that delay 7 | - Set interval in milliseconds to automatically close alert after that interval 8 | - Display only once to each user 9 | - Set custom icon, title and description for alert 10 | - Close button to close the alert 11 | 12 | ## How to Install? 13 | Add this code in the footer advert area to load the script. 14 | 15 | You can use one of the two options: 16 | 17 | #### Our CDN 18 | ```js 19 | 20 | ``` 21 | #### Manual 22 | Download the latest available version of this script and place it on your website in your desired directory. 23 | 24 | In this code example, I have added the script to the root directory of my website. 25 | ```js 26 | 27 | ``` 28 | Now instantiate an object as `wnAlerts` with options to generate an alert. 29 | 30 | Example configuration 31 | ```html 32 | 52 | ``` 53 | ### Options `(Object)` 54 | | Properties | Priority | Values | 55 | |-----------------|------------|---------------------------------------------------------------| 56 | | id `string` | optional | id: '123'
    `(by default 0 is used)` | 57 | | title `string` | required | title: 'alert title' | 58 | | icon `string` | required | icon: 'https://example.tld/alert-icon.png' | 59 | | desc `string` | required | desc: 'alert content' | 60 | | url `string` | optional | url: 'https://example.tld/action-on-alert-click' | 61 | | user `array` | optional | user: ['prefx_xxxxxx', 'prefx_xxxxx2']
    `default is none` | 62 | | delay `int` | optional | delay: 1000
    ```Delay in ms (default is 0)``` | 63 | | interval `int` | optional | interval: 3000
    ```Interval in ms (default is none)``` | 64 | 65 | > **Note**: 66 | > You must use different IDs so that different notifications are generated.** 67 | 68 | ## Changelog 69 | ```html 70 | Version 1.0.2 | October 30th, 2022 71 | - Deprecated "Display to limited number of users (by list of username)" as it could be a security risk 72 | - Fixed Bugs 73 | ``` 74 | 75 | ```html 76 | Version 1.0.1 | October 28th, 2022 77 | - Complete Re-write of Old Version 78 | - Removed Usage of Web Notification API and Shifted to Alerts system 79 | - Send alerts to logged-in users 80 | - Set delay in milliseconds to display alert after that delay 81 | - Set interval in milliseconds to automatically close alert after that interval 82 | - Display only once to each user 83 | - Display to limited number of users (by list of username) 84 | - Set custom icon, title and description for alert 85 | - Close button to close the alert 86 | ``` 87 | ```html 88 | Version 1.0.0 | October 16th, 2022 89 | - Initial Release 90 | - Push notifications to logged-in users 91 | - Set interval to automatically close notification 92 | - Show new notification for only once to each logged-in user 93 | ``` -------------------------------------------------------------------------------- /vpanel-alerts/vpanel-alerts.js: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Project: vPanel Alerts (Previously vPanel Notifications) 3 | * Version: 1.0.1 4 | * Description: Allows you to show alerts to logged in users on vPanel 5 | * Author: Wybe Network (https://wybenetwork.com/) 6 | * Created: AA22Dev (October 16th, 2022) 7 | * Updated: AA22Dev (October 28th, 2022) 8 | * Thanks to PlanetCloud for Suggestions & code for storing multiple ids in one localstorage item 9 | * Docs: https://docs.wybenetwork.com/ 10 | * DO NOT REMOVE CREDITS 11 | * */ 12 | 13 | class vPanelAlerts { 14 | #alert; 15 | 16 | constructor(args=[]) { 17 | this.#alert = args; 18 | this.#addStyle(); 19 | this.#showAlert(); 20 | } 21 | 22 | #addStyle() { 23 | const style = document.createElement('style'); 24 | style.innerHTML = ` 25 | #wnAlerts { 26 | z-index: 99999; 27 | position: fixed; 28 | top: 64px; 29 | right: 16px; 30 | } 31 | .wnAlert .panel { 32 | width: 250px; 33 | padding: 15px; 34 | box-shadow: 2px 5px 5px #00000017; 35 | border-radius: 0; 36 | transform: translateX(200%); 37 | transition: .5s ease-in-out; 38 | } 39 | .wnAlert .wnContainer { 40 | display: flex; 41 | } 42 | .wnAlert h3 { 43 | margin-top: 0; 44 | } 45 | .wnAlert p { 46 | margin-bottom: 0; 47 | } 48 | .wnAlert .wnContent { 49 | margin-left: 10px; 50 | } 51 | .wnAlert .wnIcon { 52 | align-self: center; 53 | margin-right: 3px; 54 | } 55 | .wnAlert .wnIcon img { 56 | height: 35px; 57 | width: 35px; 58 | } 59 | .wnAlert .wnClose { 60 | position: absolute; 61 | right: 15px; 62 | cursor: pointer; 63 | } 64 | `; 65 | document.head.appendChild(style); 66 | } 67 | 68 | #autoRemoveAlert() { 69 | this.#alert.forEach((v) => { 70 | if (v.interval) { 71 | setTimeout(() => { 72 | this.removeAlert(`wnalert_${v.id}`); 73 | }, v.interval); 74 | } 75 | }); 76 | } 77 | 78 | #showAlert() { 79 | const el = document.createElement('div'); 80 | el.id = 'wnAlerts'; 81 | document.body.insertAdjacentElement('beforeend', el); 82 | const al = document.getElementById('wnAlerts'); 83 | let alID = localStorage.getItem('wnAlerts') ?? ''; 84 | const al_id = (alID) ? alID.split('|') : ''; 85 | this.#alert.forEach((v) => { 86 | if (((al_id) ? !al_id.includes(v.id) : 1)) { 87 | const html = ` 88 |
    89 |
    90 |
    91 |
    92 | ${v.title} 93 |
    94 |
    95 |

    ${v.title}

    96 |

    ${v.desc}

    97 |
    98 |
    99 | 100 |
    101 |
    102 |
    103 |
    104 | `; 105 | alID += `${v.id}|`; 106 | setTimeout(() => { 107 | al.insertAdjacentHTML('afterbegin', html); 108 | }, (v.delay) ?? 0); 109 | localStorage.setItem('wnAlerts', alID); 110 | } 111 | }); 112 | this.#autoRemoveAlert(); 113 | } 114 | removeAlert(id) { 115 | const el = document.getElementById(id).childNodes[1]; 116 | el.removeAttribute('style'); 117 | setTimeout(() => { 118 | el.remove(); 119 | }, 500); 120 | } 121 | } -------------------------------------------------------------------------------- /vpanel-alerts/vpanel-alerts.min.js: -------------------------------------------------------------------------------- 1 | /*! @preserve 2 | * Project: vPanel Alerts (Previously vPanel Notifications) 3 | * Version: 1.0.1 4 | * Description: Allows you to show alerts to logged in users on vPanel 5 | * Author: Wybe Network (https://wybenetwork.com/) 6 | * Created: AA22Dev (October 16th, 2022) 7 | * Updated: AA22Dev (October 28th, 2022) 8 | * Thanks to PlanetCloud for Suggestions & code for storing multiple ids in one localstorage item 9 | * Docs: https://docs.wybenetwork.com/ 10 | * DO NOT REMOVE CREDITS 11 | * */ class vPanelAlerts{#a;constructor(e=[]){this.#a=e,this.#b(),this.#c()}#b(){let e=document.createElement("style");e.innerHTML=`#wnAlerts{z-index:99999;position:fixed;top:64px;right:16px}.wnAlert .panel{width:250px;padding:15px;box-shadow:2px 5px 5px #00000017;border-radius:0;transform:translateX(200%);transition:.5s ease-in-out}.wnAlert .wnContainer{display:flex}.wnAlert h3{margin-top:0}.wnAlert p{margin-bottom:0}.wnAlert .wnContent{margin-left:10px}.wnAlert .wnIcon{align-self:center;margin-right:3px}.wnAlert .wnIcon img{height:35px;width:35px}.wnAlert .wnClose{position:absolute;right:15px;cursor:pointer}`,document.head.appendChild(e)}#d(){this.#a.forEach(e=>{e.interval&&setTimeout(()=>{this.removeAlert(`wnalert_${e.id}`)},e.interval)})}#c(){let t=document.createElement("div");t.id="wnAlerts",document.body.insertAdjacentElement("beforeend",t);let n=document.getElementById("wnAlerts"),l=localStorage.getItem("wnAlerts")??"",r=l?l.split("|"):"";this.#a.forEach(e=>{if((r?!r.includes(e.id):1)){let t=`
    ${e.title}

    ${e.title}

    ${e.desc}

    `;l+=`${e.id}|`,setTimeout(()=>{n.insertAdjacentHTML("afterbegin",t)},e.delay??0),localStorage.setItem("wnAlerts",l)}}),this.#d()}removeAlert(e){let t=document.getElementById(e).childNodes[1];t.removeAttribute("style"),setTimeout(()=>{t.remove()},500)}} --------------------------------------------------------------------------------