[GH-ISSUE #1417] Disable Save button until user fills ssid, pass, and also custom input fields #1210

Open
opened 2026-02-28 01:29:03 +03:00 by kerem · 9 comments
Owner

Originally created by @kargarisaac on GitHub (May 13, 2022).
Original GitHub issue: https://github.com/tzapu/WiFiManager/issues/1417

Hi,

Is it possible to disable the save button until user fills the input fields? I have added also some custom input fields using:

WiFiManagerParameter email_text_box("email", "Enter your email here", "", 50);
wm.addParameter(&email_text_box);
Originally created by @kargarisaac on GitHub (May 13, 2022). Original GitHub issue: https://github.com/tzapu/WiFiManager/issues/1417 Hi, Is it possible to disable the save button until user fills the input fields? I have added also some custom input fields using: ```C++ WiFiManagerParameter email_text_box("email", "Enter your email here", "", 50); wm.addParameter(&email_text_box); ```
Author
Owner

@kargarisaac commented on GitHub (May 14, 2022):

I tried to modify the strings_en.h file like this:

const char HTTP_SCRIPT[]           PROGMEM = "<script>function c(l){"
"document.getElementById('s').value=l.getAttribute('data-ssid')||l.innerText||l.textContent;"
"p = l.nextElementSibling.classList.contains('l');"
"document.getElementById('p').disabled = !p;"
"if(p)document.getElementById('p').focus();let inputs = document.querySelectorAll('input');"
"let buttonSend = document.getElementById('save-btn');"
"let inputValidator = {'s': false,'p': false, 'email': flase};"
"inputs.forEach((input) => {input.addEventListener('input', () => {let name = event.target.getAttribute('name');"
"if (event.target.value.length > 0) {inputValidator[name] = true;} else {inputValidator[name] = false;};"
"let allTrue = Object.keys(inputValidator).every((item) => {return inputValidator[item] === true});"
"if (allTrue) {buttonSend.disabled = false;} else {buttonSend.disabled = true;}})})}</script>"; // @todo add button states, disable on click , show ack , spinner etc

.
.
.

const char HTTP_FORM_END[]         PROGMEM = "<br/><br/><button type='submit' id='save-btn' disabled>Save</button></form>";

But I cannot see any changes there. Also, I tried to just disable the save button using html but I don't see any change there too. around lines 70-80 in strings_en.h file:

const char HTTP_FORM_END[]         PROGMEM = "<br/><br/><button disabled>Save</button></form>";

Am I missing sth?

<!-- gh-comment-id:1126717743 --> @kargarisaac commented on GitHub (May 14, 2022): I tried to modify the `strings_en.h` file like this: ```C++ const char HTTP_SCRIPT[] PROGMEM = "<script>function c(l){" "document.getElementById('s').value=l.getAttribute('data-ssid')||l.innerText||l.textContent;" "p = l.nextElementSibling.classList.contains('l');" "document.getElementById('p').disabled = !p;" "if(p)document.getElementById('p').focus();let inputs = document.querySelectorAll('input');" "let buttonSend = document.getElementById('save-btn');" "let inputValidator = {'s': false,'p': false, 'email': flase};" "inputs.forEach((input) => {input.addEventListener('input', () => {let name = event.target.getAttribute('name');" "if (event.target.value.length > 0) {inputValidator[name] = true;} else {inputValidator[name] = false;};" "let allTrue = Object.keys(inputValidator).every((item) => {return inputValidator[item] === true});" "if (allTrue) {buttonSend.disabled = false;} else {buttonSend.disabled = true;}})})}</script>"; // @todo add button states, disable on click , show ack , spinner etc . . . const char HTTP_FORM_END[] PROGMEM = "<br/><br/><button type='submit' id='save-btn' disabled>Save</button></form>"; ``` But I cannot see any changes there. Also, I tried to just disable the save button using html but I don't see any change there too. around lines 70-80 in `strings_en.h` file: ```C++ const char HTTP_FORM_END[] PROGMEM = "<br/><br/><button disabled>Save</button></form>"; ``` Am I missing sth?
Author
Owner

@tablatronix commented on GitHub (May 14, 2022):

you might have to add css for disabled state

<!-- gh-comment-id:1126817947 --> @tablatronix commented on GitHub (May 14, 2022): you might have to add css for disabled state
Author
Owner

@kargarisaac commented on GitHub (May 15, 2022):

When I remove the style part, I see that the button is disabled. But I cannot enable it using javascript. Do you think I put the code in a right place? I remove the custom input box and just use ssid and password inputs but no result yet.

<!-- gh-comment-id:1126930585 --> @kargarisaac commented on GitHub (May 15, 2022): When I remove the style part, I see that the button is disabled. But I cannot enable it using javascript. Do you think I put the code in a right place? I remove the custom input box and just use ssid and password inputs but no result yet.
Author
Owner

@tablatronix commented on GitHub (May 15, 2022):

disabled style was only for inputs, I updated it, pull master
github.com/tzapu/WiFiManager@c56eec9018

Can you post your js in plain js formatting.
Use the html template for testing, its easier

<!-- gh-comment-id:1126942596 --> @tablatronix commented on GitHub (May 15, 2022): disabled style was only for inputs, I updated it, pull master https://github.com/tzapu/WiFiManager/commit/c56eec9018f93e491011bfa374fb944ee26a7ef7 Can you post your js in plain js formatting. Use the html template for testing, its easier
Author
Owner

@tablatronix commented on GitHub (May 15, 2022):

I will have the strings reworked later toda with the easier includes also

<!-- gh-comment-id:1126944793 --> @tablatronix commented on GitHub (May 15, 2022): I will have the strings reworked later toda with the easier includes also
Author
Owner

@kargarisaac commented on GitHub (May 15, 2022):

I used the code from here.

My code:
added id for save button in cpp code.

const char HTTP_FORM_END[]         PROGMEM = "<br/><br/><button type='submit' id='save-btn' disabled>Save</button></form>";

and appended the following js code to the HTTP_SCRIPT[] code inside the function:

let inputs = document.querySelectorAll('input');
let buttonSend = document.getElementById('save-btn');

let inputValidator = {
  "s": false,
  "p": false
}

inputs.forEach((input) => {
  input.addEventListener('input', () => {
    let name = event.target.getAttribute('name');
    if (event.target.value.length > 0) {
      inputValidator[name] = true;
    } else {
      inputValidator[name] = false;
    };

    let allTrue = Object.keys(inputValidator).every((item) => {
      return inputValidator[item] === true
    });

    if (allTrue) {
      buttonSend.disabled = false;
    } else {
      buttonSend.disabled = true;
    }
  })
})
<!-- gh-comment-id:1126946850 --> @kargarisaac commented on GitHub (May 15, 2022): I used the code from [here](https://javascript.tutorialink.com/how-to-disable-submit-button-until-all-mandatory-fields-are-filled-using-html-and-vanilla-js/). My code: added `id` for save button in cpp code. ```C++ const char HTTP_FORM_END[] PROGMEM = "<br/><br/><button type='submit' id='save-btn' disabled>Save</button></form>"; ``` and appended the following js code to the `HTTP_SCRIPT[]` code inside the function: ```js let inputs = document.querySelectorAll('input'); let buttonSend = document.getElementById('save-btn'); let inputValidator = { "s": false, "p": false } inputs.forEach((input) => { input.addEventListener('input', () => { let name = event.target.getAttribute('name'); if (event.target.value.length > 0) { inputValidator[name] = true; } else { inputValidator[name] = false; }; let allTrue = Object.keys(inputValidator).every((item) => { return inputValidator[item] === true }); if (allTrue) { buttonSend.disabled = false; } else { buttonSend.disabled = true; } }) }) ```
Author
Owner

@kargarisaac commented on GitHub (May 15, 2022):

Seems that the problem is putting script in head. When I put it at the end of body, it works in the html template. In cpp file, it is a bit complex. I don't know yet the logic there and have to go deeper in the code to change it.

<!-- gh-comment-id:1126969024 --> @kargarisaac commented on GitHub (May 15, 2022): Seems that the problem is putting script in head. When I put it at the end of body, it works in the html template. In cpp file, it is a bit complex. I don't know yet the logic there and have to go deeper in the code to change it.
Author
Owner

@tablatronix commented on GitHub (May 15, 2022):

maybe add an onload event wrapper ?

<!-- gh-comment-id:1126969740 --> @tablatronix commented on GitHub (May 15, 2022): maybe add an onload event wrapper ?
Author
Owner

@kargarisaac commented on GitHub (May 16, 2022):

Thanks for the tip. Now it works. Here is the code in html template:

<!-- HTTP_HEAD -->
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\"/>
		<title>{v}</title>
<!-- /HTTP_HEAD -->
<!-- HTTP_STYLE -->
<style>

:root{
	 /* CSS VARIABLE THEME COLOR */
	/*--primarycolor:#9933CC;*/
	--primarycolor:#1fa3ec;
}

body.invert,
body.invert a,
body.invert h1 {
	background-color:#060606;
	color:white;
}
body.invert .msg{
	background-color: #282828;
	border-top: 1px solid #555;
	border-right: 1px solid #555;
	border-bottom: 1px solid #555;
	color:#fff;
}
body.invert .q[role=img] {
    -webkit-filter: invert(1);
    filter: invert(1);
}
.c,
body {
    text-align: center;
    font-family: verdana
}
.wrap {
	text-align:left;
	display:inline-block;
	min-width:260px;
	max-width:500px;
}
div,
input,select {
    padding: 5px;
    font-size: 1em;
    /*width: 100%;*/
    /*/*margin: 3px 0 10px 0; // BEFORE spacing shows label closer to input, but need to do same for AFTER*/
    margin: 5px 0;
	box-sizing: border-box;
}
div{
	margin: 5px 0;
}
input,button,select,.msg{
	border-radius:.3rem;
    width: 100%;
}
input[type=radio],input[type=checkbox]{
    width: auto;
}
button,input[type="button"],input[type="submit"] {
    border: 0;
    background-color: var(--primarycolor);
    color: #fff;
    line-height: 2.4rem;
    font-size: 1.2rem;
}
input[type="file"]{
	border: 1px solid var(--primarycolor);
}
a {
    color: #000;
    font-weight: 700;
    text-decoration: none;
}
a:hover {
    color: var(--primarycolor);
    text-decoration: underline;
}
.h {
	display: none;
}
.q {
    height: 16px;
    margin: 0;
    padding: 0 5px;
    text-align: right;
    min-width: 38px;
    float:right;
}
.q.q-0:after {
    background-position-x: 0;
}
.q.q-1:after {
    background-position-x: -16px;
}
.q.q-2:after {
    background-position-x: -32px;
}
.q.q-3:after {
    background-position-x: -48px;
}
.q.q-4:after {
    background-position-x: -64px;
}
.q.l:before {
    background-position-x: -80px;
    padding-right: 5px
}
.ql .q {
    float: left;
}

.q:after,
.q:before {
    content: '';width:16px;height:16px;display:inline-block;background-repeat:no-repeat;background-position: 16px 0;
 background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAAAQCAMAAADeZIrLAAAAJFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADHJj5lAAAAC3RSTlMAIjN3iJmqu8zd7vF8pzcAAABsSURBVHja7Y1BCsAwCASNSVo3/v+/BUEiXnIoXkoX5jAQMxTHzK9cVSnvDxwD8bFx8PhZ9q8FmghXBhqA1faxk92PsxvRc2CCCFdhQCbRkLoAQ3q/wWUBqG35ZxtVzW4Ed6LngPyBU2CobdIDQ5oPWI5nCUwAAAAASUVORK5CYII=');
}
@media (-webkit-min-device-pixel-ratio: 2),
(min-resolution: 192dpi) {
    .q:before,
    .q:after {
        background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALwAAAAgCAMAAACfM+KhAAAALVBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAOrOgAAAADnRSTlMAESIzRGZ3iJmqu8zd7gKjCLQAAACmSURBVHgB7dDBCoMwEEXRmKlVY3L//3NLhyzqIqSUggy8uxnhCR5Mo8xLt+14aZ7wwgsvvPA/ofv9+44334UXXngvb6XsFhO/VoC2RsSv9J7x8BnYLW+AjT56ud/uePMdb7IP8Bsc/e7h8Cfk912ghsNXWPpDC4hvN+D1560A1QPORyh84VKLjjdvfPFm++i9EWq0348XXnjhhT+4dIbCW+WjZim9AKk4UZMnnCEuAAAAAElFTkSuQmCC');
        background-size: 95px 16px;
    }
}

.msg {
	padding: 20px;
	margin: 20px 0;
	border: 1px solid #eee;
	border-left-width: 5px;
	border-left-color: #777;
}

.msg h4 {
    margin-top: 0;
	margin-bottom: 5px;
}
.msg.P {
    border-left-color: var(--primarycolor);
}
.msg.P h4 {
    color: var(--primarycolor);
}
.msg.S {
    border-left-color: #5cb85c;
}
.msg.S h4 {
    color: #5cb85c;
}
.msg.D {
    border-left-color: #dc3630;
}
.msg.D h4 {
    color: #dc3630;
}

dt {
	font-weight: bold;
}
dd {
	margin: 0;
	padding: 0 0 0.5em 0;
}
td {
	vertical-align: top;
}
button.D{
	background-color:#dc3630;
}

button{
	/*transition: 0s filter;*/
	transition: 0s opacity;
	transition-delay: 3s;
	transition-duration: 0s;
	cursor: pointer;
}

button:active{
	opacity: 50% !important;
	/*filter: brightness(50%);*/
	cursor: wait;
	transition-delay: 0s;
}

button:hover{
	/*opacity: 80%;*/
}

:disabled {
	opacity: 0.5;
	/* not working in cp ?? */
}
</style>
<!-- /HTTP_STYLE -->
<!-- HTTP_SCRIPT -->
<script>

	let inputValidator = {
		"s": false,
		// "email": false,
		"p": false
	}

	function c(l){
			document.getElementById('s').value=l.innerText||l.textContent;
			p = l.nextElementSibling.classList.contains('l');
			document.getElementById('p').disabled = !p;
			if(p)document.getElementById('p').focus();
			inputValidator.s = document.getElementById('s').value.length > 0;
		}

	function load() {
		function enableButton(){
			if (inputValidator.s && inputValidator.p) {
				console.log('Enable Button');
				document.getElementById('save-btn').disabled = false;
			} else {
				document.getElementById('save-btn').disabled = true;
			}
		}

		/* event listener */
		document.getElementById('s').addEventListener('keyup', function(e) {
			inputValidator.s = document.getElementById('s').value.length > 0;
			console.log('here s2: ', inputValidator);
			enableButton();
		});
		
		document.getElementById('p').addEventListener('keyup', function(e) {
			inputValidator.p = document.getElementById('p').value.length > 0;
			console.log('here p: ', inputValidator);
			enableButton();
		});

	}
    window.onload = load;


	</script>
	<!-- /HTTP_SCRIPT -->


<!-- HTTP_HEAD_END -->
	</head>
	<body class="invert">
		<div class='wrap'>
		<!-- <div class='wrap ql qinv'> -->
<!-- /HTTP_HEAD_END -->
			<!-- SAMPLE -->
			<h2>/</h2><hR>
			<!-- /SAMPLE -->
			<!-- HTTP_PORTAL_OPTIONS -->
			<!-- /HTTP_PORTAL_OPTIONS -->
			<!-- HTTP_PORTAL_MENU[] -->
			<form action='/wifi' method='get'><button>Configure WiFi</button></form><br/>
			<form action='/0wifi' method='get'><button>Configure WiFi (No Scan)</button></form><br/>
			<form action='/info' method='get'><button>Info</button></form><br/>
			<form action='/param' method='get'><button>Setup</button></form><br/>
			<Hr><br/>
			<form action='/close' method='post'><button>Close</button></form><br/>
			<form action='/erase' method='post'><button class='D'>Erase</button></form><br/>
			<form action='/restart' method='post'><button>Restart</button></form><br/>
			<form action='/exit' method='post'><button>Exit</button></form><br/>
			<form action='/' method='post'><button>Back</button></form><br/>
			<!-- /HTTP_PORTAL_MENU -->
			<!-- SAMPLE -->
			<h2>/wifi</h2><hr>
			<div><a href='#p' onclick='c(this)'>Access Point 01</a><div role='img' aria-label='88%' title='88%' class='q q-4 l'></div></div>
			<div><a href='#p' onclick='c(this)'>Access Point 02</a><div role='img' aria-label='88%' title='88%' class='q q-4'></div></div>
			<div><a href='#p' onclick='c(this)'>Access Point 03</a><div role='img' aria-label='60%' title='60%' class='q q-3 l'></div></div>
			<div><a href='#p' onclick='c(this)'>Access Point 04</a><div role='img' aria-label='60%' title='60%' class='q q-3'></div></div>
			<div><a href='#p' onclick='c(this)'>Access Point 05</a><div role='img' aria-label='60%' title='60%' class='q q-3'></div></div>
			<div><a href='#p' onclick='c(this)'>Access Point 06</a><div role='img' aria-label='40%' title='40%' class='q q-2'></div></div>
			<div><a href='#p' onclick='c(this)'>Access Point 07</a><div role='img' aria-label='40%' title='40%' class='q q-2 l'></div></div>
			<div><a href='#p' onclick='c(this)'>Access Point 08</a><div role='img' aria-label='20%' title='20%' class='q q-1'></div></div>
			<div><a href='#p' onclick='c(this)'>Access Point 09</a><div role='img' aria-label='20%' title='20%' class='q q-1'></div></div>
			<div><a href='#p' onclick='c(this)'>Access Point 10</a><div role='img' aria-label='20%' title='20%' class='q q-4 l'></div><div class='q '>100%</div></div>
			<div><a href='#p' onclick='c(this)'>Access Point 11</a><div role='img' aria-label='10%' title='10%' class='q q-3'></div><div class='q '>70%</div></div>
			<div><a href='#p' onclick='c(this)'>Access Point 12</a><div role='img' aria-label='10%' title='10%' class='q q-1 l'></div><div class='q '>10%</div></div>
			<div><a href='#p' onclick='c(this)'>Access Point 13</a><div role='img' aria-label='10%' title='10%' class='q q-0 h'></div><div class='q '>100%</div></div>
			<div><a href='#p' onclick='c(this)'>Access Point 14</a><div class='q'>66%</div></div>
			<div><a href='#p' onclick='c(this)'>Access Point 15</a><div class='q'>56%</div></div>
			<!-- /SAMPLE -->
			<!-- HTTP_ITEM -->
			<div><a href='#p' onclick='c(this)'>{v}</a><div role='img' aria-label='{r}%' title='{r}%' class='q q-{q} {i}'></div></div>
			<!-- /HTTP_ITEM -->
			<!-- HTTP_FORM_START -->
			<form method='get' action='wifisave'><label for='s'>SSID</label><br/><input id='s' name='s' length=32 class="ssid_pass" placeholder='SSID'><br/><label for='p'>Password</label><input id='p' name='p' length=64 type='password' class="ssid_pass" placeholder='password'><br/>
			<!-- /HTTP_FORM_START -->
			<!-- SAMPLE -->
			<h3>custom parameter</h3><hr>
			<br/><label for='custom'>Label for Custom Param</label>
			<br/><input id='custom' name='custom' length='255' placeholder='placeholder' value='' {c}>
			<!-- /SAMPLE -->
			<!-- HTTP_FORM_LABEL -->
			<br/><label for='{i}'>{p}</label>
			<!-- /HTTP_FORM_LABEL -->
			<!-- HTTP_FORM_PARAM -->
			<br/><input id='{i}' name='{n}' length='{l}' placeholder='{p}' value='{v}' {c}>
			<!-- /HTTP_FORM_PARAM -->
			<!-- HTTP_FORM_END -->
			<br/><button type='submit' id="save-btn" disabled="disabled">Save</button></form>
			<!-- /HTTP_FORM_END -->
			<!-- HTTP_SCAN_LINK -->
			<br/><form action='/wifi' method='get'><button>Refresh</button></form>
			<!-- /HTTP_SCAN_LINK -->
			<!-- HTTP_SAVED -->
			<div class='msg'><h4>Saving Credentials</h4>Trying to connect ESP to network.<br />If it fails reconnect to AP to try again</div>
			<!-- /HTTP_SAVED -->
			<!-- HTTP_STATUS_ON -->
			<div class='msg P'><strong>Connected</strong> to {v}<br/><em><small>with IP {i}</small></em></div>
			<!-- /HTTP_STATUS_ON -->
			<!-- HTTP_STATUS_OFF -->
			<div class='msg {c}'><strong>Not Connected</strong> to {v}{r}</div>
			<!-- /HTTP_STATUS_OFF -->
			<!-- sample -->
			<div class='msg D'><strong>Not Connected</strong> to apname
			<!-- /sample -->
			<!-- HTTP_STATUS_OFFPW -->
				<br/>Authentication Failure
			<!-- /HTTP_STATUS_OFFPW -->
			<!-- HTTP_STATUS_OFFNOAP -->
				<br/>AP not found
			<!-- /HTTP_STATUS_OFFNOAP -->
			<!-- HTTP_STATUS_OFFFAIL -->
				<br/>Could not Connect
			<!-- /HTTP_STATUS_OFFFAIL -->
			</div>
			<!-- HTTP_STATUS_NONE -->
			<div class='msg'>No AP set</div>
			<!-- /HTTP_STATUS_NONE -->
			<!-- SAMPLE -->
			<div class='msg P'><h4>H4 Color Header P</h4>content</div>
			<!-- /SAMPLE -->
			<!-- SAMPLE -->
			<div class='msg S'><h4>H4 Color Header S</h4>content</div>
			<!-- /SAMPLE -->
			<!-- SAMPLE -->
			<h2>/info</h3><hr>
			<dl>
				<dt>Chip ID</dt><dd>123456</dd>
				<dt>Flash Chip ID</dt><dd>1234556</dd>
				<dt>IDE Flash Size</dt><dd>4194304 bytes</dd>
				<dt>Real Flash Size</dt><dd>4194304 bytes</dd>
				<dt>Empty</dt><dd></dd>
				<dt>Soft AP IP</dt><dd>192.168.4.1</dd>
				<dt>Soft AP MAC</dt><dd>00:00:00:00:00:00</dd>
				<dt>Station MAC</dt><dd>00:00:00:00:00:00</dd>
			</dl>
			<!-- /SAMPLE -->
			<!-- HTTP_HELP -->
		 		<br/><h3>Available Pages</h3><hr>
		 		<table class='table'>
		 		<thead><tr><th>Page</th><th>Function</th></tr></thead><tbody>
		 		<tr><td><a href='/'>/</a></td>
		 		<td>Menu page.</td></tr>
		 		<tr><td><a href='/wifi'>/wifi</a></td>
		 		<td>Show WiFi scan results and enter WiFi configuration.(/0wifi noscan)</td></tr>
		 		<tr><td><a href='/wifisave'>/wifisave</a></td>
		 		<td>Save WiFi configuration information and configure device. Needs variables supplied.</td></tr>
		 		<tr><td><a href='/close'>/close</a></td>
		 		<td>Close the configuration server and configuration WiFi network.</td></tr>
		 		<tr><td><a href='/info'>/info</a></td>
		 		<td>Information page</td></tr>
 				<tr><td><a href='/close'>/close</a></td>
 				<td>Close the captiveportal popup,configportal will remain active</td></tr>
		 		<tr><td><a href='/exit'>/exit</a></td>
		 		<td>Exit Config Portal, configportal will close</td></tr>
		 		<tr><td><a href='/restart'>/restart</a></td>
		 		<td>Reboot the device</td></tr>
		 		<tr><td><a href='/erase'>/erase</a></td>
		 		<td>Erase WiFi configuration and reboot Device. Device will not reconnect to a network until new WiFi configuration data is entered.</td></tr>
		 		</table>
		 		<h3>About</h3><hr>
		 		Version v1.x.x-xxxxx<Br/>
		 		Build_date<br/>
		 		Build_file<br/>
		 		Arduino_version<br/>
		 		<p/>Github <a href='https://github.com/tzapu/WiFiManager'>https://github.com/tzapu/WiFiManager</a>
			<!-- /HTTP_HELP -->
			<!-- FORM_UPLOAD -->
			<Br/><br/>Form UPLOAD<br/>
			<form method='POST' action='u' enctype='multipart/form-data'>
				<input type='file' name='update' accept='.bin,application/octet-stream' onchange="(function(el){document.getElementById('uploadbin').style.display = el.value=='' ? 'none' : 'initial';})(this)">
				<button id='uploadbin' class="h">Submit</button>
			<a href='http://192.168.4.1' target='_blank'><small>* Upload may not function inside captive portal, Open in browser - http://192.168.4.1</a></small>
			<!-- /FORM_UPLOAD -->


			<!-- FORM_EXTRAS -->
			<br/><br/><br/><hr>
			<!-- <br/>
			<label for='custom'>Label for Custom Param</label>
			<br/>
			<input id='custom' name='custom' length='255' placeholder='placeholder' value='' {c}>
			<br/> -->

			<!-- INOUT CHECKBOX -->
			<!-- <label for='input_checkbox'>Label for Input Checkbox</label> -->
			<input id='input_checkbox' name='input_checkbox' placeholder='placeholder' value='' type="checkbox" {c}>
			<label for='input_checkbox'>Label for Input Checkbox</label>
			<br/>

			<!-- INPUT CHOICE -->
			<p>Select Choice</p>
			<input style='display: inline-block;' type='radio' id='choice1' name='program_selection' value='1'>
  			<label for='choice1'>Choice1</label><br>
  			<input style='display: inline-block;' type='radio' id='choice2' name='program_selection' value='2'>
  			<label for='choice2'>Choice2</label><br>

  			<!-- INPUT SELECT -->
			<br/>
			<label for='input_select'>Label for Input Select</label>
			<select name="input_select" id="input_select" class="button">
			<option value="0">Option 1</option>
			<option value="1" selected>Option 2</option>
			<option value="2">Option 3</option>
			<option value="3">Option 4</option>
			</select>

			</form>

			<!-- /FORM_EXTRAS -->

<!-- HTTP_END -->
    </div>

	
	</body>
</html>
<!-- /HTTP_END -->
<!-- gh-comment-id:1127413813 --> @kargarisaac commented on GitHub (May 16, 2022): Thanks for the tip. Now it works. Here is the code in html template: ```html <!-- HTTP_HEAD --> <!DOCTYPE html> <html lang="en"> <head> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\"/> <title>{v}</title> <!-- /HTTP_HEAD --> <!-- HTTP_STYLE --> <style> :root{ /* CSS VARIABLE THEME COLOR */ /*--primarycolor:#9933CC;*/ --primarycolor:#1fa3ec; } body.invert, body.invert a, body.invert h1 { background-color:#060606; color:white; } body.invert .msg{ background-color: #282828; border-top: 1px solid #555; border-right: 1px solid #555; border-bottom: 1px solid #555; color:#fff; } body.invert .q[role=img] { -webkit-filter: invert(1); filter: invert(1); } .c, body { text-align: center; font-family: verdana } .wrap { text-align:left; display:inline-block; min-width:260px; max-width:500px; } div, input,select { padding: 5px; font-size: 1em; /*width: 100%;*/ /*/*margin: 3px 0 10px 0; // BEFORE spacing shows label closer to input, but need to do same for AFTER*/ margin: 5px 0; box-sizing: border-box; } div{ margin: 5px 0; } input,button,select,.msg{ border-radius:.3rem; width: 100%; } input[type=radio],input[type=checkbox]{ width: auto; } button,input[type="button"],input[type="submit"] { border: 0; background-color: var(--primarycolor); color: #fff; line-height: 2.4rem; font-size: 1.2rem; } input[type="file"]{ border: 1px solid var(--primarycolor); } a { color: #000; font-weight: 700; text-decoration: none; } a:hover { color: var(--primarycolor); text-decoration: underline; } .h { display: none; } .q { height: 16px; margin: 0; padding: 0 5px; text-align: right; min-width: 38px; float:right; } .q.q-0:after { background-position-x: 0; } .q.q-1:after { background-position-x: -16px; } .q.q-2:after { background-position-x: -32px; } .q.q-3:after { background-position-x: -48px; } .q.q-4:after { background-position-x: -64px; } .q.l:before { background-position-x: -80px; padding-right: 5px } .ql .q { float: left; } .q:after, .q:before { content: '';width:16px;height:16px;display:inline-block;background-repeat:no-repeat;background-position: 16px 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAAAQCAMAAADeZIrLAAAAJFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADHJj5lAAAAC3RSTlMAIjN3iJmqu8zd7vF8pzcAAABsSURBVHja7Y1BCsAwCASNSVo3/v+/BUEiXnIoXkoX5jAQMxTHzK9cVSnvDxwD8bFx8PhZ9q8FmghXBhqA1faxk92PsxvRc2CCCFdhQCbRkLoAQ3q/wWUBqG35ZxtVzW4Ed6LngPyBU2CobdIDQ5oPWI5nCUwAAAAASUVORK5CYII='); } @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { .q:before, .q:after { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALwAAAAgCAMAAACfM+KhAAAALVBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAOrOgAAAADnRSTlMAESIzRGZ3iJmqu8zd7gKjCLQAAACmSURBVHgB7dDBCoMwEEXRmKlVY3L//3NLhyzqIqSUggy8uxnhCR5Mo8xLt+14aZ7wwgsvvPA/ofv9+44334UXXngvb6XsFhO/VoC2RsSv9J7x8BnYLW+AjT56ud/uePMdb7IP8Bsc/e7h8Cfk912ghsNXWPpDC4hvN+D1560A1QPORyh84VKLjjdvfPFm++i9EWq0348XXnjhhT+4dIbCW+WjZim9AKk4UZMnnCEuAAAAAElFTkSuQmCC'); background-size: 95px 16px; } } .msg { padding: 20px; margin: 20px 0; border: 1px solid #eee; border-left-width: 5px; border-left-color: #777; } .msg h4 { margin-top: 0; margin-bottom: 5px; } .msg.P { border-left-color: var(--primarycolor); } .msg.P h4 { color: var(--primarycolor); } .msg.S { border-left-color: #5cb85c; } .msg.S h4 { color: #5cb85c; } .msg.D { border-left-color: #dc3630; } .msg.D h4 { color: #dc3630; } dt { font-weight: bold; } dd { margin: 0; padding: 0 0 0.5em 0; } td { vertical-align: top; } button.D{ background-color:#dc3630; } button{ /*transition: 0s filter;*/ transition: 0s opacity; transition-delay: 3s; transition-duration: 0s; cursor: pointer; } button:active{ opacity: 50% !important; /*filter: brightness(50%);*/ cursor: wait; transition-delay: 0s; } button:hover{ /*opacity: 80%;*/ } :disabled { opacity: 0.5; /* not working in cp ?? */ } </style> <!-- /HTTP_STYLE --> <!-- HTTP_SCRIPT --> <script> let inputValidator = { "s": false, // "email": false, "p": false } function c(l){ document.getElementById('s').value=l.innerText||l.textContent; p = l.nextElementSibling.classList.contains('l'); document.getElementById('p').disabled = !p; if(p)document.getElementById('p').focus(); inputValidator.s = document.getElementById('s').value.length > 0; } function load() { function enableButton(){ if (inputValidator.s && inputValidator.p) { console.log('Enable Button'); document.getElementById('save-btn').disabled = false; } else { document.getElementById('save-btn').disabled = true; } } /* event listener */ document.getElementById('s').addEventListener('keyup', function(e) { inputValidator.s = document.getElementById('s').value.length > 0; console.log('here s2: ', inputValidator); enableButton(); }); document.getElementById('p').addEventListener('keyup', function(e) { inputValidator.p = document.getElementById('p').value.length > 0; console.log('here p: ', inputValidator); enableButton(); }); } window.onload = load; </script> <!-- /HTTP_SCRIPT --> <!-- HTTP_HEAD_END --> </head> <body class="invert"> <div class='wrap'> <!-- <div class='wrap ql qinv'> --> <!-- /HTTP_HEAD_END --> <!-- SAMPLE --> <h2>/</h2><hR> <!-- /SAMPLE --> <!-- HTTP_PORTAL_OPTIONS --> <!-- /HTTP_PORTAL_OPTIONS --> <!-- HTTP_PORTAL_MENU[] --> <form action='/wifi' method='get'><button>Configure WiFi</button></form><br/> <form action='/0wifi' method='get'><button>Configure WiFi (No Scan)</button></form><br/> <form action='/info' method='get'><button>Info</button></form><br/> <form action='/param' method='get'><button>Setup</button></form><br/> <Hr><br/> <form action='/close' method='post'><button>Close</button></form><br/> <form action='/erase' method='post'><button class='D'>Erase</button></form><br/> <form action='/restart' method='post'><button>Restart</button></form><br/> <form action='/exit' method='post'><button>Exit</button></form><br/> <form action='/' method='post'><button>Back</button></form><br/> <!-- /HTTP_PORTAL_MENU --> <!-- SAMPLE --> <h2>/wifi</h2><hr> <div><a href='#p' onclick='c(this)'>Access Point 01</a><div role='img' aria-label='88%' title='88%' class='q q-4 l'></div></div> <div><a href='#p' onclick='c(this)'>Access Point 02</a><div role='img' aria-label='88%' title='88%' class='q q-4'></div></div> <div><a href='#p' onclick='c(this)'>Access Point 03</a><div role='img' aria-label='60%' title='60%' class='q q-3 l'></div></div> <div><a href='#p' onclick='c(this)'>Access Point 04</a><div role='img' aria-label='60%' title='60%' class='q q-3'></div></div> <div><a href='#p' onclick='c(this)'>Access Point 05</a><div role='img' aria-label='60%' title='60%' class='q q-3'></div></div> <div><a href='#p' onclick='c(this)'>Access Point 06</a><div role='img' aria-label='40%' title='40%' class='q q-2'></div></div> <div><a href='#p' onclick='c(this)'>Access Point 07</a><div role='img' aria-label='40%' title='40%' class='q q-2 l'></div></div> <div><a href='#p' onclick='c(this)'>Access Point 08</a><div role='img' aria-label='20%' title='20%' class='q q-1'></div></div> <div><a href='#p' onclick='c(this)'>Access Point 09</a><div role='img' aria-label='20%' title='20%' class='q q-1'></div></div> <div><a href='#p' onclick='c(this)'>Access Point 10</a><div role='img' aria-label='20%' title='20%' class='q q-4 l'></div><div class='q '>100%</div></div> <div><a href='#p' onclick='c(this)'>Access Point 11</a><div role='img' aria-label='10%' title='10%' class='q q-3'></div><div class='q '>70%</div></div> <div><a href='#p' onclick='c(this)'>Access Point 12</a><div role='img' aria-label='10%' title='10%' class='q q-1 l'></div><div class='q '>10%</div></div> <div><a href='#p' onclick='c(this)'>Access Point 13</a><div role='img' aria-label='10%' title='10%' class='q q-0 h'></div><div class='q '>100%</div></div> <div><a href='#p' onclick='c(this)'>Access Point 14</a><div class='q'>66%</div></div> <div><a href='#p' onclick='c(this)'>Access Point 15</a><div class='q'>56%</div></div> <!-- /SAMPLE --> <!-- HTTP_ITEM --> <div><a href='#p' onclick='c(this)'>{v}</a><div role='img' aria-label='{r}%' title='{r}%' class='q q-{q} {i}'></div></div> <!-- /HTTP_ITEM --> <!-- HTTP_FORM_START --> <form method='get' action='wifisave'><label for='s'>SSID</label><br/><input id='s' name='s' length=32 class="ssid_pass" placeholder='SSID'><br/><label for='p'>Password</label><input id='p' name='p' length=64 type='password' class="ssid_pass" placeholder='password'><br/> <!-- /HTTP_FORM_START --> <!-- SAMPLE --> <h3>custom parameter</h3><hr> <br/><label for='custom'>Label for Custom Param</label> <br/><input id='custom' name='custom' length='255' placeholder='placeholder' value='' {c}> <!-- /SAMPLE --> <!-- HTTP_FORM_LABEL --> <br/><label for='{i}'>{p}</label> <!-- /HTTP_FORM_LABEL --> <!-- HTTP_FORM_PARAM --> <br/><input id='{i}' name='{n}' length='{l}' placeholder='{p}' value='{v}' {c}> <!-- /HTTP_FORM_PARAM --> <!-- HTTP_FORM_END --> <br/><button type='submit' id="save-btn" disabled="disabled">Save</button></form> <!-- /HTTP_FORM_END --> <!-- HTTP_SCAN_LINK --> <br/><form action='/wifi' method='get'><button>Refresh</button></form> <!-- /HTTP_SCAN_LINK --> <!-- HTTP_SAVED --> <div class='msg'><h4>Saving Credentials</h4>Trying to connect ESP to network.<br />If it fails reconnect to AP to try again</div> <!-- /HTTP_SAVED --> <!-- HTTP_STATUS_ON --> <div class='msg P'><strong>Connected</strong> to {v}<br/><em><small>with IP {i}</small></em></div> <!-- /HTTP_STATUS_ON --> <!-- HTTP_STATUS_OFF --> <div class='msg {c}'><strong>Not Connected</strong> to {v}{r}</div> <!-- /HTTP_STATUS_OFF --> <!-- sample --> <div class='msg D'><strong>Not Connected</strong> to apname <!-- /sample --> <!-- HTTP_STATUS_OFFPW --> <br/>Authentication Failure <!-- /HTTP_STATUS_OFFPW --> <!-- HTTP_STATUS_OFFNOAP --> <br/>AP not found <!-- /HTTP_STATUS_OFFNOAP --> <!-- HTTP_STATUS_OFFFAIL --> <br/>Could not Connect <!-- /HTTP_STATUS_OFFFAIL --> </div> <!-- HTTP_STATUS_NONE --> <div class='msg'>No AP set</div> <!-- /HTTP_STATUS_NONE --> <!-- SAMPLE --> <div class='msg P'><h4>H4 Color Header P</h4>content</div> <!-- /SAMPLE --> <!-- SAMPLE --> <div class='msg S'><h4>H4 Color Header S</h4>content</div> <!-- /SAMPLE --> <!-- SAMPLE --> <h2>/info</h3><hr> <dl> <dt>Chip ID</dt><dd>123456</dd> <dt>Flash Chip ID</dt><dd>1234556</dd> <dt>IDE Flash Size</dt><dd>4194304 bytes</dd> <dt>Real Flash Size</dt><dd>4194304 bytes</dd> <dt>Empty</dt><dd></dd> <dt>Soft AP IP</dt><dd>192.168.4.1</dd> <dt>Soft AP MAC</dt><dd>00:00:00:00:00:00</dd> <dt>Station MAC</dt><dd>00:00:00:00:00:00</dd> </dl> <!-- /SAMPLE --> <!-- HTTP_HELP --> <br/><h3>Available Pages</h3><hr> <table class='table'> <thead><tr><th>Page</th><th>Function</th></tr></thead><tbody> <tr><td><a href='/'>/</a></td> <td>Menu page.</td></tr> <tr><td><a href='/wifi'>/wifi</a></td> <td>Show WiFi scan results and enter WiFi configuration.(/0wifi noscan)</td></tr> <tr><td><a href='/wifisave'>/wifisave</a></td> <td>Save WiFi configuration information and configure device. Needs variables supplied.</td></tr> <tr><td><a href='/close'>/close</a></td> <td>Close the configuration server and configuration WiFi network.</td></tr> <tr><td><a href='/info'>/info</a></td> <td>Information page</td></tr> <tr><td><a href='/close'>/close</a></td> <td>Close the captiveportal popup,configportal will remain active</td></tr> <tr><td><a href='/exit'>/exit</a></td> <td>Exit Config Portal, configportal will close</td></tr> <tr><td><a href='/restart'>/restart</a></td> <td>Reboot the device</td></tr> <tr><td><a href='/erase'>/erase</a></td> <td>Erase WiFi configuration and reboot Device. Device will not reconnect to a network until new WiFi configuration data is entered.</td></tr> </table> <h3>About</h3><hr> Version v1.x.x-xxxxx<Br/> Build_date<br/> Build_file<br/> Arduino_version<br/> <p/>Github <a href='https://github.com/tzapu/WiFiManager'>https://github.com/tzapu/WiFiManager</a> <!-- /HTTP_HELP --> <!-- FORM_UPLOAD --> <Br/><br/>Form UPLOAD<br/> <form method='POST' action='u' enctype='multipart/form-data'> <input type='file' name='update' accept='.bin,application/octet-stream' onchange="(function(el){document.getElementById('uploadbin').style.display = el.value=='' ? 'none' : 'initial';})(this)"> <button id='uploadbin' class="h">Submit</button> <a href='http://192.168.4.1' target='_blank'><small>* Upload may not function inside captive portal, Open in browser - http://192.168.4.1</a></small> <!-- /FORM_UPLOAD --> <!-- FORM_EXTRAS --> <br/><br/><br/><hr> <!-- <br/> <label for='custom'>Label for Custom Param</label> <br/> <input id='custom' name='custom' length='255' placeholder='placeholder' value='' {c}> <br/> --> <!-- INOUT CHECKBOX --> <!-- <label for='input_checkbox'>Label for Input Checkbox</label> --> <input id='input_checkbox' name='input_checkbox' placeholder='placeholder' value='' type="checkbox" {c}> <label for='input_checkbox'>Label for Input Checkbox</label> <br/> <!-- INPUT CHOICE --> <p>Select Choice</p> <input style='display: inline-block;' type='radio' id='choice1' name='program_selection' value='1'> <label for='choice1'>Choice1</label><br> <input style='display: inline-block;' type='radio' id='choice2' name='program_selection' value='2'> <label for='choice2'>Choice2</label><br> <!-- INPUT SELECT --> <br/> <label for='input_select'>Label for Input Select</label> <select name="input_select" id="input_select" class="button"> <option value="0">Option 1</option> <option value="1" selected>Option 2</option> <option value="2">Option 3</option> <option value="3">Option 4</option> </select> </form> <!-- /FORM_EXTRAS --> <!-- HTTP_END --> </div> </body> </html> <!-- /HTTP_END --> ```
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/WiFiManager#1210
No description provided.