jQuery command other than appendTo - javascript

I am trying to clear an LI tag's previous data.
Is there another command that will work other than appendTo?
Here is what my code currently looks like:
var obj = JSON.parse(data);
$.each(obj, function(index, item)
{
$('<li>').
text(item.datestamp+' - '+item.comment).
appendTo($('#pCodeComment'));
});
I asked a similar question not too long ago. I just want to know if there is another command other than appendTo that will clear out the previous data.

You should empty the list before you loop to populate it, then just continue doing what you are already doing.
var obj = JSON.parse(data);
$('#pCodeComment').empty();
$.each(obj, function(index, item)
{
$('<li>').
text(item.datestamp+' - '+item.comment).
appendTo($('#pCodeComment'));
});
And after optimizing a little bit:
var obj = JSON.parse(data); // i'm assuming `obj` is an array
var htmlToInsert = obj.map(function (item) {
return '<li>' + item.datestamp + ' - ' + item.comment + '</li>';
}).join('');
$('#pCodeComment').html(htmlToInsert);
Note: the above is vulnerable to XSS. See this so question for ways to fix it, or just use the original.

$.replaceWith()
might be what you are looking for, or as Kevin B pointed out
$.html()
replaceWith would need an element selected to replace. whilst html will populate a parent element to insert a new dom fragment into.

Related

How can I only select some JSON objects?

