An unwanted object in the last cell of an array - javascript

I'm using the following code on a parsed XML array:
$(this).find("cp_group").each(function() {
$("select#comp_1").append('<optgroup label="' + $(this).attr('label') + '"><option>' + $(this).find("cmp").map(function() {
return $(this).text();
}).get().join("</option><option>") + $(this).append('</option></optgroup>'));
});​
And i get an unwanted [object Object] in the last option of each option group as following:
<select name="comp_1" id="comp_1">
<optgroup label="Combat">
<option>Arme</option>
<option>Arts martiaux</option>
<option>Esquive</option>
<option>Feinte</option>
<option>Parade</option>
<option>Lutte[object Object]</option>
I dont understand from where this [object Object] come from and I didn't achieve to not get it or to remove it.
Thanks for you help.

It's coming from the + $(this).append(...). You just want the +'</option....' part, without that jQuery wrapper.

You've misunderstood how jQuery, and in particular append, works. When you're manipulating things with jQuery, you're not dealing with markup (largely), you're dealing with objects (DOM elements).
This should fix it:
$(this).find("cp_group").each(function() {
// Get this entry
var $this = $(this);
// Create the optgroup
var optgroup = $('<optgroup label="' + $this.attr('label') + '">');
// Fill it in
$this.find("cmp").each(function() {
$("<option>").text($(this).text()).appendTo(optgroup);
});
// Append it to the select
$("select#comp_1").append(optgroup);
});​

Related

Having difficulty building a form summary with JS

Sorry for the noobish question but, I am trying to build a form summary that will populate a div (immediately) with all of the fields being used. Here is a small sample of the field: Fiddle
For some reason the JS is not working as I would expect it to, can anyone point out what I am doing wrong?
For example, I would like it to output: "AND name: john EXCEPT number 222".
I would also like to be able click on a result to remove it, and clear the field. Thank you
$(".allS").change(function () {
if ($(this).next('.textArea').not(':empty'))
// varible to hold string
var str = "";
$("select option:selected").each(function () {
str += $(this).text() + " ";
});
$("#text_here").text(str);
}).change();
$('.textArea').change(function(){
var $inputs = $('form#form :input[type="text"]'),
result = "";
$inputs.each(function(){
// access the individual input as jQuery object via $(this)
result += $(this).val()+"<br>";
});
// store result in some div
$('div#text_here').text(result);
}).change();
There were many mistakes in your code. I simplified it to a very short code that only does what's needed to get the output you requested. Here's the working fiddle.
$(".allS, .textArea").change(function () {
var str = '';
if ($('#name').val().length > 0 && $('#number').val().length > 0)
var str = $('#nameMod>option:selected').text() + ' name:' + $('#name').val() + ' ' + $('#numberMod>option:selected').text() + ' number ' + $('#number').val();
$("#text_here").html(str);
});
Basically, what this does is attach a change event handler to both classes (.alls, .textArea), and when the event is triggered, both input fields are tested for any content. If this test passes, a string is composed out of all the relevant values, and the div content is set. If the test failed (no content), the str variable contains an empty string and the div is cleared.
Just glancing at the code, the selector 'form#form :input[type="text"]' looks wrong. For starters, input is not a pseudoclass. Also, attribute matching shouldn't have the quotes.
This may or may not be what you want (I think it is, from looking at your html):
'form#form input[type=text]'
Also your <br>'s are not working because you called text(). call html() instead.

Can't get JSON to render correctly in dropdown

I'm trying to take JSON from a PHP file and use it to populate a dropdown box.
I'm getting the JSON just fine from the PHP file. It looks like this:
[{"state":"AL"},{"state":"AK"},{"state":"AZ"},{"state":"AR"}]
I can see in the response in developer tools that it's coming over fine. However, when I look at the JSON, line 1 is empty and everything is on line 2. Not sure if that's a problem or not.
On the HTML side, here's what I've got:
<select id="myselect"></select>
and
$.getJSON('state_get.php', function(data) {
$.each(data, function(key, val) {
$('#myselect').append("<option>"+key.text+"</option>");
})
});
What I get in my dropdowns are a bunch of options with "undefined". There appear to be one for each JSON value, so something's party right, but not all the way.
Any help would be appreciated.
The first argument to each callback is the index, second is the value also the key to the property is State not text
$.getJSON('state_get.php', function (data) {
$.each(data, function (key, val) {
$('#myselect').append("<option>" + val.state + "</option>");
})
});
First argument of $.each when looping an array is index, the second is the element of the array
Try
$('#myselect').append("<option>"+val.state+"</option>");
Each of the objects in your array would be an element
reference jQuery.each() API Docs
You object has property state, not text
$.each(data, function(key, val) {
$('#myselect').append("<option>" + val.state + "</option>");
});
Try this
$('#myselect').append("<option>"+val.state+"</option>");
Lets have dropdown like below
<select id="myselect" name="stateList" class="state-list ></select>
You can append your value like this
var stateSelector = $('select.state-list');
var option = $("<option value=''></option>");
$.each(data, function(key, val) {
option = $("<option value='" + val.state + "'>" + val.state + "</option>");
stateSelector.append(option);
});
$('.state-list').selectpicker('refresh'); // you can refresh your dropdown if required

