I have been given some feedback on some code.
The feedback: "no accessibility or validation has been considered for the search form"
Heres the code:
export const Search = () => {
const [searchTerm, setSearchTerm] = useState('');
return (
<form className={styles.search} onSubmit={handleSubmit}>
<input
type='text'
id='search'
name='search'
onChange={handleChange}
value={searchTerm || ''}
placeholder='search'
/>
<button className='btn' type='submit' onClick={handleSubmit}>
Search
</button>
</form>
);
};
After searching I cannot find anything else extra to add. I thought that forms and buttons have default accessibility.
I'm trying to learn how to add extra accessibility and validation to this form as I believe it is important to encourage use good accessibility practise. Any guidance would be great.
P.S the code is in React treat it like html and JavaScript if your'e unfamiliar.
First, you can identify this form as a search landmark for assistive technology with the use of role="search". Using the search landmark will help assistive technology to "read" the user that this is a search option and screen readers also have an option to navigate to this section directly instead of navigating through all the elements on the page.
Search role landmark info on MDN
Secondly, all modern browsers support the input type="search", that works exactly as type="text" but helps with autocomplete option across domains, helping users with dyslexia not making mistakes when they need to use this option.
Input type search info on MDN
Third, like TJ answered, labels for user control elements like inputs are important for blind people. Screen readers "read" the values of these fields, if there is no label it can be confusing what should they fill there. You can use the element with the for="someID" attribute, or you can use aria-label="labelText" attribute to add label for assistive technology. Although some of the screen readers will use the placeholder as the label when the value is empty, you can't use it as a label.
Labeling controls info on W3C-WAI
Fourth, consider the validation, if it is not the default HTML5 validation, you need to let the user know about any errors so he can correct the mistakes. You can use an element like span with role="alert" or role="status" or use some tooltip open (just to cover more disabilities) to inform the user about errors and suggestions on how to correct them.
Accessible form validation article on WebAIM
In matter of form validation, you can use the HTML5 validation like TJ answered using the input attributes required/pattern/etc. or use your own business logic to validate the form in the handleSubmit function you write.
My code suggestion:
export const Search = () => {
const [searchTerm, setSearchTerm] = useState('');
return (
<form role='search' className={styles.search} onSubmit={handleSubmit}>
<input
type='search'
id='search'
name='search'
onChange={handleChange}
value={searchTerm || ''}
placeholder='search'
aria-label='Enter your search term'
required={true}
/>
<span className='errMsg' role='status'>Error message here</span> {/*use CSS to show and hide msg*/}
<button className='btn' type='submit' onClick={handleSubmit}>
Search
</button>
</form>
);
};
Only accessibility issue I can notice is placeholder='search'. You should always use a <label for="">, placeholder is just a complimentary feature for normal people.
For validation you prob need required since it is the only <input>. You might also need min/max/pattern etc but that's up to you.
<label for="search">Search<label>
<input
type='text'
id='search'
name='search'
onChange={handleChange}
value={searchTerm || ''}
placeholder='search'
required
/>
Related
We have a ReactJs web application and we are taking some data through of input field but the problem is sometimes this field fills data automatically
For more specification, this problem happens when we are using Oppo and Redmi(OS) but for other OS it's working as normal
For more clear understanding, we made a video using Redmi mobile phone, and here is the video link, Please have a look at the video from the link.
https://drive.google.com/file/d/1yo03CjqeV9iFXgtSH-ff7zgH1hJq60BY/view?usp=sharing
Here is the input field code
// Formik Field
<Field name={name}>
{({ field }: any) => {
return (
<input
{...rest}
{...field}
id={name}
type="text"
autoComplete="off" // we use before off= boolean
value={values.data}
placeholder="Input data"
className={`appoint-input-box ${errors && touched ? " error-red-400" : null}`}
onChange={async (event) => {
handleFiend(event);
setFieldValue("data", event.value.toLowerCase());
}}
/>
);
}}
</Field>
As we said before, this is a ReactJs web app but for form handling we use Formik and this is a text-type input field also this form is a child form, it has a parent form as a controller.
Now we have autoComplete="off" but before we use boolean and top label form we also use the same.
We are hoping, that the provided information is describing properly the exact issue.
If someone expert can guide us on what to do then it's will really pleasure
Thanks
Internazionaleauto
I've made multiple search boxes that search external dictionary sites. Due to the site search syntax, I've had to use JavaScript to construct a url from the text box input. This code works perfectly fine:
function prepare_link_glosbe() {
var url_param_gl = document.getElementById('url_param_gl');
var target_link_gl = document.getElementById('target_link_gl');
if ( ! url_param_gl.value ) {
return false;
}
target_link_gl.href = "https://nb.glosbe.com/en/nb"
target_link_gl.href = target_link_gl.href + '/' + encodeURI(url_param_gl.value);
window.open(target_link_gl.href, '_blank')
}
function prepare_link_dict() {
var url_param_dict = document.getElementById('url_param_dict');
var target_link_dict = document.getElementById('target_link_dict');
if ( ! url_param_dict.value ) {
return false;
}
target_link_dict.href = "https://www.dict.com/engelsk-norsk"
target_link_dict.href = target_link_dict.href + '/' + encodeURI(url_param_dict.value);
window.open(target_link_dict.href, '_blank')
}
<!--Search Glosbe.com-->
<div style="border:0px solid black;padding:8px;width:60em;">
<table border="0" cellpadding="2">
<tr><td>
<input type="text" onfocus="this.value=''" value="Search glosbe.com" name="url_param_gl" id="url_param_gl" size="40"/>
<input type="button" onclick="prepare_link_glosbe()" value="Glosbe (en-no)" />
<a href="https://nb.glosbe.com/en/nb" id="target_link_gl" target="_blank" ></a>
</td></tr></table></div>
<!--Search Dict.com-->
<div style="border:0px solid black;padding:8px;width:60em;">
<table border="0" cellpadding="2">
<tr><td>
<input type="text" onfocus="this.value=''" value="Search dict.com" name="url_param_dict" id="url_param_dict" size="40"/>
<input type="button" onclick="prepare_link_dict()" value="Dict (en-no)" />
<a href="https://www.dict.com/engelsk-norsk" id="target_link_dict" target="_blank" ></a>
</td></tr></table></div>
However, I wish to search both sites using a single input box. I've tried different approaches, including addEventListener, but I'm not fluent enough in either HTML or JavaScript to achieve it. Can anyone point me in the right direction?
First of all, some things that will make your life easier in the long run:
You don't need this.value='', just use the placeholder attribute - it's well supported.
Don't use <table> to create a layout.
Don't use attributes to assign JS event handlers. (so no onclick=)
And now, how to use just one text field for both websites - just remove the second field and move the button somewhere else. Here's an example:
// This is our search input field.
const searchValue = document.getElementById('search_value');
// Here I'm looking for all search buttons and iterating over them
// with for ... of, querySelectorAll accepts valid CSS selectors.
for (let button of document.querySelectorAll('.search_button')) {
// Getting the data-url attribute value from the button.
const url = button.dataset.url;
// Adding a click event handler, instead of relying on onclick=''
button.addEventListener('click', function () {
// Quick string replace...
const targetURL = button.dataset.url.replace('%s', encodeURI(searchValue.value));
// ...and here we open the new tab.
window.open(targetURL, '_blank');
});
}
<div>
<input type="text" placeholder="Search..." id="search_value" />
<button class="search_button" data-url="https://nb.glosbe.com/en/nb/%s">Glosbe (en-no)</button>
<button class="search_button" data-url="https://www.dict.com/engelsk-norsk/%s">Dict (en-no)</button>
</div>
Here's the explanation:
I'm using the HTML data-* attributes (accessible in JS via element.dataset.*) to store the URL, %s is being used as a placeholder for the search value and will be later replaced with the .replace function.
Instead of manually assigning IDs to buttons I've declared a class - this allows you to extend the application infinitely.
I've merged the input fields into just one and read its value in the button event handler.
I've replaced your this.value='' hack with a proper placeholder.
I've removed the table layout, if you wish to add a nicer layout or styling I would suggest to learn more about CSS - also: don't use HTML attributes to style elements (except for class and style). Avoid using ID selectors in CSS as well (it's fine in JS, but in CSS it can cause issues when it comes to importance). Also, you should avoid the style attribute anyway - it will take precedence over most CSS rules except for the rules with !important and causes code duplication.
Please check the link below:
http://jsfiddle.net/cT9kg/4/
As you can see its a search field with a button.
If you have trouble understanding what I mean below please just look at the "Title" input on the Ask a question page.
The input has autofocus on.
BUT
How can I have it so text is already in the input with autofocus on but as soon as someone types into the input the text disappears.
AND
When someone has entered text in the input but then deletes it, it goes back to the way it was at the beginning: on focus with text in it instructing the person what to type in the input.
Thanks!
James
You could define the default value.
On focus - empty value, if the value is default value.
When the element lose the focus, You could check, if it's empty, and if Yes - restore the default value.
I've tested this as working, just make sure you put the <script> part just before the </body> tag.
<input type="text" class="input1" autofocus="focus" id="search" value="Type here..." onKeyPress="checkValue()" />
----
<script type="text/javascript">
var searchEl = document.getElementById('search');
var defaultValue = searchEl.value;
function checkValue() {
if (searchEl.value == defaultValue) {
searchEl.value = "";
}
}
</script>
You could use the HTML placeholder attribute, but in the majority of browsers that won't achieve quite what you are after: as soon as the input is focused, the placeholder text disappears.
For functionality akin to iOS (found on sites such as Twitter as well), you need to use JavaScript. One example can be seen online here.
This similar question (and this one) have some useful alternatives and code examples.
You're correctly using autofocus, which is fine but has patchy browser support. You can add in a JS fallback, like this (taken from here):
<script>
window.onload = function () {
if (!("autofocus" in document.createElement("input"))) {
document.getElementById("s").focus();
}
}
</script>
Wow. I tried digging around in the source code for the Ask a question page. Talk about convoluted.
Here is the CSS File.
While it seems the relevant bits are thus, they don't seem to DO much more than format (other than the edit-field-overlay trick.
.form-item {padding:10px 0px 15px 0px;}
.ask-title {margin-bottom:-15px;margin-top:-10px;}
.ask-title-table {width:668px;}
.ask-title-field {width:610px;}
.ask-title-cell-value {padding-left:5px;}
.edit-field-overlay {display:none;}
HTML (some TD tags removed):
<div class="form-item ask-title">
<table class="ask-title-table">
<tr>
<td class="ask-title-cell-value">
<input id="title" name="title" type="text" maxlength="300" tabindex="100" class="ask-title-field" value="">
<span class="edit-field-overlay">what's your programming question? be specific.</span>
</td>
</tr>
</table>
</div>
But I totally could NOT figure out the relevant Javascript bits. As there are NO onEvent handlers for this form that I can see, the only reference to this field (title) would be in the prepareEditor function.
Anybody care to try and explain it to a relative newbie??
Is there anyway to make the textbox/input box in prompt multiline?
No, browsers only allow single-line input for prompt(). However, with a simple change to the jQuery Alert Dialogs library you could get multi-line input there. Take jquery.alerts.js, look for <input type="text" size="30" id="popup_prompt" /> and replace it by <textarea rows="5" cols="30" id="popup_prompt"></textarea>. That should do to have a multi-line input field show up when calling jPrompt().
Edit: As Mulletfingers999 points out in a comment, jQuery Alert Dialogs have been deprecated in favor of jQuery UI dialogs. There you can also show a "modal" dialog, that dialog can have arbitrary content however - meaning that a <textarea> tag is possible if you want multi-line input.
Use \n encased in double quotes ("\n")
prompt("This\nis\nmultiline");
For pretty much any user-facing web application these days, you're going to want to avoid using clunky old dialogs like alert() and prompt(). Almost any library you're using should have a much better answer. jquery would be fine as others have said. It would also be good to think of how you might eliminate a need for modality by designing a more clever interface.
"Interestingly", in Firefox they are already using XUL and reinventing a lot of user interface based on that (instead of relying on the "common dialogs" of the underlying OS). There's a template for modal dialogs in /source/toolkit/components/prompts/content/tabprompts.xml:
<vbox anonid="infoContainer" align="center" pack="center" flex="1">
<description anonid="info.title" class="info.title" hidden="true" />
<description anonid="info.body" class="info.body"/>
</vbox>
<row anonid="loginContainer" hidden="true" align="center">
<label anonid="loginLabel" value="&editfield0.label;" control="loginTextbox"/>
<textbox anonid="loginTextbox"/>
</row>
<row anonid="password1Container" hidden="true" align="center">
<label anonid="password1Label" value="&editfield1.label;" control="password1Textbox"/>
<textbox anonid="password1Textbox" type="password"/>
</row>
<row anonid="checkboxContainer" hidden="true">
<spacer/>
<checkbox anonid="checkbox"/>
</row>
What they do is just hide the elements of the UI that they don't need. In the case of a call to prompt, they re-use the user name field and keep the password and checkbox elements hidden. You can see this happening in /source/toolkit/components/prompts/src/CommonDialog.jsm#52:
case "prompt":
this.numButtons = 2;
this.iconClass = ["question-icon"];
this.soundID = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
this.initTextbox("login", this.args.value);
// Clear the label, since this isn't really a username prompt.
this.ui.loginLabel.setAttribute("value", "");
break;
Since it's more or less HTML, the only question is what the non-standard tag <textbox> means for the user interface. The XUL controls documentation informs us that it's only a one-line entry, you would need <textarea> for more:
https://developer.mozilla.org/en/XUL_controls
I thought it would be "fun" to look at the implementation in Chromium on top of GTK too. After a bit of digging through the circuitous wrappers of WebKit, I did manage to find chromium/src/chrome/browser/ui/gtk/js_modal_dialog_gtk.cc, specifically this part:
// Adjust content area as needed. Set up the prompt text entry or
// suppression check box.
if (ui::MessageBoxFlags::kIsJavascriptPrompt == dialog_->dialog_flags()) {
GtkWidget* content_area =
gtk_dialog_get_content_area(GTK_DIALOG(gtk_dialog_));
GtkWidget* text_box = gtk_entry_new();
gtk_entry_set_text(GTK_ENTRY(text_box),
UTF16ToUTF8(dialog_->default_prompt_text()).c_str());
gtk_box_pack_start(GTK_BOX(content_area), text_box, TRUE, TRUE, 0);
g_object_set_data(G_OBJECT(gtk_dialog_), kPromptTextId, text_box);
gtk_entry_set_activates_default(GTK_ENTRY(text_box), TRUE);
}
The text_box is created with gtk_entry_new() and the GTK documentation states that GtkEntry is "A single line text entry field". For multi-line entry you would have to use GtkTextView:
http://developer.gnome.org/gtk/2.24/GtkTextView.html
So there's your answer not just of "can you?" but the smoking guns of why you can't (in a couple of popular browser implementations.) Unless there's a way to override that XUL in Firefox with an extension of some kind, which there may well be! I'll leave it as an exercise for the reader. :P
How can I write this so the text shows in the text field (search bar) during the page load?
<input type="text" id="addressInput" value="<%=addressStr%>" onblur="if(this.value=='')this.value='Search a location here';" onfocus="if(this.value=='Search a location here')this.value='';" />
At the moment the text only shows when you click in the textfield.
#detonate: You could just add some of the same logic to the ASP value so it'll show Search a location here if addressStr is blank:
<input type="text" id="addressInput" value="<% If addressStr = "" Then Response.Write "Search a location here" End If %>" onblur="if(this.value=='')this.value='Search a location here';" onfocus="if(this.value=='Search a location here')this.value='';" />
it looks like you're trying to setup a watermark for a textbox, is that correct?
I'm going to refer you to a basic example of textbox watermarking that should be able to give you an example and give everyone a bit of a common codebase for discussion, since you didn't include a lot of code in your post: http://www.codeproject.com/KB/aspnet/WatermarkTextBox.aspx
In it, I'll reference one of his codeblocks, that is similar to the one you posted:
<td>
<asp:TextBox ID="txtUserId" runat="server"
onfocus="Focus(this.id,'User ID')"
onblur="Blur(this.id,'User ID')"
Width="126px" CssClass="WaterMarkedTextBox">User ID</asp:TextBox>
</td>
While I realize he used ASP.NET instead of ASP, I wanted to draw attention to the fact that he put <textbox>text</textbox> so that you could see part of the answer to the question you directly asked above.
EDIT: Let me try this again: You would have something like this:
<textbox attributes="" methods="" >
<%=addressStr%>
</textbox>
Hopefully tho, the whole example given on that page will help you. Feel free to ask more questions.