Setting focus to input element on validation error not working - javascript

I have a long list of input fields created from data in a database, more or less like this:
foreach ($data as $value) {
...
<input type="text" name="date_earned$row" id="date_earned$row" value = "$date_earned" onchange="changeDate(this)">
...
}
The onchange script is like this (note: the date is not a standard date so I'm not trying to validate a normal date). It won't let me set focus back to the element that I just changed, if there is an error. I have no trouble setting the focus to a different element. Why?
<script type="text/javascript">
function changeDate(sel) {
var theDate = sel.value;
var isValid = true;
if (theDate) {
<!-- .... some stuff in here to validate the date, sets isValid = false if it is not correct format} -->
}
if (!(isValid)) {
<!-- ... do some stuff in here to display the error message -->
document.getElementById('thiselementsid').focus(); <!-- this doesn't work when 'thiselementsid' is the id of the element which just lost focus-->
document.getElementById('someotherelement').focus(); <!-- this works, but not if 'someotherelement' is the id of the last focused element -->
}

One thing that strikes me is that you are missing an apostrophe in the line
document.getElementById('thiselementsid).focus();
after "thiselementsid." I don't know if that's the source of your problem or if it's just example code.
It's also possible that some subsequent code is calling something along the lines of document.getElementById('thiselementsid').blur() (blur is the order to lose focus). Evan's suggestion in a comment appended to your question would solve that - setTimeout would delay the setting of focus until after the blur() method was called.
There are other possibilities, most of them rather nasty. Let us know in an edit if you're still having problems. It might be good in that case to provide more of the surrounding code.

You can set it like this as well.
document.getElementById('thiselementsid').focus() = true;

Related

Removing focus from input box that was focussed earlier

I have one more input box - ibox2, on the same page.
Problem - After doing anything on ibox1 and leaving value of length > 5 there, if I start typing in ibox2 the focus jumps back to ibox1.
It is that if loop with ibox1.focus() that is doing it. How could I remove focus entirely from ibox1 upon clicking outside and nullify the if loop and its statements.
I tried blurbut it did not work.
var ibox1 = $("#inputbox1");
$(document).on("change", ibox1,function(e) {
var valu = ibox1.val();
if(valu.length > 5){
#do something
ibox1.focus(); #used this as input box lost focus with each charater typed.
}
});
var ibox2 = $("#inputbox2"); #This is for google places autocomplete.
PS - Please do not tag it as a duplicate one, I have tried almost everything here, and only then I posted this. I shall remove it upon getting solution.
Respected mods, I followed a nice accepted answer and made a mistake about understanding $('document'), but I now got it cleared. That's the reason I am not deleting this question, even though I said I would, as it might help others. You guys, if
you feel, could delete this. Thanks.
The focus is jumping back to ibox1 because you are instructing your document to do so each time the onChange event is fired.
e.g.: $(document).on("change", ibox1, funct... where you are calling for ibox1.focus(); `.
Possible solution: bind your change event to the element of interest itself and avoid binding an event of such local significance to the whole document in the future.
Use a simple method to attach an event to inputs. Check below code it may help you.
(function(){
var in1 = jQuery('#input1'); // first input
var in2 = jQuery('#input2'); // second input
// On change of first input
in1.change(function(){
if(this.val().length > 5){
// do something
}
});
// On change of second input
in2.change(function(){
if(this.val().length > 5){
// do something
}
});
})();

JS Replacing form inputs with user input

I'm a novice with javascript, and am struggling with my final project for a class. We're essentially making an online quiz. It's a math quiz, and I've set up forms with text input fields for the answer, and those forms are within div containers. I'm trying to create a function that, upon clicking a submit button, will pull the value of the user's input, and use that value to replace the form as the inner html of the div. This way the answer will be committed and cannot be changed after the user submits their answer. One key step of this is that the digits of the answer are entered individually - a field for the tens column, a field for the ones. I'm trying to pull those separately, concatenate them, and then compare them with the calculated actual answer. The actual answer will replace the submit button, color coded to reflect whether the user was correct or not. Here's what I have:
var firstNumber = Math.floor((Math.random()*50)+1);
var secondNumber = Math.floor((Math.random()*50)+1);
var generate = function(){
document.getElementById("addends1").innerHTML=firstNumber;
document.getElementById("addends2").innerHTML=secondNumber;
};
var evaluate = function(){
var result = firstNumber+secondNumber;
document.getElementById("button").innerHTML=result;
var tens = document.getElementById("result10s").value;
var ones = document.getElementById("result1s").value;
var entry = tens + ones;
document.getElementById("resultContainer").innerHTML=entry;
var cO = document.getElementById("cO").value;
document.getElementById("carryOverContainer").innerHTML=cO;
var answer = parseFloat(entry);
if (answer===result) {
document.getElementbyID("resultContainer").style.color="#b2f078";
} else {
document.getElementbyID("resultContainer").style.color="#e87c73";
}
};
document.getElementById("button").onclick=evaluate();
(the first function is called in the html tag, onload for the button image)
Thanks!
Edit: My problem is just that my code isn't doing anything at all. I don't know if that has to do with how I'm calling the "evaluate" function, or the function itself. I want to replace all form fields with their entered values, and then also replace the button with the correct answer to the addition problem. Here's my html:
<body>
<div id="carryOverContainer">
<form>
<input type="text" name="carryOver" id="cO"/>
</form>
</div>
<div id="addends1" class="addends"> </div>
<div id="addends2" class="addends"> </div>
<div id="resultContainer">
<form>
<input type="text" id="result10s" class="result">
<input type="text" id="result1s" class="result">
</form>
</div>
<div id="button" onclick=evaluate();>
<img src="next.png" alt="next" onload="generate();"/>
</div>
</body>
I'm suspecting the problem may lie in how I'm trying to pull and store the values from the form fields?
As there are potentially many issues, I'll help you in steps rather than try to give you the whole solution. (It's the weekend now, so I can respond more frequently.)
The first issue is in the way you're defining and using functions. Your syntax, i.e.
var evaluate = function() {
// ...
}
defines an anonymous function assigned to the variable generate. For comparison, here's how regular functions are defined:
function evaluate() {
// ...
}
Your syntax can work if called properly, but you're calling it like a regular function:
document.getElementById("button").onclick=evaluate();
What's happening is, whereas for a regular function, the function evaluate() would get assigned to the onclick event, for an anonymous function, evaluate and () are interpreted as call the anonymous function in this variable. Therefore, evaluate() is getting called right away, instead of onclick! Here's a JSFiddle that shows how your form fields are immediately replaced.
Once you've fixed this issue, update your question and comment on my answer to grab my attention, and we'll take it from there.
By the way, if you're using Chrome, hit CtrlShiftI and go to the Console tab to see if your Javascript is throwing any issues. Firefox has a similar feature—look for developer tools in the menu.

Control Cursor Location on Focus in Form Field

I have a form with 4 fields. I want the first of the four to have the autofocus and be the first the user fills out. But then, either by tab or mouse or whatever, when the user gets to second field, I want the cursor to end up at the end of the string to start. There is a pre-filled string in that field.
I'm using Django so I have a form widget controlling the attributes. I can get the string to show up and even get the cursor to the end, but this always causes autofocus as well on that second field. I haven't managed to get both.
Here is code I'm using so far:
Django
field = forms.URLField(
widget = forms.URLInput(
attrs = {
'placeholder': 'enter field',
# call to javascript function - this works
'onfocus': 'add_string("field_id", "string")',
}
)
)
JavaScript:
// add string to element
function add_string(id, string) {
var input = document.getElementById(id);
input.value = string;
}
I've played around with various JS scripts but to no avail. I then found setSelectionRange and played around with this like so:
input.setSelectionRange(7, 7)
Where 7 would be end of the particular "string" in the onfocus JavaScript function call, but I could't get this to work...
Finally, I played around with some jQuery that looked like this:
// focus after string, no highlight
$(document).ready(function() {
var $field = $("#field_id");
var old_val = $field.val();
$field.focus().val('').val(old_val);
});
But this did the same thing: brought initial focus to second field and brought cursor to the end.
Any idea how I can do this, get both autofocus on field one but get cursor to jump to end of pre-filled string of field two on it's focus? Might be a nice trick if I knew how to do it.
You're almost there, you just need to fire your code when your form field is focused, instead of on document ready. In my tests it was necessary to add a zero timeout, because otherwise the field value remains selected:
$(document).ready(function() {
var $field = $("#field_id");
$field.on('focus', function() {
setTimeout(function() {
var old_val = $field.val();
$field.val('').val(old_val);
}, 0);
});
});
JSFiddle demo

Clear default values using onsubmit

I need to clear the default values from input fields using js, but all of my attempts so far have failed to target and clear the fields. I was hoping to use onSubmit to excute a function to clear all default values (if the user has not changed them) before the form is submitted.
<form method='get' class='custom_search widget custom_search_custom_fields__search' onSubmit='clearDefaults' action='http://www.example.com' >
<input name='cs-Price-2' id='cs-Price-2' class='short_form' value='Min. Price' />
<input name='cs-Price-3' id='cs-Price-3' class='short_form' value='Max Price' />
<input type='submit' name='search' class='formbutton' value=''/>
</form>
How would you accomplish this?
Read the ids+values of all your fields when the page first loads (using something like jquery to get all "textarea", "input" and "select" tags for example)
On submit, compare the now contained values to what you stored on loading the page
Replace the ones that have not changed with empty values
If it's still unclear, describe where you're getting stuck and I'll describe more in depth.
Edit: Adding some code, using jQuery. It's only for the textarea-tag and it doesn't respond to the actual events, but hopefully it explains the idea further:
// Keep default values here
var defaults = {};
// Run something like this on load
$('textarea').each(function(i, e) {
defaults[$(e).attr('id')] = $(e).text();
});
// Run something like this before submit
$('textarea').each(function(i, e){
if (defaults[$(e).attr('id')] === $(e).text())
$(e).text('');
})
Edit: Adding some more code for more detailed help. This should be somewhat complete code (with a quality disclaimer since I'm by no means a jQuery expert) and just requires to be included on your page. Nothing else has to be done, except giving all your input tags unique ids and type="text" (but they should have that anyway):
$(document).ready(function(){
// Default values will live here
var defaults = {};
// This reads and stores all text input defaults for later use
$('input[type=text]').each(function(){
defaults[$(this).attr('id')] = $(this).text();
});
// For each of your submit buttons,
// add an event handler for the submit event
// that finds all text inputs and clears the ones not changed
$('input[type=submit]').each(function(){
$(this).submit(function(){
$('input[type=text]').each(function(){
if (defaults[$(this).attr('id')] === $(this).text())
$(this).text('');
});
});
});
});
If this still doesn't make any sense, you should read some tutorials about jQuery and/or javascript.
Note: This is currently only supported in Google Chrome and Safari. I do not expect this to be a satisfactory answer to your problem, but I think it should be noted how this problem can be tackled in HTML 5.
HTML 5 introduced the placeholder attribute, which does not get submitted unless it was replaced:
<form>
<input name="q" placeholder="Search Bookmarks and History">
<input type="submit" value="Search">
</form>
Further reading:
DiveintoHTML5.ep.io: Live Example... And checking if the placeholder tag is supported
DiveintoHTML5.ep.io: Placeholder text
1) Instead of checking for changes on the client side you can check for the changes on the client side.
In the Page_Init function you will have values stored in the viewstate & the values in the text fields or whichever controls you are using.
You can compare the values and if they are not equal then set the Text to blank.
2) May I ask, what functionality are you trying to achieve ?
U can achieve it by using this in your submit function
function clearDefaults()
{
if(document.getElementById('cs-Price-2').value=="Min. Price")
{
document.getElementById('cs-Price-2').value='';
}
}

Dynamically added JavaScript not finding dynamically added fields in IE

I have a table which has a button to "Add Rows". This button adds a row dynamically with JQuery. It works by copying the first ... and then replacing all the id=".." with an incremented number.
The problem is that the rows have a YUI AutoComplete which looks like the following:
<td>
<input type="hidden" name="location_num[0]" value="508318" maxLength="25" style="width:230px" id="location_num[0]"/>
<input type="textbox" name="location_numDisplayDesc[0]" value="WINNIPEG" maxLength="25" style="width:230px" id="location_numDisplayDesc[0]"/>
<div id="Container_location_num[0]" style="display:inline;"></div>
<script type="text/javascript">
// Initialize autocomplete
var location_numAC = new YAHOO.widget.AutoComplete(
"location_numDisplayDesc[0]",
"Container_location_num[0]",
locationDataSource,
acConfig);
location_numAC.useShadow = true
location_numAC.useIFrame = true
location_numAC.dataErrorEvent.subscribe(acErrorFunction);
// Format results to include the reference number
location_numAC.formatResult = function(resultItem, query) {
return resultItem[0];
};
// Clear key before request
location_numAC.dataRequestEvent.subscribe(function fnCallback(e, args) {
YAHOO.util.Dom.get("location_num[0]").value = ""; });
// Set key on item select
location_numAC.itemSelectEvent.subscribe(function(event, args) {
YAHOO.util.Dom.get("location_num[0]").value = args[2][1];
});
// Clear key when description is cleared
location_numAC.textboxBlurEvent.subscribe(function fnCallback(e, args) {
if (isEmpty(YAHOO.util.Dom.get("location_numDisplayDesc[0]").value)) {
YAHOO.util.Dom.get("location_num[0]").value = "";
} // end if
});
</script>
</td>
This code works fine in Firefox and the newly created AutoCompletes work, but in IE (6 & 7) I am getting an error that means that the location_num_AC is not being created successfully. I believe that it's because that it's not reading the newly created inputs or div as it should. I've tried wrapping the javascript with
$("Container_location_num[0]").ready(function {...});
but that didn't seem to work. Does anyone have any other ideas?
Form fields that are inserted into the DOM in IE don't add to the forms collection as you might expect.
Normally you can refer to a form field one of two ways:
document.forms[0]["myFormName"];
document.forms[0][12];
That is, by its form field name or by its index. But when you add a form field to the DOM in IE you can't refer to it by name, only by its index. If your code (or any supporting code) is looking for a form field in the collection by its name you've obviously got a problem.
If your only key is the name you can loop through all the form fields by index and find what you're looking for, but that's obviously going to be a linear operation. You can also loop through and find which form fields are indexed numerically but not by name and update the form object yourself.
I don't have enough detail to know how (or if) this is occurring in your project, but it's one of those IE quirks that sounds like it might be playing a role since you're adding fields dynamically.

Categories