calling javascript function with an argument from html

I am creating a html element using javascript:
html_info += '<div class="row"><h4>'+ i +'. Patient: '+ key +'</h4>Date of birth: '+info[0]+'<br> Occupation: '+info[1]+'<br> Date of Test: ' + info[2]+ '<script type="text/javascript"> draw_chart(' + patient_test_info[key].right_eye +' ); </script></div>';
document.getElementById('patient_display').innerHTML += html_info;
It creates the element properly and displays the information stored in info array, but call to the draw_chart() function fails. I printed the contents of patient_test_info[key].right_eye using console.log before passing it as an argument and the contents of the variable are fine. But checking the html elements displays that patient_test_info[key].right_eye is not passed correctly and are just empty objects.
<script type="text/javascript"> draw_chart([object Object],[object Object],[object Object],[object Object] ); </script>
My draw_chart() function must draw the chart in the same div as the one used to display info content. On calling it independently, it does not recognise the newly created div and thus does not display anything.
function draw_chart(data) {
var chart = d3.cloudshapes.barChart()
.width(800).height(800);
for(var i=0; i<data.length; i++) {
var temp_value = data[i];
d3.select("#row")
.datum(temp_value)
.call(chart);
}
}
What is the right way of calling the function using an argument ?
What adeneo is saying is if you call the function directly it should work, like this:
html_info += '<div class="row"><h4>'+ i +'. Patient: '+ key +'</h4>Date of birth: '+info[0]+'<br> Occupation: '+info[1]+'<br> Date of Test: ' + info[2] + draw_chart(patient_test_info[key].right_eye) + '</div>';
In response to your comment, I don't know how the chart code you're using works, but if d3.select("#row") is supposed to be targeting the div you've created, then you have 3 problems:
1) You're calling the function before the div has actually been added to the DOM. You need to do your html_info += '<div class="row">...' and ....innerHTML += html_info; first, then call draw_chart() afterwards.
2) You're targetting the <div class="row"> with select("#row") - assuming standard syntax, # denotes an ID, not a class. You either need to make it id="row" or select(".row") (a dot denotes a class). However, if you're planning to be able to call this function multiple times to add multiple charts, you'll need them to have unique names, otherwise you'll have trouble specifying that you want to use the latest row. I suggest using the ID and adding your "key" to it, assuming that's valid.
3) Again, I'm not sure how the chart code works, but I'd guess that it's going to replace the contents of the targetted div, not append to it, which means you'll lose the title from your row. If that's the case, I'd suggest putting another div inside your row div and giving it the name instead so you can target it, e.g. '<div><h4>'+ i +'. Patient: '+ key +'</h4>Date of birth: '+info[0]+'<br> Occupation: '+info[1]+'<br> Date of Test: ' + info[2] + '<div id="chart-' + key + '"></div></div>'. Once you've added that to the innerHTML, you can then call draw_chart(patient_test_info[key].right_eye, key) and modify your draw_chart method to use the key for the name, e.g. d3.select("#chart-" + key).

How can I create dynamic controls and put their data into an object?

