How to replace appendto to something else to update the data - javascript

I am listing AJAX data in cards using the below code. It works well, but if I run it with setinterval with other function with some condition, if that becomes true it calls the below function to update the listed data.
It append all the new data to the existing listing data and duplicates it. I know this is because I am using the appendTo function, I tried to replace it with HTML but that did not work, it didn't list the data at all.
I want to update the data when this function is called again, rather than appending data. What should I use for this? Thanks.
function orderlist() {
return $.getJSON( "/restaurant/order/list/100/1",
function( orderdata )
{
var items = [];
$.each( orderdata, function( key, val ) {
var $o_on = val.ordernumber;
var $o_odate = val.bizorderdate;
var $o_userid = val.userid;
var $o_tnumber = val.tablenumber;
var $o_a = "<div class='card' id="+$o_on+">"
+ "<div class='title'>"
+ "Order No." + $o_on + "</div>"
+ "Date & Time: " + $o_odate + " </br>"
+ "User: " + $o_userid + " </br>"
+ "Table No: " + $o_tnumber + " </br>"
+ "</div>";
items.push($o_a);
})
$( "<div/>",
{
"class": "row",
html: items.join( "" )
}).appendTo( "#list_of_orders" );
});
}

Use empty() to clear out the list and then append your new stuff.
$('#list_of_orders').empty().append($( "<div/>",
{
"class": "row",
"html": items.join( "" )
}

Related

Sanitize val() to append to avoid XSS

Currently I'm using checkmarx to find vulnerabilities on mi code.
The javascript files aparently haev some potential xss vulnerabilites when I use jquery val() function and then try to append this val. How should I solve, sanitize or encode this to avoid this problem?
Here some examples about what checkmarx mark as vulnerability:
function insertContactToTable(table) {
var ContactId = jQuery("#select_contacts").val();
var ContactName = jQuery("#select_contacts option:selected").text();
var Type = jQuery("#select_contact_type").val();
if (ContactId != "" && Type != "") {
var ID = ContactId + "_" + Type;
var Img = "<img class='image pointer-item' src='/app/assets/img/icon-package/cross.png' alt='cross' onClick='removeTableLine(\"" + ID + "\")'/>";
if (jQuery("#" + table + " tbody tr:last").length > 0) {
jQuery("#" + table + " tbody tr:last").after("<tr id='" + ID + "' name='" + ID + "'><td id='" + ID + "' name='contact_list'>" + ContactName + "</td><td>" + Type + "</td><td>" + Img + "</td></tr>");
} else {
jQuery("#" + table + " tbody").html("<tr id='" + ID + "' name='" + ID + "'><td id='" + ID + "' name='contact_list'>" + ContactName + "</td><td>" + Type + "</td><td>" + Img + "</td></tr>");
}
}
...
It marks the following error:
The application's insertContactToTable embeds untrusted data in the generated output with after, at line 542 of app\assets\js\administration.js. This untrusted data is embedded straight into the output without proper sanitization or encoding, enabling an attacker to inject malicious code into the output.
The line 542 is the jQuery("#select_contacts").val(); but it happens the same with the others lines that use .val() and .text() function.
Also, on other functions happens the same while getting this .val() or .text() functions and trying to use them with append() or html() functions.
Finally, I also have same issue while getting ajax response and try to append it with append() o html().
Note: I'm using php on my project, sanitizing most of the variables with it.
Edit
I changed to DOM object as suggested in comments and the code now looks like this:
var ContactId = jQuery("#select_contacts").val();
var ContactName = jQuery("#select_contacts option:selected").text();
var Type = jQuery("#select_contact_type").val();
if (ContactId != "" && Type != "") {
var ID = ContactId + "_" + Type;
var Img = jQuery("<img>", { "class": 'image pointer-item', alt: 'cross', "src": '/app/assets/img/icon-package/cross.png'
}).on("click", function() {
removeTableLine(ID);
});
var row = $("<tr>", { id:"TR_" +ID , name: ID })
.append($("<td>", { id: ID, name: 'contact_list', text: ContactName }))
.append($("<td>", { text: Type }))
.append($("<td>").append(Img));
$("#" + table + " tbody").append(row);
}
but I still have the problem
Don't create a string of HTML, create a DOM object and set its attributes.
if (ContactId != "" && Type != "") {
var ID = ContactId + "_" + Type;
var Img = jQuery("<img>", {
"class": 'image pointer-item',
alt: 'cross'
}).click(function() {
removeTableLine(ID);
});
var row = $("<tr>", {
id: ID,
name: ID
})
.append($("<td>", {
id: ID,
name: 'contact_list',
text: ContactName
}))
.append($("<td>").append(Img))
$("#" + table + " tbody").append(row);
}
You don't need different code depending on whether there's already a last row or not. Just append the new row to the table body.
You have another problem, you're using the same ID for the <tr> and first <td> in the row. If you really need them both to have an ID, they should have different IDs.
Use the DOMPurify library to sanitize the val() and text() return values before .append-ing it to the DOM
var ContactId = DOMPurify.sanitize(jQuery("#select_contacts").val());
var ContactName = DOMPurify.sanitize(jQuery("#select_contacts option:selected").text());
var Type = DOMPurify.sanitize(jQuery("#select_contact_type").val());
if (ContactId != "" && Type != "") {
var ID = ContactId + "_" + Type;
var Img = jQuery("<img>", { "class": 'image pointer-item', alt: 'cross', "src": '/app/assets/img/icon-package/cross.png'
}).on("click", function() {
removeTableLine(ID);
});
var row = $("<tr>", { id:"TR_" +ID , name: ID })
.append($("<td>", { id: ID, name: 'contact_list', text: ContactName }))
.append($("<td>", { text: Type }))
.append($("<td>").append(Img));
$("#" + table + " tbody").append(row);
}
If there are attributes or tags you want to be allowed, you can pass a second parameter to the sanitize function to define that whitelist:
// allow only <b> and <q> with style attributes
var clean = DOMPurify.sanitize(dirty, {ALLOWED_TAGS: ['b', 'q'], ALLOWED_ATTR: ['style']});

manipulate partial view's content with jquery

With the code below I am trying to update PartialView's HTML.
open_Modal_AssignAmendRoles = function (url) {
$.ajax({
url: url,//PartialView URL
cache: false,
type: "POST",
dataType: "html",
success: function (data, textStatus, XMLHttpRequest) {
var modalhtml = data;
var result = datafetchfunction("action URL", )
if (result.compleate == true) {
result.data.employeeroles.forEach(function (roletype) {
var tagbox = $(modalhtml).find("#tagbox" + roletype.clientroletypeid);
var span = $(modalhtml).find("#rolecontainer" + roletype.clientroletypeid);
var roletypeid = roletype.clientroletypeid
roletype.roles.forEach(function (role) {
var roleid = role.FK_ClientRoleID
var roledescription = role.ClientRole_Description;
var rolecode = role.ClientRole_Code
var markup = ""
markup += " <li class='taglist' id='" + roleid + "'>"
markup += " <button onclick='$(this).parent().remove()' class='tagclose'>"
markup += " <span class='glyphicon glyphicon-remove' aria-hidden='true'></span>"
markup += " </button>"
markup += " <a class='assignedrole' href='Javascript:void(0);' onclick='pop_click_fn(this)'"
markup += " role-id='" + roleid + "' role-type-id=" + roletypeid + ""
markup += " data-toggle='popover' data-trigger='hover' data-content='" + roledescription + "' data-placement='top' > " + rolecode + " </a>"
markup += " </li>";
$(span).append(markup)
})
})
openModal( modalhtml);
}
}
});
}
Step 1:
On button click the open_Modal_AssignAmendRoles() function is called. Then it goes to the success() function.
Step 2:
var result = datafetchfunction("action URL" )
this fetch data as JSON format
Step 3:
Then I start some loop, I already create some spans and find them with
var span = $(modalhtml).find("#rolecontainer" + roletype.clientroletypeid);
Step 4:
then I build a markup and assign this
$(span).append(markup)
and finally, call
openModal( modalhtml);
But modalhtml is not updated as expected, it means lis which I created with loop is not added.
Can someone tell me what is the problem and how to solve this?

How can I order the results of several async JQuery queries?

I'm pulling in information from several web services to display on a web page. I'd like to be able to order the results, but keep the fetching dynamic. However, the way I've structured the code means that the elements get inserted into the DOM in the order that the requests complete, which is non-deterministic. How can I guarantee a specific order, but avoid inserting 'dud' elements if one of the results errors out instead of returning valid info?
// Get my apps from iTunes
var iTunesLinks = ["525393529", "645218452", "737479996"];
var iTunesSquareSize = 128;
$.each(iTunesLinks, function(index, value) {
var iTunesLink = "https://itunes.apple.com/lookup?id=" + value + "&callback=?";
$.getJSON(iTunesLink, function(data) {
var items = [];
items.push("<section id=\"myApps\"><table>");
var results = data.results;
$.each ( results, function( key, val ) {
var appName = val.trackName;
var iconURL = val.artworkUrl100;
var appURL = val.trackViewUrl;
items.push( "<td align=center width=" + iTunesSquareSize + " style=\"vertical-align:top\">" + divStart + "</div><a href=" + appURL + " target=_blank>" + appName + "</a></td>" );
});
items.push("</table></section>");
$( "<td/>", {
"class": "applist",
html: items.join( "" )
}).appendTo( document.getElementById("myApps") );
});
});
You can use collect all the promises into an array, pass that to $.when() and then when that is resolved, you will have all the data from all the async ajax calls in order like this:
// Get my apps from iTunes
var iTunesLinks = ["525393529", "645218452", "737479996"];
var iTunesSquareSize = 128;
var promises = [];
$.each(iTunesLinks, function(index, value) {
var iTunesLink = "https://itunes.apple.com/lookup?id=" + value + "&callback=?";
promises.push($.getJSON(iTunesLink));
});
$.when.apply($, promises).done(function(/* arg1Array, arg2Array, arg3Array, ... */) {
// now process all the results in order
var items, results;
for (var i = 0; i < arguments.length; i++) {
// arguments[i] is an array of [data, statusText, jqXHR]
results = arguments[i][0].results;
items = [];
items.push("<section id=\"myApps\"><table>");
$.each ( results, function( key, val ) {
var appName = val.trackName;
var iconURL = val.artworkUrl100;
var appURL = val.trackViewUrl;
items.push( "<td align=center width=" + iTunesSquareSize + " style=\"vertical-align:top\">" + divStart + "</div><a href=" + appURL + " target=_blank>" + appName + "</a></td>" );
});
items.push("</table></section>");
$( "<td/>", {
"class": "applist",
html: items.join( "" )
}).appendTo( document.getElementById("myApps") );
}
});

search with an array associate with javascript?

I want to do a search by name and surname with an array javascript, and the results in a div. for example: I write Ali in input, an it shoul show me Alison and Alibaba.
this is my code, but it's giving errors; are there other ways to do it?:
<input type='text' id='filter' placeholder='search'>
<div id='output' style='margin-top:50px '></div>
my array
var arrayD =[
{"Name":"Alison","Surname":"Kenn","Mobile":529129293},
{"Name":"Ashton","Surname":"Jhojan","Mobile":529129293},
{"Name":"Bith","Surname":"Klint","Mobile":129129293},
{"Name":"Ana","Surname":"Clow","Mobile":229129293},
{"Name":"Geoge","Surname":"Rich","Mobile":329129293},
{"Name":"kenneth","Surname":"Cooler","Mobile":329129}
]
var $result = $('#output');
$('#filter').on('keyup', function () {
var $fragment = $('<div />');
var val = this.value.toLowerCase();
$.each(arrayD, function (i, item) {
console.log( item[0].toLowerCase().indexOf(val));
if ( item[0].toLowerCase().indexOf(val) == 0 ) {
$fragment.append('<li>' + item[0] + ' ' + item[1] + '</li>');
}
});
$result.html( $fragment.children() );
});
http://jsfiddle.net/henrykend/ChpgZ/4/
The main problem with your code is that you're trying to reference fields in the object by ordinal position rather than name. There is nothing automagic in JavaScript which will read item.Name (or item["Name"]) from item[0].
There is also no need to build up a "false element" (in your case $fragment) and then append its children to the output area - you may as well do this in one go (remembering to .empty() it between calls).
Your corrected code:
var $result = $('#result');
$('#output').on('keyup', function () {
$result.empty();
var val = this.value.toLowerCase();
$.each(arrayD, function (i, item) {
if ( item.Name.toLowerCase().indexOf(val) == 0 ) {
$result.append('<li>' + item.Name + ' ' + item.Surname + '</li>');
}
});
});
And a live example: http://jsfiddle.net/ChpgZ/6/
You had couple of problems in your code.
Names of the elements we're wrongly placed (which you've fixed with the edit)
In the .each, you've used item[0] instead of item.Name (also surname)
See the following code
var arrayD =[
{"Name":"Alison","Surname":"Kenn","Mobile":529129293},
{"Name":"Ashton","Surname":"Jhojan","Mobile":529129293},
{"Name":"Bith","Surname":"Klint","Mobile":129129293},
{"Name":"Ana","Surname":"Clow","Mobile":229129293},
{"Name":"Geoge","Surname":"Rich","Mobile":329129293},
{"Name":"kenneth","Surname":"Cooler","Mobile":329129}
]
var $result = $('#result');
$('#output').on('keyup', function () {
var $fragment = $('<div />');
var val = this.value.toLowerCase();
$.each(arrayD, function (i, item) {console.log( item.Name.toLowerCase().indexOf(val) );
if ( item.Name.toLowerCase().indexOf(val) == 0 ) {
$fragment.append('<li>' + item.Name + ' ' + item.Surname + '</li>');
}
});
$result.html( $fragment.children() );
});

Another jQuery autocomplete issue

So, i have read at least 20-30 auto complete problems here on so and i cannot find any solutions. For some odd reason i keep getting value = undefined. Here is my code.
//Cycles through each input and turns it into a person searcher.
$.each(settings.input, function() {
var input = $(this);
input.autocomplete({
delay: 70,
minLength: 2,
source: function(req, add) {
var val = input.val();
$.post(VUI.SITE_URL + "scripts/autocomplete/_AutoComplete.php", {q: val, display_count: settings.displayCount, action: "user"}, function(data) {
data = eval("(" + data + ")");
if (data.length > 0) {
var results = new Array(data.length);
$.each(data, function(key, value) {
results[key] = {desc: value, value: value.firstname + " " + value.lastname};
});
add(results);
} else {
add(["No results..."]);
}
});
},
select: function(event, ui) {
alert(ui.item ? ("Selected: " + ui.item.value + " aka " + ui.item.id) : "Nothing selected, input was " + this.value);
}
}) // end auto complete.
.data("autocomplete")._renderItem = function($ul, item) {
var $li = $("<li></li>"),
$inner = $("<div class='st-display side-content clearfix'style='padding-top:6px'></div>"),
$a = $("<a></a>"),
$img = $("<div class='image fl'></div>").html(ST.Image.getImage({
uid: item.desc.uid,
type: ST.ST_IMAGE_TYPE_THUMBNAIL_SMALL
})),
$content = $("<div class='content fl'></div>").html(
item.desc.firstname + " " + item.desc.lastname + "<br/>" +
"<span class='color:#979797;font-weight:bold'>" + item.desc.city + ", " + item.desc.state + "</span>"
);
$inner.append($img).append($content);
$a.append($inner);
$li.append($a);
$ul.append($li);
return $ul;
} // end _renderItem */
I tried to make it so that its very straight forward. But it wont work! (its facebook like auto complete). The auto complete displays properly (item does not equal undefined at that point), but when i highlight it, item becomes undefined so item.value (line 6347 of jquery.ui.1.8.13) throws exception!
Anyone see problems?
Here is something interesting... When i do not use data("autocomplete")._renderItem (for custom completion) the selecting works! ... So why does overriding the custom rendering cause issues? I am even returning the UL.
The only thing in your code that's different from a working version I've got of something very similar is that I initialise $li with:
var $li = $( '<li></li>' ).data('item.autocomplete', item);
That attaches the data to the list item which I think the autocomplete plugin uses to get the value at selection time.
Hope it helps

Categories