Got a strange thing going on, really don't have a idea how to solve this one. Neither did I find useful stuff when googleing.
I have a html form that includes this:
<label for="gebied">Gebieden</label>
<div class="button button-selected"><input type="checkbox" name="areas" value="nederland" checked="checked" />Nederland</div>
<div class="button button-selected"><input type="checkbox" name="areas" value="europa" checked="checked" />Europa</div>
<div class="button button-selected"><input type="checkbox" name="areas" value="wereld" checked="checked" />De Wereld</div>
Then with javascript (jQuery) I check which are checked and which are not:
var areas = [];
$('input[name=areas]:checked').each(function(){
areas.push($(this).val());
});
This is called from within createShortUrl();, below in the relevant code:
$(function() {
//Handle things when a buttons is clicked
$("div.button").click(function() {
//Find the input field for the clicked div
var input = $(this).find(':input');
var inputName = $(input).attr('name');
//Handle checkboxes, which define the gebied
if ($(input).is(':checkbox')) {
//Change the classes
input.prop('checked', !input[0].checked);
$(this).toggleClass('button-selected');
}
//Handle radio
if ($(input).is(':radio')) {
$('form').find('input[name=' + inputName + ']').each(function() {
$(this).parent('div').toggleClass('button-selected');
$(this).prop('checked', !input[0].checked);
});
}
//Clicking means something chanhes; create a new short url
createShortUrl();
});
});
The strange thing is that when in Firefox, when I have earlier checked some of them, they stay in the areas array. Even when I uncheck some of them, they stay in the array and vice versa. But when debugging in Safari, it works like a charm!
When I then uncheck every thing, the array is empty. Recheck some, and there in the array.
So, any ideas, what's going on with Firefox? It looks like FF is caching, even after couple of times refreshing, the previous array. Despite my
var areas = []
in which I hoped to empty it and rebuild it....
It's live at here, fired after the large button on the bottom is clicked.
Any thoughts are more then welcome!
The issue is with your event handler. The problem is, the way you are modifying the state of the element does not work in Firefox. You should use attr() instead of prop() to change the checked state.
Working code: Replaced .prop() with .attr().
//Handle things when a buttons is clicked
$("div.button").click(function() {
console.log("Click");
//Find the input field for the clicked div
var input = $(this).find(':input');
var inputName = $(input).attr('name');
//Handle checkboxes, which define the gebied
if ($(input).is(':checkbox')) {
//Change the classes
console.log("check");
input.attr('checked', !input[0].checked);
$(this).toggleClass('button-selected');
}
//Handle radio
if ($(input).is(':radio')) {
$('form').find('input[name=' + inputName + ']').each(function() {
$(this).parent('div').toggleClass('button-selected');
$(this).attr('checked', !input[0].checked);
});
}
//Clicking means something chanhes; create a new short url
createShortUrl();
});
You are pushing the values (these are strings) of the inputs into a static array. There is no reason for this array to be updated in tandem with the DOM, in Firefox or in any other browser.
If you were to store the DOM elements themselves in the array and retrieve values from those, that would be a different story.
Related
Please see my fiddle here
I have a couple of radio buttons and depending if one of them is selected I want a text box to then show. I have been able to achieve this using knockout.
What I want to happen is when the page loads, if the value of the "Timesheet" radio button is checked I want the text box to show. But I've been unable to work out how to do this. Thanks is advance.
See below my knockout code:
function K2ConsultantApprovalViewModel() {
var self = this;
self.timeSheetSelected = ko.observable("");
}
ko.applyBindings(new K2ConsultantApprovalViewModel());
If the checked binding is applied to a radio button, it will set the element to be checked when the parameter value equals that of the radio button element's value attribute. So you need to slightly change your way of thinking and create a "payment type" observable that stores the chosen payment type, rather than the boolean "is timesheet selected?" observable that you have now. You can then initially give this observable the value "Timesheet", and that will be what is selected on page load. It also makes it trivial to show or hide any other elements based on the current selection.
function K2ConsultantApprovalViewModel() {
var self = this;
self.paymentType = ko.observable("Timesheet");
}
ko.applyBindings(new K2ConsultantApprovalViewModel());
And binding would look like this:
<input id="DisbursementsOrTimeSheet_ChoiceField0" type="radio" name="DisbursementsOrTimeSheetChoice" value="Disbursements" data-bind="checked: paymentType">
Update Fiddle here.
Update
I would not recommend this since it's a backwards way of working, but if the initial value of your checked binding has to come from the input element itself, you could create a small binding handler that is executed before the checked binding.
ko.bindingHandlers['initChecked'] = {
init: function (element, valueAccessor, allBindings) {
var checked = valueAccessor();
if (element.checked) {
checked(element.value);
}
}
};
Then bind like this:
<input id="DisbursementsOrTimeSheet_ChoiceField1" type="radio" name="DisbursementsOrTimeSheetChoice" value="Timesheet" data-bind="initChecked: paymentType, checked: paymentType" checked="checked">
It will work (proof). But the proper way to do this would be to get the data in the view model and, as someone well put it in the comments, cut out the middle man.
Tried to solve this multiple ways. 1. by simply adding the normal html "checked" default option to radio buttons in my form and 2. having js functions do it, being the gist of the ideas tried.
The issue: I'm finding that no matter how I do it, if the radio is designated as checked by default (before the user makes his/her choice), anything done after that will not be saved correctly (if at all) in localStorage. localStorage WILL save the initial default selections, however but, nothing can be changed from then on (even after "physically" selecting another option).
I know localStorage is working because if I leave off the default designation (and for the rest of the inputs) it functions perfectly.
The form code:
<label>Who is the contact person for this event?<span class="requiredtext">*</span></label>
<input type="radio" name="Contact_Person" id="Contact_Person1" value="Submitter is the contact person" onclick="contacthide()" checked required> I am<br />
<input type="radio" name="Contact_Person" id="Contact_Person2" value="Submitter is not the contact person" onclick="contactshow()" required>
The localStorage save code:
function localStoragefunctions() {
localStorage.clear();
if (Modernizr.localstorage) {
//Set variable to show that data is saved
localStorage.setItem("flag", "set");
//Save radio and checkbox data
$(window).bind('unload', function() {
$('input[type=radio]').each(function() {
localStorage.setItem('radio_' + $(this).attr('id'), JSON.stringify({
checked: this.checked
}));
});
});
The code that spits it back out if the user goes back to make changes before final submission:
$(document).ready(function() {
if (Modernizr.localstorage) {
//Browser supports it
if (localStorage.getItem("flag") == "set") {
$('input[type=radio]').each(function() {
var state = JSON.parse(localStorage.getItem('radio_' + $(this).attr('id')));
if (state) this.checked = state.checked;
});
Other than this, I have a confirmation page that grabs all of the variables stored in localStorage and presents them to the user for final inspection before they hit submit for good.
That consists of: var ContactPerson = localStorage.getItem('Contact_Person'); and then a document.write that spits out html and the variable's value. Again, this works fine if I don't try to set default radio choices (and works great for all other input types).
The ideal outcome would be choosing the most likely radio button choices by default so that it could possibly save the user time. I'd like to not have to present them with a form where they have to physically click each radio button if I can "make that decision for them" before hand.
Hope this all makes sense!
I know this an old question, but I've been troubleshooting a similar issue and thought I'd share my solution.
When you set your localStorage item, you are saving both radio inputs and their values, b/c your using the ID attribute as your key.
localStorage.setItem('radio_' + $(this).attr('id'), JSON.stringify({ checked: this.checked }));
This could be ok, but I've taken a different approach. And, I maybe missing something, so comments are welcome.
Instead, I use $(this).attr('name') to set the key. As a result, when either radio button in selected, you are saving the value to the same localStorage key.
In my scenario, I'm storing many inputs to localStorage, so my solution is a bit abstract. I'm calling saveToLocalStorage() using jQuery's .change() method on each input. Also, I'm saving the input's value directly to localStorage.
function saveToLocalStorage(input) {
if ( $(input).attr('type')=='radio' ) {
localStorage[$(input).attr('name')] = $(input).val();
} else {
localStorage[$(input).attr('id')] = $(input).val();
}
}
When retrieving from localStorage, I had to check if the localStorage key:value pair matched the radio input before selecting it. Otherwise, I was selecting both radio inputs. Note, in my scenario, I'm working with jQuery 1.4.4, hence the attr('checked', 'checked').
$('input[type=radio]').each(function() {
var key = $(this).attr('name');
var val = localStorage[key];
if ( $(this).attr('name') == key && $(this).attr('value') == val ) {
$(this).attr('checked', 'checked');
}
});
I have a website with a form. The form is filled by user with data for example i show to user:
<input type='text' value="" name="dsa" />
And he fills it with value of "3";
And he clicks button "save". Now i want to have the whole HTML of the website including values of fields. So i use:
document.documentElement.innerHTML
But i get:
<input type='text' value="" name="dsa" />
But i want to get this:
<input type='text' value="3" name="dsa" />
NOTICE I want to take the whole HTML of the website, not only one field. I dont know what fields will be on the website so i need a general solution.
AFAIK you can't get this from the HTML code, as the HTML code does not change when the user inputs something in a Input text field.
What you could do is get all input fields on the page and get their values with something like this:
var inputs, index;
inputs = document.getElementsByTagName('input');
for (index = 0; index < inputs.length; ++index) {
// deal with inputs[index] element.
}
The code is from this post: https://stackoverflow.com/a/2214077/312312
I was too lazy to write it down my self :P
In jQuery I do
$(function() {
$('input').keyup(function() {
$(this).attr('value', $(this).val());
});
});
Because the value attribute isn't set after key up
You could try to set a live event on a whole document that will set attribustes to html with values user set in or set them on your submit.
First way for example
$("body").on("change", "select,input,textarea", function(){
$(this).attr("value", $(this).val());
});
But this should not be done so blindly, and you'll get problems with reset. And you should solve problem with selected radio, checkbox and other attributes, not only values.
Second way is to serialize whole page when it really needed.
var serialize = function(el){
$("select, input, textarea").each(function(){
$(this).attr("value", $(this).val()); //the same way as upper
});
}
$(".serialize").click(function(){
var inner = $("body"),
html;
serialize(inner);
html = inner.html(); //here you will get whole html with setted attributes
});
This way seems to be better because there wont be delegation of unnecessary event.
http://jsfiddle.net/CeAXL/2/ - test example.
But in both ways it's not good idea to set permanent values to DOM itself.
Following code is generated by a for loop.
<form action="saveresponse.php" method="POST" name="mainForm">
<input class="cbox_yes" type="checkbox" name="yes[]" value="01.jpg"
onclick="spenable()" /> OK
<input class="cbox_sp" type="checkbox" name="sp[]" value="01.jpg" disabled />Special<br />
<input class="cbox_yes" type="checkbox" name="yes[]" value="02.jpg"
onclick="spenable()" /> OK
<input class="cbox_sp" type="checkbox" name="sp[]" value="02.jpg" disabled />Special<br />
etc etc upto n times...
Now, what I want is that on page load, all the sp[] checkboxes should be disabled and enabled only if their corrosponding yes[] checkbox is checked by user.
Javascript code I am using: (Just to check if JS is capturing the states of yes[] checkbox?
function spenable(){
var yes = document.mainForm.yes[].value;
if (yes == true)
//alert("true");
document.mainForm.yes[].value = checked;
else
//alert("false");
document.mainForm.yes[].value = checked;
};
};
But I am not getting any alert (Neither Yes, Nor No).
So, is yes[] (Square brackets) in second line is incorrect? Or my if/else condition is wrong in JS?
P.S. All the questions here at SO or on Google deal with only one case/pair.
P.S. If required, I can change yes[] to yes1, yes2, yes3 etc and corresponding sp1, sp2, sp3 where 1,2,3 is $i of For loop, but then how will I capture/refer to it in JS?
_UPDATE:_
The flow/conditions are(Clarification):
Initially Special checkbox will be disabled and OK checkbox will be unchecked.
Then if user checks Ok, Special gets enabled.
If user want, he can tick Special.
If, later, user changes mind and untick the OK, Special should be unticked as well as disabled again.
I used jQuery here for the sake of simplicity.
$("input[name='yes[]']").change(function() { //When checkbox changes
var checked = $(this).attr("checked");
$(this).next().attr("disabled", !checked); //The next checkbox will enable
}); // or disable based on the
// checkbox before it
Demo: http://jsfiddle.net/DerekL/Zdf9d/
Pure JavaScript: http://jsfiddle.net/DerekL/Zdf9d/1/
Update
It will uncheck the first checkboxes when the Special checkbox is checked.
Pure JavaScript: http://jsfiddle.net/DerekL/Zdf9d/2/
More Updates
Here's the demo:
Pure JavaScript: http://jsfiddle.net/DerekL/Zdf9d/3/
jQuery: http://jsfiddle.net/DerekL/Zdf9d/4/
Little note: document.querySelectorAll works on all modern browsers and IE8+ including IE8. It is always better to use jQuery if you want to support IE6.
You can't use yes[] as an identifier in the Javascript, so you have to access the field using the name as a string:
document.mainForm["yes[]"]
This will not return a single element, it will return an array of elements. Use an index to access a specific element:
document.mainForm["yes[]"][0]
The value of the checkbox will always be the value property, regardless of whether the checkbox is selected or not. Use the checked property to find out if it's selected:
function spenable() {
var yes = document.mainForm["yes[]"][0].checked;
if (yes) {
alert("true");
} else {
alert("false");
};
}
To access the specific checkbox that was clicked, send the index of the checkbox in the event call:
<input class="cbox_yes" type="checkbox" name="yes[]" value="01.jpg" onclick="spenable(0);" /> OK
Use the index in the function:
function spenable(idx) {
var yes = document.mainForm["yes[]"][idx].checked;
var sp = document.mainForm["sp[]"][idx];
sp.disabled = !yes;
}
If you are open to using jQuery:
$('input[type="checkbox"]').click(function(){
var obj = $(this);
obj.next('.cbox_sp').attr({'disabled':(obj.is(':checked') ? false : 'disabled')});
});
This solution will assign an onclick event handler to all checkboxes and then check to see if the corresponding "special" checkbox should be disabled or not. It also sets the default checked state to true.
Working Example: http://jsfiddle.net/6YTqC/
I have a page that displays a list of records. The user can select the record status using radio buttons, e.g.:
<div id="record_653">
<label><input type="radio" name="status_653" value="new" checked/>new</label>
<label><input type="radio" name="status_653" value="skipped" />skipped</label>
<label><input type="radio" name="status_653" value="downloaded" />downloaded</label>
</div>
I am using JQuery to send the changes made by the user back to the server, where I use them to update the database. This is a simplified version of what I do:
$("#record_653").click(
function(event) {
var url = ...,
params = ...;
post(url,params);
});
The problem is that this code will create requests even if the user clicks the same button that was previously checked. What I actually want is the "on change" event, except its behavior in Internet Explorer is not very useful (e.g. here).
So I figure I somehow have to identify if the click event changed the value.
Is the old value stored somewhere (in the DOM? in the event?) so I could compare against it?
If not, how should I store the old value?
The old value is not stored someplace where you can query it, no. You will need to store the value yourself. You could use a javascript variable, a hidden input element, or jQuery's data() function.
EDIT
The jQuery data function provides access to a key-value-pair data structure as a way to store arbitrary data for a given element. The api looks like:
// store original value for an element
$(selector).data('key', value);
// retrieve original value for an element
var value = $(selector).data('key');
A more developed thought:
$(document).ready(function() {
// store original values on document ready
$(selector).each(function() {
var value = $(this).val();
$(this).data('original-value', value);
})
// later on, you might attach a click handler to the the option
// and want to determine if the value has actually changed or not.
$(selector).click(function() {
var currentValue = $(this).val();
var originalValue = $(this).data('original-value');
if (currentValue != originalValue) {
// do stuff.
// you might want to update the original value so future changes
// can be detected:
$(this).data('original-value', currentValue);
}
});
});
$('#record_653 input:radio').each(function() {
$(this).data('isChecked', $(this).is(':checked'));
$(this).click(function() {
if ( $(this).is(':checked') !== $(this).data('isChecked') ) {
// do changed action
} else {
$(this).data('isChecked', !$(this).data('isChecked') );
}
})
});
This was complicated to do in my head but I think you want something like this.
As was suggested by meder and Ken Browning, I ended up using JQuery's data() to store the previous value and check against it on every click.
Storing an "is checked" boolean for each input radio is one solution. However you need to maintain this value. So in the click event handler, in addition to changing the "is checked" of the current input, you need to find the input that was previously checked and change its "is checked" data to false.
What I chose to do instead was to store, in the parent element, the currently checked object. So my code looks something like:
$(document).ready(
function() {
// find the checked input and store it as "currChecked" for the record
$("#record_653").data("currChecked",
$(this).find("input:radio:checked")[0]);
// add the click event
$("#record_653").click( function(event) {
if ($(event.target).is("input:radio") &&
event.target !== $(this).data("currChecked"))
{
$(this).data("currChecked", event.target);
handleChangeEvent(event);
}
});
});
}
);
Thanks
I had the same problem, but with FF I managed to deal with it using the onchange event rather than the onclick.
This is exactly what I was looking for to deal with IE7. Works like a charm!
Thanks for the detailed solution!