Using .children and .find in jQuery - javascript

I have a set of controls on my page that I am attempting to iterate through and determine if they have values. Some of these controls are <select> items and in this instance I need to loop through the options associated with the <select> control and find the ones that are selected. I have tried .children() as well as .find("option:selected") and neither of them work (both throw an "undefined" error in javascript). What am I doing wrong?
function getJsonValue(control, json) {
if(control.dataset["fieldname"] !== "undefined"){
if(control.tagName == "SELECT") {
var selected = "{";
var idName = control.dataset["idname"];
control.children.each( function() {
if(this.selected) {
selected += idName + ": " + this.val() + ",";
}
});
selected += "}";
if(selected != '') {
json += control.dataset["fieldname"] + ": ";
json += selected + ",";
}
} else {
if(control.val() != '') {
json += control.dataset["fieldname"] + ": ";
json += control.val() + ",";
}
}
}
};
The error is appearing on line 5 of the above code (control.children.each). I've tried:
control.children.each( function() {
control.childre().each( function() {
control.find("option:selected").each( function() {
None of these options work. For reference, the "control" variable is passed from another function that is found by doing the following:
$("#search-header").find("select").each( function() {
json = getJsonValue(this, json);
});

To further extend on my comment, I can see that you are passing the object this, which is assigned to the variable control in your function. However, jQuery cannot directly operate on this object unless it is converted into a jQuery object, and this can be done simply by wrapping it with the jQuery alias, $(control) (hint, just like how people use $(this) in jQuery, it's the same thing).
Therefore, if you revise your code this way, it should work:
function getJsonValue(control, json) {
if(control.dataset["fieldname"] !== "undefined"){
if(control.tagName == "SELECT") {
var selected = "{";
var idName = control.dataset["idname"];
$(control).children.each( function() {
if(this.selected) {
selected += idName + ": " + this.val() + ",";
}
});
selected += "}";
if(selected != '') {
json += control.dataset["fieldname"] + ": ";
json += selected + ",";
}
} else {
if(control.val() != '') {
json += control.dataset["fieldname"] + ": ";
json += $(control).val() + ",";
}
}
}
};
p/s: On a side note, if you ever want to access the original DOM node from a jQuery object, just use $(control)[0] ;)

Try
$(control).find("option:selected").each( function() {
or
$(control).children.each( function() {
You are passing (this) to you function from the caller. It doesn't have jquery selector.

You are missing Open close bracket on first children
control.children().each( function() {
control.childre().each( function() {
control.find("option:selected").each( function() {

Related

Assign id to div dynamically created from a JSON file

I want to assign dynamic id attributes to the div(s) which are being appended through JavaScript. For example:
function x() {
for (current_list = 0; current_list < data.length; current_list++) {
$("#current").append(
"<div class="card">" +
"" + data[current_list].name + "" +
"</div>");
}
}
Two cards will be appended, so I want to assign them an id which can increase if there are more numbers of arrays present in the JSON.
you probably looking for this.
function x() {
var container=$("#current");
for(var i=1;i<10;i++)
{
var id="card"+i;
var divHtml="<div class='"+id+"'>" +
""+data[current_list].name+"" +
"</div>"
container.append(divHtml);
}
}
As Rory said, here a solution using DOM traversal.
You would have to call this after appending your "cards".
$(".card").each(function(value, index){
$(value).attr("id", "card" + index);
});
if you call x() function one time you can use
function x() {
for (current_list = 0; current_list < data.length; current_list++) {
$("#current").append('<div id="card-'+current_list+'" class="card">' + data[current_list].name + '</div>');
}
}
and if you call it many time you can use this function after every call
$(".card").each(function(value, index){
$(value).attr("id", "card-" + index);
});

Recursive Function not working correctly

I have a recusive function that is supposed to loop through a json object and output the expression. However, my recusion seems to be off because it's outputting field1 != '' AND field3 == '' when it should be outputting field1 != '' AND field2 == '' AND field3 == ''
I've tried a couple different things and the only way I can get it to work is by creating a global variable outstring instead of passing it to the function. Where am I off? When I step through it, i see a correct result but once the stack reverses, it start resetting outstring and then stack it back up again but leaves out the middle (field2).
JSFiddle
function buildString(json, outstring) {
var andor = json.condition;
for (var rule in json.rules) {
if (json.rules[rule].hasOwnProperty("condition")) {
buildString(json.rules[rule], outstring);
} else {
var field = json.rules[rule].id;
var operator = json.rules[rule].operator;
var value = json.rules[rule].value == null ? '' : json.rules[rule].value;
outstring += field + ' ' + operator + ' ' + value;
if (rule < json.rules.length - 1) {
outstring += ' ' + andor + ' ';
}
}
}
return outstring;
}
var jsonObj = {"condition":"AND","rules":[{"id":"field1","operator":"!= ''","value":null},{"condition":"AND","rules":[{"id":"field2","operator":"== ''","value":null}]},{"id":"field3","operator":"== ''","value":null}]};
$('#mydiv').text(buildString(jsonObj, ""));
The function has a return of a string.
When you call the function recursively from within itself, you aren't doing anything with the returned string from that instance, just calling the function which has nowhere to return to
Change:
if (json.rules[rule].hasOwnProperty("condition")) {
buildString(json.rules[rule], outstring);
}
To
if (json.rules[rule].hasOwnProperty("condition")) {
// include the returned value in concatenated string
outstring += buildString(json.rules[rule], outstring);
}
DEMO
Why so complicated?
function buildString(obj) {
return "condition" in obj?
obj.rules.map(buildString).join(" " + obj.condition + " "):
obj.id + " " + obj.operator + " " + string(obj.value);
}
//this problem occurs quite often, write a utility-function.
function string(v){ return v == null? "": String(v) }

Error: ..attempt was made to use an object that is not, or is no longer, usable

I have the following function that I use to debug vectors/objects in javascript:
function dump(arr,level) {
var dumped_text = "";
if(!level) level = 0;
//The padding given at the beginning of the line.
var level_padding = "";
for(var j=0;j<level+1;j++) level_padding += " ";
if(typeof(arr) == 'object') { //Array/Hashes/Objects
for(var item in arr) {
var value = arr[item];
if(typeof(value) == 'object') { //If it is an array,
dumped_text += level_padding + "'" + item + "' ...\n";
dumped_text += dump(value,level+1);
} else {
dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
}
}
} else { //Stings/Chars/Numbers etc.
dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
}
return dumped_text;
}
(http://www.openjs.com/scripts/others/dump_function_php_print_r.php)
Its working fine, but when Im having some trouble to use it in this scenario:
function test( opt ){
console.log(dump( opt )); //Attempt to debug (breaks the code)
var options = jQuery.extend({
"multiple" : false,
"autoload" : false,
"template" : "default"
}, opt );
//-- etc
}
In this specifc line console.log(dump( opt )); I have the javascript error:
Uncaught InvalidStateError: An attempt was made to use an object that
is not, or is no longer, usable.
But when I comment this, the code works fine. Anybody have any idea of whats going on?
Edit:
Function calling:
test({
"multiple": true,
"template": "dark1"
});

Can't create select element with returned json data from Ajax call

I'm making an ajax call to retrieve some JSON objects. I get them right. but the problem is when I want to create a select element from returned JSON, it doesn't create one or seemed to be.
My JavaScript so far:
jQuery("#make").change(function () {
var value = $(this).val();
jQuery.getJSON("<?php echo site_url('ajax/get/models'); ?>", {
makeId: value
},
function (data) {
if (data != "false") {
var modelsSelect = jQuery.createElement('select');
var modelsOptions = "";
var id;
var model
jQuery.each(data, function () {
jQuery.each(this, function (key, value) {
if (key == "id") {
id = value;
} else {
model = value;
}
});
modelsOptions += "<option value=" + id + ">" + model + "</option>"
});
modelsSelect.innerHTML = modelsOptions;
jQuery("#model").html = modelsSelect;
} else {
alert("false");
}
});
});
my returned JSON Format:
Object { id="28", model="test model"}
There could be n number of JSON objects in returned response from ajax call.
There is no createElement method in jQuery
jQuery.createElement should be document.createElement
Also no need to loop over the objects' properties, you can access them by the key directly
jQuery.each(data, function (index, item) {
modelsOptions += "<option value=" + item.id + ">" + item.model + "</option>"
});
Change this
jQuery("#model").html = modelsSelect;
to
jQuery("#model").html(modelsSelect);
Reference
.html()

Why can't I replace the URL of these incoming JSON'd images?

So I've got this JS code that pulls JSON from a php file. That works. What I'm trying to do is change JSON values before they're put into the DOM to replace image URLs with lower-res images. You'll see the beginning of this in the IF statement calling the mobile() function
Here we go:
$.post(url, project, function(data, textStatus) {
$(data.tags).each(function(i, item){
projectTags += "<span class='project-tag'>"+item+"</span>";
});
$(data.slides).each(function(i, item){
if ((mobile() == true && $(window).width() <= 680)){
if (i != 0){
console.log('Before' +item);
var newItem = JSON.stringify(item);
$(newItem).replace('.png','-lofi.png');
console.log(newItem);
console.log('After' + item);
}
}
projectImages += "<div class=\"slide-container\">" + item + "</div>";
console.log(projectImages);
});
setTimeout(function(){
btnAbout.removeClass('active');
sectionDetail
.attr('data-id', data.id)
.find('.project-name').html(data.name).end()
.find('.project-year').html(data.year).end()
.find('.project-agency').html(data.agency).end()
.find('.project-details').html(data.details).end()
.find('.project-tags').html(projectTags).end()
.find('#slideshow').html(projectImages);
}, "json");
What gives? ALL I want to do is replace the URL of JSON value if it's a mobile device smaller than an iPad.
EDIT: Fixed by James! Thanks buddy! FINAL CODE BELOW.
$.post(url, project, function(data, textStatus) {
$(data.tags).each(function(i, item){
projectTags += "<span class='project-tag'>"+item+"</span>";
});
$(data.slides).each(function(i, item){
var loFi = JSON.stringify(item);
if ((mobile() == true && $(window).width() <= 680)){
if (i != 0){
loFi = loFi.replace(/(.png)/g,'-lofi.png')
loFi = $.parseJSON(loFi);
item = loFi;
}
}
projectImages += "<div class=\"slide-container\">" + item + "</div>";
});
setTimeout(function(){
btnAbout.removeClass('active');
sectionDetail
.attr('data-id', data.id)
.find('.project-name').html(data.name).end()
.find('.project-year').html(data.year).end()
.find('.project-agency').html(data.agency).end()
.find('.project-details').html(data.details).end()
.find('.project-tags').html(projectTags).end()
.find('#slideshow').html(projectImages);
}, "json");
Should be:
var newItem = JSON.stringify(item);
newItem = newItem.replace('.png','-lofi.png');
You're forgetting to assign the result of 'replace' to your variable and you don't need to wrap newItem in $(..), replace is a String object function.
PS. You probably don't need to stringify either. Isn't your item already a String?
$(data.slides).each(function(i, item){
var newItem = JSON.stringify(item); <-- Add this early
if ((mobile() == true && $(window).width() <= 680)){
if (i != 0){
console.log('Before' +item);
newItem = newItem.replace(/(.png)/g,'-lofi.png');
console.log(newItem);
console.log('After' + item);
}
}
You are still adding the regular item here? any changes you made to item are not reflected.
projectImages += "<div class=\"slide-container\">" + item + "</div>";
change to
projectImages += "<div class=\"slide-container\">" + newItem + "</div>";

Categories