Hi I have a script which parses a local JSON object (at the moment just to display a list).
function generateFamilySelect() {
var implantData = JSON.parse(localStorage.getItem("implantData"));
var implantFamilies = "";
$.each(implantData.implantFamilies, function( index, value ) {
implantFamilies += implantData.implantFamilies[index].familyDisplay + "<br />";
});
$("#holderForFamilySelect").html(implantFamilies);
}
and the JSON object:
{"implantFamilies":[
{"id":"1","familySelector":"aa","familyDisplay":"One","loadInitially":"1"},
{"id":"2","familySelector":"bb","familyDisplay":"Two","loadInitially":"1"},
{"id":"3","familySelector":"cc","familyDisplay":"Three","loadInitially":"1"},
{"id":"4","familySelector":"dd","familyDisplay":"Four","loadInitially":"0"},
{"id":"5","familySelector":"ee","familyDisplay":"Five","loadInitially":"0"},
{"id":"6","famiā€¦
At the moment, the list shows all of the elements. How can I modify this script to only show those with "loadInitially":"1"?
Also, a quick syntax question, I feel like the line
implantFamilies += implantData.implantFamilies[index].familyDisplay + "<br />";
could be written something like
implantFamilies += this[index].familyDisplay + "<br />";
but I can't get that to work...
The easiest is to use the Javascript Array.filter() method
// (or in your case, you get it from localstorage, but here's the data)
var myJson = {"implantFamilies":[
{"id":"1","familySelector":"aa","familyDisplay":"One","loadInitially":"1"},
{"id":"2","familySelector":"bb","familyDisplay":"Two","loadInitially":"1"},
{"id":"3","familySelector":"cc","familyDisplay":"Three","loadInitially":"1"},
{"id":"4","familySelector":"dd","familyDisplay":"Four","loadInitially":"0"},
{"id":"5","familySelector":"ee","familyDisplay":"Five","loadInitially":"0"}] };
//the array of implant families
var implantFamilies = myJson.implantFamilies;
//the filtering function. This is preferable to $.each
function implantFamiliesThatLoadInitially(implantFamily){
return implantFamily.loadInitially === '1';
}
//this is only the ones you want, (filtered by loadInitially property)
var loadInitiallyImplantFamilies = implantFamilies.filter(implantFamiliesThatLoadInitially);
The goal of the second part of your code is to build some html based on the data in the json, stored in teh variable implantFamilies. I will recommend Array.map() as an easier solution, than dealing with this. like before I am breaking this into multiple steps with comments so it is clear what is happening.
//your map function. You can make any html you want, like li's
function toImplantFamilyHtml(family){
return family.familyDisplay + '<br />'
}
//returns a plain string of html
var implantFamilyHtml = loadInitiallyImplantFamilies.map(toImplantFamilyHtml);
//jquery object you can use, or append to the DOM or whatever
var $implantFamilyHtml = $(implantFamilyHtml);
//append to DOM
$("#holderForFamilySelect").html($implantFamilyHtml);
working Fiddle: https://jsfiddle.net/mv850pxo/2/
the_5imian has provided a good answer to your first question, and you have determined the obvious alternate solution, given your current code.
As to your second question (this within jQuery.each()):
Within jQuery.each(), this is the value wrapped as an Object. value is the value of the array element at the current index, not the entire array. In other words, you don't use [index] on value or this within this context to get the current array element. For this code, value and this are the same because value is already an Object.
For what you want, you could just use value (Given that all elements of the array are already Objects, you could use this instead, but using value is a better habit to be in.):
$.each(implantData.implantFamilies, function( index, value ) {
if (value.loadInitially == "1") {
implantFamilies += value.familyDisplay + "<br />";
} else {
//do nothing
}
});
this is the value wrapped as an Object:
The following should show you what the values of value and this are within $.each(array,function(index,value){...});:
var myArray = ['zero','one','two','three','four','five'];
$.each(myArray, function(index,value){
console.log(index + ' value =',value);
console.log(index + ' this =',this); //this is the value wrapped as an Object.
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Well that just seems obvious now.
$.each(implantData.implantFamilies, function( index, value ) {
if (implantData.implantFamilies[index].loadInitially == "1") {
implantFamilies += implantData.implantFamilies[index].familyDisplay + "<br />";
} else {
//do nothing
}
});
How about the second part of my question?

JS Object values start with 'undefined'

I am trying to use an array as a key value type scenario and it is working with the exception that every value starts with 'undefined'. I believe this is due to the initial assignment being a += operator however I am not sure how to resolve it.
This is the code stripped of a lot of string concats....
var phasehtml = {};
$.each(json, function (i, item) {
phasehtml[item.Phase] += 'item:'+item.ID;
});
Basically I am trying to append the string to the appropriate key....
You can change the code to only append the ID if there's already IDs:
var phasehtml = {};
$.each(json, function (i, item) {
// Use the existing value for the phase, or an empty string that we can append to
var existingValue = (phasehtml.hasOwnProperty(item.Phase) ? phasehtml[item.Phase] : "");
phasehtml[item.Phase] = existingValue + 'item:' + item.ID;
});
That's assuming that you want phasehtml to contain an appended lists of the form "item:1item:2" for each phase.
The array you have posted is empty.
var phasehtml = {};
It seems that is the cause the following statement
phasehtml[item.Phase]
is being evaluated to "undefined".
Hmmm,
got the problem.
In your code you are trying to add with that value which is previously not defined that's why this error is occur.
In your code you have not initialize the variable that you are adding.
So try this:
var phasehtml = {};
$.each(json, function (i, item) {
phasehtml[item.Phase] = "";
phasehtml[item.Phase] += 'item:'+item.ID;
});
In this first assign some value, here is blank and then use that index of array.

Testing function that creates a list of DOM components

I have a function which creates an Array of components. Each component is an outer div with a few inner divs.
function createDivs(quizQuestions) {
var returnElements = new Array();
$.each(quizQuestions.questions, function(i, val){
// create the div.
quizDiv = $('<div class="questionContainer radius">')
questionDiv = $('<div class="question"><b><span>QuestionText</span></b></div>');
quizDiv.append(questionDiv);
// Now change the question div text.
questionDiv.text = val.question;
answerDiv = $('<div class="answers">');
// ...
// ...
// Now the answers.
questionDiv.append(answerDiv);
returnElements[i] = quizDiv;
});
return returnElements;
I pass JSON such as:
{questions:[{"question":"Name the best Rugby team?",
"answers":["Leinster", "Munster", "Ulster", "Connaught"],
"correct_answer":"Leinster"},
{"question":"Name the best DJ?",
"answers":["Warren K", "Pressure", "Digweed", "Sasha"],
"correct_answer":"Leinster"}]};
I'd like to write a simpe unit test so that I could test the array of div returned made sense
Any tips?
Also, are my better to return a DOM component or just text? The latter would be easier to test.
Thanks.
Not sure exactly what you want to test but it is far more performant to create as much html in strings as you possibly can to reduce function calls. Also append is expensive so ultimately making one string for all the new content represented by the JSON will be the biggest performance gain.
In my opinion it also makes code more readable since fragments are in same order as the would be in html editor
Example(my preferece is creating an array of all the string fragments, concatenation also commonly used):
var newcontent = [];
$.each(quizQuestions.questions, function(i, val) {
newcontent.push('<div class="questionContainer radius">');
newcontent.push('<div class="question"><b><span>' + val.question + '< /span></b > < /div>');
$.each(val.answers, function(idx, answer) {
newcontent.push('<div class="answers">' + answer + '</div > ')
})
newcontent.push(' </div></div > ');
});
Then to add content to DOM:
$('#someDiv').append( newcontent.join(''));
disclaimer: Not fully checked for proper closing/nesting of tags.

Read from serialize to populate form

I did serialize() on my form and saved the string, is there any function which can populate values back to the form from serialized string?
Here is the updated version of Explosion Pills' answer with the additional suggestions in the comments applied:
$.each(serialized.split('&'), function (index, elem) {
var vals = elem.split('=');
$("[name='" + vals[0] + "']").val(decodeURIComponent(vals[1].replace(/\+/g, ' ')));
});
Check out http://phpjs.org/functions/unserialize:571
I recommend instead of serializing data for communication with javascript, you use JSON. PHP should have json_encode() and json_decode() to help with this, and javascript also has built in JSON handling functions, which you may not even need. For example, if $.getJSON gets a valid JSON string from the server, it will be transformed into a javascript object automatically.
EDIT: assuming you are talking about jQuery's $.serialize(), that I know of there's no function to undo this (I'm not even sure why that would ever be necessary..) but this should work:
$.each(serialized.split('&'), function (index, elem) {
var vals = elem.split('=');
$("[name='" + vals[0] + "']").val(vals[1]);
});
Based on previous answers, if you have checkbox or radio buttons:
$.each(serialized.split('&'), function (index, elem) {
var vals = elem.split('=');
var $elem = $formularioEquipo.find("[name='" + vals[0] + "']");
var value = decodeURIComponent(vals[1].replace(/\+/g, ' '));
if ($elem.is(':radio,:checkbox')) {
$elem.prop('checked', ($elem.val() === value));
} else {
$elem.val(value);
}
});

JSON result containing only one item

I'm likely missing something with json and javascript.
[{"commentText":"Testing 123","userPosted":"maxfridbe"},
{"commentText":"Testing 23","userPosted":"maxfridbe"}]
Sometimes I get multiple responses which works with this code:
function(data)
{
var sel = this;
jQuery.each(data,
function()
{
sel.append("<li>"+ this.userPosted+ "-" + this.commentText + "</li>");
});
};
Sometimes I only get one response which breaks the above code:
[{"commentText":"another test again welcom","userPosted":"maxfridbe"}]
I know this is because the response is being treated differently than a list.
Looking for the answer to this I get a bit of a runaround. Any solution would be greatly appreciated.
In the second example you provide, it seems to be an array with only one item, if it's like that, it should work, but I think that you're getting only a single object like:
{"commentText":"another test again welcom","userPosted":"maxfridbe"}
If it's a single object $.each iterates over the object properties.
You could check if your data variable is not an array using $.isArray, and if is not, you can wrap it into a single element array, so the $.each function will still work as expected:
//..
if (!jQuery.isArray(data)) data = [data]; // if isn't an array, wrap it
jQuery.each(data, function() {
sel.append("<li>"+ this.userPosted+ "-" + this.commentText + "</li>");
});
//..
I think you should user some optional parameters in your each() function:
function(data)
{
var sel = this;
jQuery.each(data,
function(i, item)
{
sel.append("<li>"+ item.userPosted+ "-" + item.commentText + "</li>");
});
};
using THIS keyword creates confusion in your case
Hope this helps
Playing around with CMS's solution made me realize that data was just a string somehow so:
if (!jQuery.isArray(data)) data = eval(data);
worked because then the data was an object. Not sure why when there are multiple results it does an eval for you.

Categories