I created a div and a button. when the button clicked, there will be a group of element(included 1 select box and 2 text inputs) inserted into the div. User can add as many group as they can, when they finished type in data of all the group they added, he can hit save button, which will take the value from each group one by one into the JSON object array. But I am stuck in the part how to get the value from each group, so please help, thank you.
The code for the div and the add group button function -- AddExtra() are listed below:
<div id="roomextra">
</div>
function AddExtra() {
$('#roomextra').append('<div class=extra>' +
'<select id="isInset">' +
'<option value="Inset">Inset</option>' +
'<option value="Offset">OffSet</option>' +
'</select>' +
'Length(m): <input type="text" id="insetLength">' +
'Width(m): <input type="text" id="insetWidth">' +
'Height(m): <input type="text" id="insetHeight">' +
'</div>');
}
function GetInsetOffSetArray (callBack) {
var roomIFSDetail = [{
"IsInset": '' ,
"Length": '' ,
"Width": '' ,
"Height": ''
}];
//should get all the value from each group element and write into the array.
callBack(roomIFSDetail);
}
This should just about do it. However, if you're dynamically creating these groups, you'll need to use something other than id. You may want to add a class to them or a data-* attribute. I used a class, in this case. Add those classes to your controls so we know which is which.
var roomIFSDetail = [];
var obj;
// grab all of the divs (groups) and look for my controls in them
$(.extra).each(function(){
// create object out of select and inputs values
// the 'this' in the selector is the context. It basically says to use the object
// from the .each loop to search in.
obj = {
IsInset: $('.isInset', this).find(':selected').val() ,
Length: $('.insetLength', this).val() ,
Width: $('.insetWidth', this).val() ,
Height: $('.insetHeight', this).val()
};
// add object to array of objects
roomIFSDetail.push(obj);
});
you'd better not to use id attribute to identity the select and input, name attribute instead. for example
$('#roomextra').append('<div class=extra>' +
'<select name="isInset">' +
'<option value="Inset">Inset</option>' +
'<option value="Offset">OffSet</option>' +
'</select>' +
'Length(m): <input type="text" name="insetLength">' +
'Width(m): <input type="text" name="insetWidth">' +
'Height(m): <input type="text" name="insetHeight">' +
'</div>');
}
and then, usr foreach to iterate
$(".extra").each(function() {
var $this = $(this);
var isInset = $this.find("select[name='isInset']").val();
var insetLength = $this.find("input[name='insetLength']").val();
// ... and go on
});
A common problem. A couple things:
You can't use IDs in the section you're going to be repeating, because IDs in the DOM are supposed to be unique.
I prefer to use markup where I'm writing a lot of it, and modify it in code rather than generate it there.
http://jsfiddle.net/b9chris/PZ8sf/
HTML:
<div id=form>
... non-repeating elements go here...
<div id=roomextra>
<div class=extra>
<select name=isInset>
<option>Inset</option>
<option>OffSet</option>
</select>
Length(m): <input id=insetLength>
Width(m): <input id=insetWidth>
Height(m): <input id=insetHeight>
</div>
</div>
</div>
JS:
(function() {
// Get the template
var container = $('#roomextra');
var T = $('div.extra', container);
$('#addGroup').click(function() {
container.append(T.clone());
});
$('#submit').click(function() {
var d = {};
// Fill d with data from the rest of the form
d.groups = $.map($('div.extra', container), function(tag) {
var g = {};
$.each(['isInset', 'insetLength', 'insetWidth', 'insetHeight'], function(i, name) {
g[name] = $('[name=' + name + ']', tag).val();
});
return g;
});
// Inspect the data to ensure it's what you wanted
debugger;
});
})();
So the template that keeps repeating is written in plain old HTML rather than a bunch of JS strings appended to each other. Using name attributes instead of ids keeps with the way these elements typically work without violating any DOM constraints.
You might notice I didn't quote my attributes, took the value attributes out of the options, and took the type attributes out of the inputs, to keep the code a bit DRYer. HTML5 specs don't require quoting your attributes, the option tag's value is whatever the text is if you don't specify a value attribute explicitly, and input tags default to type=text if none is specified, all of which adds up to a quicker read and slimmer HTML.
Use $(".extra").each(function() {
//Pull info out of ctrls here
});
That will iterate through all of your extra divs and allow you to add all values to an array.

Show enter contents of JSON

QUESTION ::
I know this is a redundant question, but I am finding little help in other similar questions...
I have a json file.
I can load the json fine, but when I try to output a specific element with this
div.innerHTML = jsonfromfile[element];
I only get this...
[object Object]
as my output...
How do I get the entire element to display instead of this [object Object]?
more code to get a feel for how it is being done up...
var activity;
function jsfr() {
$.getJSON('myjson.json', function(response){
jsonfromfile = response;
})
}
.
.
.
SOLUTION :: from Francis Stalin's answer
I added a new function...
var items;
function outty(data) {
$.each(data, function(key, val) {
items=items+key+","+val+";";
});
}
and i set the depth on the json leaving me with an object which i send to outty...
dpth = jsonfromfile["elementOne"]["elSubone"]["elsuboneSub"];
outty(dpth);
div.innerHTML=items;
here's the HTML that shows the div it all prints to...
<div class="col-rght">
<div class="text" id="postcomp"></div>
</div> <!--div class="col-rght"-->
this turns the object of your desired json depth into an ugly string that you can then format for display..
if you like html lists check out how Stalin did it, but be weary of his appendTo('div')... this will place your list in every div. Try putting the name of the class of the div you want to print to with a period leading it, appendTo('.outputbox')
you can't append the json object directly into ur html. u have to parse and convert into string
$.getJSON('myjson.json', function(data) {
var items = [];
$.each(data, function(key, val) {
items.push('<li id="' + key + '">' + val + '</li>');
});
$('<ul/>', {
'class': 'my-new-list',
html: items.join('')
}).appendTo('div');
});
http://api.jquery.com/jQuery.getJSON/
Use JSON.stringify(yourjsonobjecthere)
Try div.innerHTML = JSON.stringify(jsonfromfile[element]);

Categories

Resources