I'm having problems with dynamically adding a row to a table using data stored in two arrays (categories and treatments). The arrays are fine, I've determined that.
When passing just the categories array the new row displays but the select box reads [object:object], it's clearly blank.
When I pass a second array with it, as shown below, the console reads 'undefined is not a function'.
Any help would be hugely appreciated!
// Add an extra row when button is clicked
var counter = 1;
$('input.add').click(categories, treatments, function(){
counter++;
var newRow = '<tr><td><label for="category' + counter + '">Category</label></td><td><select id="category' + counter + '" name="category' + counter + '" required="required">';
$.each(categories, function(key, value) {
$('#category' + counter)
newRow += '<option value ="' + key + '">' + value + '</option>';
});
newRow += '</select></td><td><label for="treatment' + counter + '">Treatment</label></td><td><select id="treatment' + counter + '" name="treatment' + counter + '">';
$.each(treatments, function(key, value) {
$('#treatment' + counter)
newRow += '<option value ="' + key + '">' + value + '</option>';
});
newRow += '</select></td></tr>';
$('table.treatments').append(newRow);
});
});
The first parameter for the jQuery .click() is an Object, and you're trying to pass two arrays.
This should work for you (remember to check for the missing semi-colons):
// Create an Object obj containing the two arrays.
$('input.add').click(obj = { categories: categories, treatments: treatments }, function () {
counter++;
var newRow = '<tr><td><label for="category' + counter + '">Category</label></td><td><select id="category' + counter + '" name="category' + counter + '" required="required">';
// Use the obj.
$.each(obj.categories, function (key, value) {
$('#category' + counter);
newRow += '<option value ="' + key + '">' + value + '</option>';
});
newRow += '</select></td><td><label for="treatment' + counter + '">Treatment</label></td><td><select id="treatment' + counter + '" name="treatment' + counter + '">';
// Use the obj.
$.each(obj.treatments, function (key, value) {
$('#treatment' + counter);
newRow += '<option value ="' + key + '">' + value + '</option>';
});
newRow += '</select></td></tr>';
$('table.treatments').append(newRow);
});
Demo
jQuery .click()
Related
I want to make a switch for declaring variables inside each loop, like this
switch (label) {
case "Users":
content = item.username+ ' ' + item.firstname + ' '
+ item.lastname + '('+ item.organization + ')';
break;
default:
}
$.each(result, function (i, item) {
html += "<option value ='" + item.id + "'>" + content + "</option>";
});
But since item variable hasn't defined yet I will get an ReferenceError.
Moving switch inside loop will make It really slow.
Is this even possible to declare loop variables outside of scope?
function selectorAddEdit(label, tag, result, labelconf) {
var idtag = tag+"s";
var none = "<option value='None'>None</option>";
var labelHead = (labelconf=="head") ? "<div class='selectTitles'><label>"+label+"</label></div>" : "";
switch (label) {
case "Users":
var content = item.username + ' ' + item.firstname + ' ' + item.lastname + '('+ item.organization + ')';
break;
default:
}
var html = labelHead + "<select name='" + tag + "' class='" + tag + "'>";
$.each(result, function (i, item) {
html += "<option value ='" + item.id + "'>" + content + "</option>";
});
html += "</select></div>";
$("." + idtag).html(html);
}
Declare the content as a global variable
var content="";
switch (label) {
case "Users":
content = item.username+ ' ' + item.firstname + ' ' + item.lastname + '('+ item.organization + ')';
break;
default:
}
$.each(result, function (i, item) {
html += "<option value ='"+item.id+"'>"+content+"</option>";
});
This is assuming that item is distinct/unique and therefore you want the switch statement to be re-evaluated at each iteration of loop. What you can do is to use a method/function that returns the value, after evaluating a given condition:
var getOptionContent = function(item) {
switch (label) {
case "Users":
return item.username + ' ' + item.firstname + ' ' + item.lastname + '(' + item.organization + ')';
default:
return '';
}
}
var html = labelHead + "<select name='" + tag + "' class='" + tag + "'>";
$.each(result, function(i, item) {
html += "<option value ='" + item.id + "'>" + getOptionContent(item) + "</option>";
});
I have six static html questions and then 3-4 questions being generated by JSON dynamically based upon a form choice made on a page before. What I'm trying to do is generate the questions, then create a progress bar based on the final number of questions created. Where I'm having trouble is using the jQuery when done method after my each loop. It is firing after the first iteration instead of the last. I have tried populating an array "Qs" and passing the array, after reading some other posts, but what I have hasn't worked. I would really like to segment my code and clean it up as much as possible, so I'm trying to stay away from nesting it.
var Qs = [];
var generateQs = function (){
var $dept = sessionStorage.getItem("sFGeneralDepartment1");
var $qWrapper = $("#assessmentTool");
$.getJSON("js/dept-questions.json", function(data) {
var key = $dept;
var vals = [];
switch(key) {
case 'Information technology':
vals = data.IT;
break;
case 'Finance':
vals = data.FIN;
break;
case 'Human resources':
vals = data.HR;
break;
case 'Marketing':
vals = data.MKT;
break;
default:
vals = data.OT;
break;
}
$.each(vals, function(index, value) {
var $cleanID = (value.qID).replace(/q/g, '');
$qWrapper.append('<div class="question-container rangeIcon disabled" id="' + value.qID + '"><p>Question ' + $cleanID +'</p> <h4>' + value.questionText + '</h4><ul class="answer-container"></ul></div>');
$.each(value.answers, function(i, answer) {
var $aID = answer.aID;
var $radioBtn = '<div class="radioBtn"><span class="radioBtnInner"></span></div>';
$('.question-container#' + value.qID + ' .answer-container').append('<li class="survey-item"><div class="icon-holder" id="' + $aID + '"><img src="img/' + answer.iconFileName + '" width="' + answer.iconWidth +'" height="'+ answer.iconHeight + '"/></div><input type="radio" id="'+ $aID + '" value="' + answer.pointValue + '"><label for="' + $aID + '" class="radio" data-popover="'+ answer.popoverText + '">' + $radioBtn + '<span class="labelTopText">' + answer.labelTopText + '<span class="divider">/</span></span><span class="labelBottomText">' + answer.labelBottomText + '</span></label></li>');
});
Qs.push($cleanID);
});
console.log('done');
console.log(Qs);
});
};
$.when(generateQs($,Qs)).done(function() {
//create progress bar
console.log('starting');
var qCount = ($('.question-container').length + 1);
var qList = $('#progressBar');
for (var i = 0; i < qCount; i++){
qList.append('<li class="progress-bar-steps" data-item="q' + (i+1) + '">' + '<span class="step-text">' + (i+1) + '</span>' + '</li>');
$('.question-container').each(function (i, value){
var qId = $(this).attr('id');
if ($(this).hasClass("active")) {
$(this).css('opacity','1.0');
$('#progressBar').find("[data-item='" + qId + "']").addClass('active').html('<span class="step-text">' + (i+1) + '</span>');
$('.progress-bar-steps.active').next('.progress-bar-steps').addClass('next disabled-next').html('<span class="step-text">' + (i+2) + '</span>');
} else {
$(this).addClass('disabled');
}
});
}
});
I'm using a .each function to build a dropdown list. I understand the basics of programming that the index of an array element will always start at 0. When I build this dropdown I need the first value to be a 1. This is what I have.
$.each(codes, function(key,value){
$('#columnD1').append('<option value="' + key + '">' + key + ' - ' + value + '</option>');
})
So as expected I get 0 - Item1, 1 - Item2, 2 - Item3. But these codes are specific to certain values. 1 is for Item1 and 2 if for Item2. When I go to insert it wouldn't be a problem because I could fix it before the insert, the problem I'm having is that, I need the customer to see the code number for the item they are picking because in some place the value means nothing to the customer because they have the codes memorized.
You can add to key before you use it, just like in a for loop.
fiddle demo
$.each(codes, function(key, value) {
key++;
$('#columnD1').append('<option value="' + key + '">' + key + ' - ' + value + '</option>');
})
$.each(codes, function(key,value){
$('#columnD1').append('<option value="' + (key + 1) + '">' + (key + 1) + ' - ' + value + '</option>');
})
will give you what you want.
$.each(codes, function(key, value) {
if (key == 0) {
return false;
}
$('#columnD1').append('<option value="' + key + '">' + key + ' - ' + value + '</option>');
})
I am trying to make a select with the option value and text coming from two separate arrays (one is called like_list and the other like_list_name). The '$.each' joins two arrays and makes list of options. When I look in console.log I can see the options looking good:
$.each(like_list, function(i, item) {
console.log('<option value="' + like_list[i] + '">' + like_list_name[i] + '</option>');
});
But when I name the output as 'optionlist' and try to put 'optionlist' into the div 'friendselect' with Inner HTML it doesn't work:
var optionlist = $.each(like_list, function(i, item) {
'<option value="' + like_list[i] + '">' + like_list_name[i] + '</option>';
});
document.getElementById('friendselect').innerHTML = '[select]' + optionlist + '[/select]';
Is there anyway to get this select box into the 'friendselect' div? NOTE: i USED '[' because the side arrow wasn't working.
You should try with map function:
var optionlist = $.map(like_list, function(i, item) {
return '<option value="' + like_list[i] + '">' + like_list_name[i] + '</option>';
}).join('');
document.getElementById('friendselect').innerHTML = '<select>' + optionlist + '</select>';
$.each() doesn't return the values in it's function, you will have to add them toghether yourself.
The best thing you can do is add the options to the select in the each loop like so:
$.each(like_list, function(i, item) {
$("#friendselect").append('<option value="' + like_list[i] + '">' + like_list_name[i] + '</option>');
});
I am working on preparing some dynamic html with jquery and json object. but the problem is that when my json object has around 1500 rows it takes ages to load.
is there a way to load the thing faster.
Some code.
$(jQuery.each(jsonObject.AvailableColumns, function (i, l) {
if (type == "manual") {
innerList1 += '<li newText="" valueFormat="' + l.ValueFormat + '" scaleID="' + l.ScaleID + '" scaleType="' + l.ScaleType + '" hasWeights="' + l.HasWeights + '" customColumnType="' + l.CustomColumnType + '" class="" id="li_' + controlId + '"><span id="span_' + controlId + '" title = "' + l.QuestionText + '">' + getDisplayString(l.QuestionText) + '</span><a class="actionLeft"></a></li>';
}
else if (type = "exportall") {
innerList2 += CreateLiWithSpans('li_' + controlId, l.QuestionText, true, false, l.ScaleID, l.ScaleType, l.HasWeights, l.CustomColumnType, l.ValueFormat);
}
controlId++;
}));
$("#itemList").html(innerlist1);
EDIT : createliwithspan method
function CreateLiWithSpans(id, html, isLeft, isAddAll, scaleID, scaleType, hasWeights, customColumnType, valueFormat, newText) {
var ancClass = isLeft ? 'actionRight' : 'actionLeft';
var liObject = "";
if (newText == null) {
newText = "";
}
if (isLeft) {
liObject = '<li newtext="' + newText + '" valueFormat="' + valueFormat + '" scaleID="' + scaleID + '" scaleType="' + scaleType + '" hasWeights="' + hasWeights + '" customColumnType="' + customColumnType + '" class="" id="' + id + '"><span id="span_' + id + '" title = "' + html + '">' + getDisplayString(html) + '</span><span style="margin:0 10px 0 20px;pagging:0"><input title = "' + (newText == "" ? html : newText) + '" type="text" id="' + id + 'displayText" value="' + (newText == "" ? html : newText) + '" /><span style="color:Red; width:100%;" id="' + id + 'displayTextError"></span></span><span style="float:left">' + CreateDropDown('ddl_' + id, valueFormat, hasWeights) + '</span><a class="' + ancClass + '"></a></li>';
}
else {
liObject = '<li newtext="' + newText + '" valueFormat="' + valueFormat + '" scaleID="' + scaleID + '" scaleType="' + scaleType + '" hasWeights="' + hasWeights + '" customColumnType="' + customColumnType + '" class="" id="' + id + '"><span id="span_' + id + '" title = "' + html + '">' + getDisplayString(html) + '</span><a class="' + ancClass + '"></a></li>';
}
return liObject;
}
You can use for loop instead of jQuery.each, that will be faster. Store the itemCount before the loop, and use that:
itemCount = jsonData.items.length;
for(var i = 0; i < itemCount; i++ ) {
...
You can also use use an array instead of string concatenation, like so:
var innerList = [];
... // inside the loop
innerList.push(CreateLiWithSpans('li_' + controlId, l.QuestionText, true, false, l.ScaleID, l.ScaleType, l.HasWeights, l.CustomColumnType, l.ValueFormat));
... // after the loop
$("#itemList").html(innerList.join(''));
This will be faster in IE, I'm not sure about other js engines.
These two methods will not make a significant difference, so you should try implementing a client side pagination from json. (Not by hiding and showing divs, by rendering only visible page into the DOM).
Instead of waiting for the loop to end to append your data, why not actively append the data as you process it. This will allow the user to get immediate feedback instead of waiting for the whole thing to process. Other than this, I'd stick with my original comment to page the data.
$(jQuery.each(jsonObject.AvailableColumns, function (i, l) {
if (type == "manual") {
$("#itemList").append( '<li newText="" valueFormat="' + l.ValueFormat + '" scaleID="' + l.ScaleID + '" scaleType="' + l.ScaleType + '" hasWeights="' + l.HasWeights + '" customColumnType="' + l.CustomColumnType + '" class="" id="li_' + controlId + '"><span id="span_' + controlId + '" title = "' + l.QuestionText + '">' + getDisplayString(l.QuestionText) + '</span><a class="actionLeft"></a></li>');
}
else if (type = "exportall") {
$("#itemList2").append(CreateLiWithSpans('li_' + controlId, l.QuestionText, true, false, l.ScaleID, l.ScaleType, l.HasWeights, l.CustomColumnType, l.ValueFormat));
}
controlId++;
}));
Try replacing jQuery.each with a plain old for...in loop. Using jQuery.each adds overhead that you don't need.
Don't concatenate strings inside your loop. Instead, .push them onto an array variable and use .join('') to build the string all at once at the end.
You may need to eliminate CreateLiWithSpans as a separate function in order to fully implement (2).
Changing from using jQuery.each to a standard javascript for loop should speed it up a bit. Make sure that you save the length to a variable like this though:
for(var i = 0, len = jsonObject.AvailableColumns.length; i < len; i++){
var l = jsonObject.AvailableColumns[i];
// Continue with rest of code
}
Probably won't be a huge increase but every little helps.
Also try lowering the number of function calls you make as these have added overhead (not usually an issue, but in a large loop it can help). Unless the code is shared between functions try doing it inline and see how much that speeds it up.