I using an HTML / Javascript combination to add fields dynamically.
Here is the jsfiddle for it: http://jsfiddle.net/kM9Yg/2/
My problem is, if I input values in a field, and then click on the Add More button, a new field gets added but the previous fields' values get reset.
The button to add more is of type <input type="button"/> and not <input type="reset" />
Any way to prevent this?
Use DOM methods, not innerHTML. DOM methods are standardised, innerHTML is not. Some browsers will reflect the current value as the default value, others will not.
You can do:
var el, oEl = document.getElementById('divToClone');
if (oEl) {
el = oEl.cloneNode(true);
// code here to fix duplicate ids and
// set style.display = '' so it's visible
oEl.parentNode.appendChild(el);
}
Related
In the accepted answer to this question Multiple submit buttons in an HTML form the comment is raised:
Please don't do this without also changing the tab order, so that
hitting the tab button will cycle through the buttons as they appear
on screen.
My question is: is there a way to set the tabindex on those two buttons to accomplish this ordering without having to assign a specific tabindex to every other tabable element on the page?
My understanding of tabindex values is that specified positive values proceed elements w/o a specified value, so I am at a loss to figure out a way to do this w/o going through and assigning everything else a value.
If indeed, assigning a specific tabindex to every item is the only way, is there some (hopefully short and hopefully jQuery) magic to assign every appropriate element on the page a tabindex of, say, 1?
EDIT
As it looks like the solution is going to involve applying a specific tabindex to every other tabable object -- it seems like an important part of the solution is going to be: is there a convenient way in jQuery to select every tabable object? All s s s and ???
According to the specification:
positiv values assigned to tabindex orders the elements according to their tabindex values
negative values make elements "unfocusable"
a value of 0 makes the element focusable but its order dependents on the platform
mdn-html specification of tabindex
So if you want to have a specific order in your page you have to assign a value to each element.
But here comes jquery:
Say the elements which should be in order are in a div with id="myDiv"
You can then do:
$("#myDiv").find("*").prop("tabindex", 1);
This would make every child/subchild element of myDiv have a tabindex of 1.
Then your two buttons could have a css class assigned (e.g: class="highTabIndex").
Then you can call jquery again:
var idx = 2;
$("#myDiv").find(".highTabIndex").each(function(idx, element) {
element.prop("tabindex", idx++);
});
and your buttons with class highTabIndexwould be orderd according to "position" in the page.
Using Adding tabindex dynamically and fixing button indecies:
$(":input:not(:hidden)")
.each(function (i) {
$(this).attr('tabindex', i + 1);
});
var r = $('input.r').attr('tabindex');
$('input.r').attr('tabindex', $('input.l').attr('tabindex'));
$('input.l').attr('tabindex', r);
html:
<input type="submit" value="Next" class="r" />
<input type="submit" value="Previous" class="l" />
Plunk
Update - fixed query to select not only inputs (check link in John's comment below):
$("a[href],area[href],input:not([disabled]),select:not([disabled]),\
textarea:not([disabled]),button:not([disabled]),iframe,[tabindex],\
[contentEditable=true]")
So basically what I'm trying to do as a measure of security (and a learning process) is to my own "Capthca" system. What happens is I have twenty "label's" (only one shown below for brevity), each with an ID between 1 and 20. My javascript randomly picks one of these ID's and makes that picture show up as the security code. Each label has its own value which corresponds to the text of the captcha image.
Also, I have the submit button initially disabled.
What I need help with is figuring out how to enable the submit button once someone types in the proper value that matches the value listed in the HTML label element.
I've posted the user input value and the ID's value and even when they match the javascript won't enable the submit button.
I feel like this is a really really simple addition/fix. Help would be much much appreciated!!!
HTML code
<div class="security">
<label class="captcha enabled" id="1" value="324n48nv"><img src="images/security/1.png"></label>
</div>
<div id="contact-div-captcha-input" class="contact-div" >
<input class="field" name="human" placeholder="Decrypt the image text here">
</div>
<input id="submit" type="submit" name="submit" value="Send the form" disabled>
Javascript code
//Picks random image
function pictureSelector() {
var number = (Math.round(Math.random() * 20));
//Prevents zero from being randomly selected which would return an error
if (number === 0) {
number = 1;
};
console.log(number);
//Set the ID variable to select which image gets enabled
pictureID = ("#" + number);
//If the siblings have a class of enabled, remove it
$(pictureID).siblings().removeClass("enabled");
//Add the disabled class to all of the sibling elements so that just the selected ID image is showing
$(pictureID).siblings().addClass("disabled");
//Remove the disabled class from the selected ID
$(pictureID).removeClass("disabled");
//Add the enabled class to the selected ID
$(pictureID).addClass("enabled");
};
//Calls the pictureSelector function
pictureSelector();
//Gets the value of the picture value
var pictureValue = $(pictureID).attr("value");
console.log(pictureValue);
//Gets the value of the security input box as the user presses the keys and stores it as the variable inputValue
$("#contact-div-captcha-input input").keyup(function(){
var inputValue = $("#contact-div-captcha-input input").val();
console.log(inputValue);
});
console.log($("#contact-div-captcha-input input").val());
//Checks to see if the two values match
function equalCheck() {
//If they match, remove the disabled attribute from the submit button
if ($(pictureValue) == $("#contact-div-captcha-input input").val()) {
$("#submit").removeAttr("disabled");
}
};
equalCheck();
UPDATE
Fiddle here
UPDATE #2
$("#contact-div-captcha-input input").keyup(function(){
var inputValue = $("#contact-div-captcha-input input").val();
console.log(inputValue);
if (pictureValue === inputValue) {
$("#inputsubmit").removeAttr("disabled");
}
});
So I got it working 99.9%, now the only problem is that if someone were to backspace or delete the correct value they have inputted, the submit button does not then change back to disabled. Any pointers?
Known issue.
Give your button a name OTHER THAN submit. That name interferes with the form's submit.
EDIT
A link was requested for this -- I don't have a link for pure JavaScript, but the jQuery docs do mention this issue:
http://api.jquery.com/submit/
Forms and their child elements should not use input names or ids that
conflict with properties of a form, such as submit, length, or method.
Name conflicts can cause confusing failures. For a complete list of
rules and to check your markup for these problems, see DOMLint.
EDIT 2
http://jsfiddle.net/m55asd0v/
You had the CSS and JavaScript sections reversed. That code never ran in JSFiddle.
You never re-called equalCheck. I added a call to your keyUp handler.
For some reason you wrapped pictureValue inside a jQuery object as $(pictureValue) which couldn't have possibly done what you wanted.
Basic debugging 101:
A console.log inside of your equalCheck would have shown you that function was only called once.
A console log checking the values you were comparing would have shown
that you had the wrong value.
Basic attention to the weird highlighting inside of JSFiddle would have shown you had the code sections in the wrong categories.
I am using knockout.js. I created a view model say testViewModel with only 1 observable property testProperty.
function testViewModel()
{
var self = this;
self.testProperty = ko.observable("Initial");
}
than i created a span in which the changed value of testProperty is reflected and a input text field by which we can change the testProperty value.
<span data-bind="text: testProperty"></span><br />
<input type="text" data-bind="value: testProperty" />
I created an Example Fiddle.It seems that the observable property value is updated when the focusout event is executed on the input text field.
Now my question is that can we change the observable property value update event from focusout to something else. I created a save button also. Is there any way to update the observable property value only on save button press.
I am trying to create an application in which a user can create and save its profile and can edit the saved profile.I am using the same observable properties in create and edit form and these properties are observable. So when user edit its profile the ui should not
be updated until user press the save button. This is my goal. Please help me to solve this issue ?
I would suggest have testProperty and testProperty_temp. Bind the input to temp and when the button is clicked, set testProperty to the testProperty_temp
function testViewModel()
{
var self = this;
self.testProperty = ko.observable("Initial");
self.testProperty_temp = ko.obserable("");
self.save = function() { self.testProperty(self.testProperty_temp()); }
}
Hope this helps
Another means, along the same lines of what Matt Burland suggested:
http://jsfiddle.net/mori57/PQxJC/
Basically, wrap your input and button in a form, and bind the form to submit: which is handled by a method on your ViewModel. See the comments I've made inline, but here it is for people who don't want to go out to jsFiddle:
<span data-bind="text: testProperty"></span><br />
<!-- wrap the input and button in a form and
data-bind to submit, with a reference
to a handler on your viewmodel -->
<form data-bind="submit: updateProfile">
<!-- this must be bound to your shadow value -->
<input type="text" data-bind="value: _tmpTestProperty" />
<button type="submit">save</button>
</form>
and in your javascript
function testViewModel()
{
var self = this;
self.testProperty = ko.observable("Initial");
// Create the "shadow" property
// and prepopulate it with testProperty's value
self._tmpTestProperty = ko.observable(self.testProperty());
// Create our form handler
self.updateProfile = function(val){
// set the testProperty value to the
// value of the shadow property
self.testProperty(self._tmpTestProperty());
};
}
ko.applyBindings(new testViewModel());
In this way, your value doesn't change when you lose focus on the text input box, but is only updated when you submit the form.
Your simplest approach would be to have a shadow property for each of your properties. So you bind one to your text boxes and only copy the value to the other property, the one bound to the other UI elements, when save is clicked.
See here: http://jsbin.com/aguyud/5/edit
An easier way using two models and $.extend to copy from one to the other:
http://jsbin.com/aguyud/7/edit
Update, actually scratch that, that doesn't seem to work. I tried this instead:
http://jsbin.com/aguyud/22/edit
which works the first time, but after copying the model with $.extend it seem it's copied all the bindings too, so it only works once!
Using jQuery, I change the value of an input text field through some process. After the process is done, I need to capture this change and apply it to another process. My problem is that I can't seem to capture this change and assign it to a variable. I know the changes are happening because the DOM is getting updated. Furthermore, this variable assignment works in IE, but not for the other browsers I tested.
Below is a snippet to prove my point (and you can see this online here: http://jsfiddle.net/xMwAE/).
<form>
<input type="hidden" name="my_hidden" value="Hidden Field" />
<input type="text" name="my_text" value="Text Field" />
</form>
$().ready(function() {
$('input[name=my_hidden]').val('Hello Hidden Field');
$('input[name=my_text]').val('Hello Text Field');
// Display
var temp = $('form').html();
// Though the DOM is updated with the new values. The variable temp
// does not capture the changes to the input text field, but captures
// the change in the hidden field. When in IE, temp captures the
// changes in both fields.
alert(temp);
});
Obviously, I need consistent behavior across browsers. Any ideas what's going on?
I don't get any trusted idea what happens, but somehow there should be a difference between setting the value as a member (input.value) or setting the value as a attribute-node.
This works for me :
$('input[name=my_text]').each(function()
{ this.setAttribute('value','Hello Text Field');});
I guess its a bug in innerHTML, see bugzilla: https://bugzilla.mozilla.org/show_bug.cgi?id=535992
Alternatively, you can store the values of your fields into array and use however you like like this:
var data = [];
$('form :input').each(function(){
data.push(this.value);
});
Now you can check for values like this:
alert(data[0]);
alert(data[1]);
Unfortunately form.reset() function doesn't reset hidden inputs of the form.
Checked in FF3 and Chromium.
Does any one have an idea how to do the reset for hidden fields as well?
Seems the easiest way of doing that is having <input style="display: none" type="text"/> field instead of <input type="hidden"/> field.
At this case default reset process regularly.
This is correct as per the standard, unfortunately. A bad spec wart IMO. IE provides hidden fields with a resettable defaultValue nonetheless. See this discussion: it's not (alas) going to change in HTML5.
(Luckily, there is rarely any need to reset a form. As a UI feature it's generally frowned upon.)
Since you can't get the original value of the value attribute at all, you would have to duplicate it in another attribute and fetch that. eg.:
<form id="f">
<input type="hidden" name="foo" value="bar" class="value=bar"/>
function resetForm() {
var f= document.getElementById('f');
f.reset();
f.elements.foo.value= Element_getClassValue(f.elements.foo, 'value');
}
function Element_getClassValue(el, classname) {
var prefix= classname+'=';
var classes= el.className.split(/\s+/);
for (var i= classes.length; i-->0;)
if (classes[i].substring(0, prefix.length)===prefix)
return classes[i].substring(prefix.length);
return '';
}
Alternative ways of smuggling that value in might include HTML5 data, another spare attribute like title, an immediately-following <!-- comment --> to read the value from, explicit additional JS information, or extra hidden fields just to hold the default values.
Whatever approach, it would have to clutter up the HTML; it can't be created by script at document ready time because some browsers will have already overridden the field's value with a remembered value (from a reload or back button press) by that time that code executes.
Another answer, in case anyone comes here looking for one.
Serialize the form after the page loads and use those values to reset the hidden fields later:
var serializedForm = $('#myForm').serialize();
Then, to reset the form:
function fullReset(){
$('#myForm').reset(); // resets everything except hidden fields
var formFields = decodeURIComponent(serializedForm).split('&'); //split up the serialized form into variable pairs
//put it into an associative array
var splitFields = new Array();
for(i in formFields){
vals= formFields[i].split('=');
splitFields[vals[0]] = vals[1];
}
$('#myForm').find('input[type=hidden]').each(function(){
this.value = splitFields[this.name];
});
}
You can use jQuery - this will empty hidden fields:
$('form').on('reset', function() {
$("input[type='hidden']", $(this)).val('');
});
Tip: just make sure you're not resetting csrf token field or anything else that shouldn't be emptied. You can narrow down element's specification if needed.
If you want to reset the field to a default value you can use(not tested):
$('form').on('reset', function() {
$("input[type='hidden']", $(this)).each(function() {
var $t = $(this);
$t.val($t.data('defaultvalue'));
});
});
and save the default value in the data-defaultvalue="Something" property.
I found it easier to just set a default value when the document is loaded then trap the reset and reset the hidden puppies back to their original value. For example,
//fix form reset (hidden fields don't get reset - this will fix that pain in the arse issue)
$( document ).ready(function() {
$("#myForm").find("input:hidden").each(function() {
$(this).data("myDefaultValue", $(this).val());
});
$("#myForm").off("reset.myarse");
$("#myForm").on("reset.myarse", function() {
var myDefaultValue = $(this).data("myDefaultValue");
if (myDefaultValue != null) {
$(this).val(myDefaultValue);
}
});
}
Hope this helps someone out :)
$('#form :reset').on('click',function(e)({
e.preventDefault();
e.stopImmediatePropagation();
$("#form input:hidden,#form :text,#form textarea").val('');
});
For select, checkbox, radio, it's better you know (hold) the default values and in that event handler, you set them to their default values.
Create a button and add JavaScript to the onClick event which clears the fields.
That said, I'm curious why you want to reset these fields. Usually, they contain internal data. If I would clear them in my code, the post of the form would fail (for example after the user has entered the new data and tries to submit the form).
[EDIT] I misunderstood your question. If you're worried that someone might tamper with the values in the hidden fields, then there is no way to reset them. For example, you can call reset() on the form but not on a field in the form.
You could think that you could save the values in a JavaScript file and use that to reset the values but when a user can tamper with the hidden fields, he can tamper with the JavaScript as well.
So from a security point of view, if you need to reset hidden fields, then avoid them in the first place and save the information in the session on the server.
How I would do it is put an event listener on the change event of the hidden field. In that listener function you could save the initial value to the DOM element storage (mootools, jquery) and then listen to the reset event of the form to restore the initial values stored in the hidden form field storage.
This will do:
$("#form input:hidden").val('').trigger('change');
You can reset hidden input field value using below line, you just need to change your form id instead of frmForm.
$("#frmForm input:hidden").val(' ');