How do you store object references in HTML elements? - javascript

I am building a form in HTML out of a javascript object that I've imported from a JSON file.
I use a recurisve algorithm to build HTML tables, and respective elements (labels, text boxes, etc.)
The fields load with the value of the current node.
The idea is to edit the values in the textboxes; which in turn updates the javascript object. When
changes have been made, the editor will send the JSON object to the server and update the file.
The puzzling question, is how do I reference the node that has been changed? I have tried several
approaches to no avail.
EDIT:
This is a basic idea of what I'm doing:
function build_tree(obj, depth) {
for (key in obj) {
if (typeof(obj[key]) == 'object') {
print(key + "<input type="text" value='" + obj[key] + "'>");
build_tree(obj[key], depth + 1);
} else
print(key + "<input type="text" value='" + obj[key] + "'>");
}
Now, how do I bind the value of obj[key] to the text boxes, so that when I change the
value it updates the Javascript object?

document.getElementById('name').changed = true;
So now the DOM element has the property 'changed'. You can also use any other value (dates, arrays, etc)

First off you need a way to individually identify the input so, i would add a data-key attribute.
function build_tree(obj, depth) {
for (key in obj) {
if (typeof(obj[key]) == 'object') {
print(key + "<input type="text" value='" + obj[key] + "' data-key= '"+key+"'>");
build_tree(obj[key], depth + 1);
} else
print(key + "<input type="text" value='" + obj[key] + "' data-key= '"+key+"'>");
}
Then i would attach a change event handler to each text input, after the tree is built.
$('input[type="text"]').on('change',function(){
var key = $(this).data('key');
obj[key] = $(this).val();
});
obj would be a global array. Hope this makes sense.

An approach I have seen many others use is a special attribute with data- prefixed.
For example:
<div id="pie" data-like-pie="true">I do like pie.</div>
Then, to find the attribute with JavaScript:
likesPie = document.getElementByID("pie").getAttribute("data-like-pie");
Or with jQuery:
likesPie = $("#pie").data("like-pie");
As you can see, jQuery's data method automatically prepends data- to the front of the attribute.

You should take a look at knockoutjs. It has an entire binding engine that updates values between html and object model automatically. So all you need to do is to send back your JSON model whenever the right values has been entered into your textboxes or whatever you use to update your values.

This will update your original model (global obj) when the generated textboxes change.
When using your print function:
print(key + "<input type="text" value='" + obj[key] + "'>");
update it to something like:
print(key + "<input type="text" value='" + obj[key] + "' data-object-key='" + key + "' >");
And in your JS, if using JQuery you want to listen to all changes on your input elements.
Add a class if necessary.
$("input[type='text']").change(function()
{
var key = $(this).data("object-key");
obj[key] = $(this).val();
});

Related

Radiobuttons set attribute checked is not working in function

Why is this not working with JQuery?
The property wont be checked to true so or with asnyc function... I tried everything, but it only will working if i set the attribute checked true in browser at console. Not even with outsourced async callback functions.
for (var i = 0; i < user.benutzer.length; i++)
{
var user_var = user.benutzer[i].benutzer;
user_rep = user_var.replace(/ /g, '_');
$('#div_buttongroup').append('<label for="' + user_rep + '" class="btn btn-primary" id="label_'+user_rep+'"><input type="radio" class="user_radio" id="' + user_rep + '" value="' + user_var + '" name="radio" autocomplete="off"></input>' + user_var + '</label>');
if (i === 0)
{
t = user_rep;
$('#label_'+user_rep).addClass("btn btn-primary active");
$('#'+user_rep).prop("checked",true);
}
}
The difference between attributes and properties can be important in specific situations. Before jQuery 1.6, the .attr() method sometimes took property values into account when retrieving some attributes, which could cause inconsistent behavior. As of jQuery 1.6, the .prop() method provides a way to explicitly retrieve property values, while .attr() retrieves attributes.
$('#'+user_rep).attr("checked");
I think it was a JQuery bug in combination with radiobuttons. I used a selectbox and everything was working

Check value of input field regardless of type

I've seen and read this question. Didn't quite find my answer there.
I have some code that accept an html template, and uses that template inside a form.
That template will contain x number of input fields.
Is there a way to check for a value in those input fields generically?
Kinda like this:
var inputFields = element.getElementsByTagName('input');
inputFields.forEach(function (element) {
var value = element.value;
// ... something
});
I know that won't work, but you get the idea.
I think I have to write special cases for different input types, but i thought I'd ask if anyone have any experience with this problem.
This is done in pure JavaScript, so I don't really need jQuery. Unless you have a really neat way to do it in jQyery, compared to just plain JavaScript.
EDIT: I need to check if any input has been entered into the field, whether it is a file or text. I need to remove the name attribute on those who have no value.
Using the following, I can't see that you need any special handling for different types. You can just read the value property:
<script>
var t = '<table>';
var inputTypes = ('hidden text tel url email password datetime date month week' +
' time number range color checkbox radio file submit image' +
' reset button').split(' ');
var type;
for (var i=0, iLen=inputTypes.length; i<iLen; i++) {
type = inputTypes[i];
value = type == 'number'? 10 : 'input type ' + type;
t += '<tr><td>' + type + '<td><input type="' + type +
'" name="' + type + 'Input" value="' + value + '">';
}
document.write(t + '<\/table>');
</script>
<button onclick="getValues(document.getElementsByTagName('input'))">Get values</button>
<script>
function getValues(inputs) {
var input;
for (var i=0, iLen=inputs.length; i<iLen; i++) {
input = inputs[i];
console.log(input.name + ': ' + input.value);
}
}
</script>
You may want to check that checkboxes and radios are checked. For that, getting the value can be:
if (input.type in {radio:'', checkbox:''}) {
if (input.checked) {
// get value
}
} else {
// get value
}

If both select values have been selected run function

Im trying to populate and show a select if the previous 12 dropdowns have a value.
I cant seem to get my if statement correct though, can anybody see what I may be doing wrong?
$('select').on('change',function(){
if( $('.player1') != null || $('.player2') != null ){
// If both players have been selected, show the winner dropdown and populate it with the value from player1 and player 2.
$('.winner').show();
}
});
http://jsfiddle.net/kbPLn/1/
A jQuery object will never equal null. What you can do is check the length property of the collection. Also, it looks like you want && instead of ||.
if ($('.player1>option:selected').length && $('.player2>option:selected').length) {
EDIT: What you rather need to do is check if it has a selected child option.
the cases you have will never be null.. (as youre not checking .val...and also, they always have a val) updated your HTML + your selectors here:
http://jsfiddle.net/kbPLn/5/
if( $('.player1>option:selected').val() != "No value" && $('.player2>option:selected').val() != "No value" ){
updated
http://jsfiddle.net/kbPLn/9/
var first = $('.player1>option:selected').val(),
second =$('.player2>option:selected').val();
$('.winner').find('option:first').val(first).html(first);
$('.winner').find('option:not(:first)').val(second).html(second);
$('.winner').show();
you need to use && when checking negation values
Try this. This may help you:
$('select').on('change', function () {
$('select[name="winner"]').html('');
if ($('.player1') != null || $('.player2') != null) {
// If both players have been selected, show the winner dropdown and populate it with the value from player1 and player 2.
$('.winner').show();
//$('.winner').
}
$('select[name="winner"]').append('<option value="' + $(".player1").val() + '">' + $(".player1").val() + '</option>');
$('select[name="winner"]').append('<option value="' + $(".player2").val() + '">' + $(".player2").val() + '</option>');
});

jQuery .each() index value

I’ve been teaching my self JavaScript and jQuery for a few months, but I’m still getting confused with JavaScript objects and jQuery objects.
In the following example I assigned a jQuery object to the variable $target. The $target should consist of an array of two objects.
My question is why I have to wrap the value variable again into the jQuery object in .each() function ?
$('select.to_append').change(function(){
var $target = $('select.to_append');
var $form = $('#anotherForm');
$.each($target, function(key, value){
$form.append('<input name="' + $(value).attr('name') + '" type="hidden" value="' + $(value).val() + '"></input>');
});
});
The sample code I use to append values from selects which are not parts of the form being submitted;
because $target is a jQuery object, but when you iterate you will get a dom element reference in your iteration handler not a jQuery object. So if you want to access jQuery methods on that object you need to wrap the object again.
By the way to iterate over a jQuery object you can use .each() instead of jQuery.each()
$('select.to_append').change(function () {
var $target = $('select.to_append');
var $form = $('#anotherForm');
$target.each(function (index, el) {
$form.append('<input name="' + $(el).attr('name') + '" type="hidden" value="' + $(el).val() + '"></input>');
});
});

Converting pairs of input elements into json

I have a simple ui which has a link that says "add item". When this is clicked, a pair of input boxes appears below it. If it is clicked again, yet another pair appears. I'm trying to think of the best way to generate these elements and turn it into some sort of json array of key value pairs (the first input element in each pair being the key and the second input element being the value).
Right now I just have a counter and I generate the ids using it, such as (in the click event of the "add item" link):
$('#features').append('<input id="feature-name-' + self.featureCount + '" type="text" name="asdf" /><a class="delete-feature" data-id="' + self.featureCount + '">Delete</a><input id="feature-description-' + self.featureCount + '" type="text" name="asdf" />');
I don't know what to use as the "name" attributes in order to make it easy to create a json array from them.
you can do something like this without using id attributes.
$('#features').append('<div><input type="text" />
<a class="delete-feature" data-id="' + self.featureCount + '">Delete</a><input type="text" /></div>');
And your javascript,
var yourArray=[];
$('#yourButton').click(function(){
$('#features div').each(function(){
var div=$(this);
var k=$('input:first',div).val();
var v=$('input:first',div).next().val();
yourArray.push({key:k, value: v});
});
});
It doesn't matter what you use for a name attribute, so long as there name and description names are different. Let's say that these elements are all appended to a form with the id myform. Give each pair its own wrapper object. Here, I've used a div, but a fieldset is equally appropriate.
$('#features').append(
'<div class="feature-div">
'<input id="feature-name-' + self.featureCount + '" type="text" name="asdf" />' +
'<a class="delete-feature" data-id="' + self.featureCount + '">Delete</a>' +
'<input id="featurena-description-' + self.featureCount + '" type="text" name="asdf" />' +
'</div>');
Now, it's possible to extract each pair sensibly:
var myarray = [];
$('#myform .feature-div').each(function(i, v) {
myarray.push([
$('input[name=name]', v).val(), $('input[name=description]', v).val()]);
});
Or however you want the data to be presented.

Categories