Jquery array.length is shorter than the real array length - javascript

I'm new to jquery and a I've got the problem as mentioned in the title.
My controller code looks like:
[HttpPost]
public JsonResult getProjectList()
{
List<Project> projectList = new List<Project>();
foreach (IML.ProjectInfo pr in getProjectArray())
{
Project x = new Project(pr.Name, pr.ID, pr.OwnerID, pr.CreatedBy, pr.CreatedAt, "", pr.Deleted, pr.Closed);
projectList.Add(x);
}
return Json(projectList.ToArray());
}
When I check the projectList under debugger mode it has 6 elements.
In my webpage I have the following ajax call:
$.ajax({
url: '#Url.Action("getProjectList")',
type: "POST",
//enumerowanie projektów
success: function (data) {
projekty = data;
var wyswietl ="<table><tbody>";
var tabelka = "";
var wybranyProjekt;
alert($.data.length);//this alert tells me that data.length is 3
for (i = 0; i < 6; i++)//even if $.data.length is 3 the data[i].Name holds values for 6 elements
{
tabelka += "<tr class=\"enumeracjaProj\" id=\"" + i
+ "\"><td class=\"projekty\" id=\"" + i + "\"> " + data[i].Name + " </td></tr>"
}
wyswietl += tabelka;
wyswietl += "</tbody></table>";
$('#projekty_div').append(wyswietl);
})
Even if I Post an array of 6 elements ajax result tell me that its length is 3. If I go over it in loop which was 6 iterations hard-coded I get properly displayed name.

Small correction, You should change your alert($.data.length); to alert(data.length);
$.data is jQuery function and your data is response result

Related

jquery (server side) search and sorting using ajax

I tried to create search and sort from live URL using Ajax , i used do search function and i managed to retrieve the data from the URL .
I am showing Ajax response in select options as below code. I want to sort the select options in order of values (level values),the values are retrieved randomly in the results.
How can I combine search and sort function for that ?I used lots of tutorials to do that. To anyone who knows please help me to do that. Thank you.
Please provide a solution to automate sort data with the current search function on values basis (by level) . Sample of the current results like :
So far I have this code:
function doSearch() {
$.Ajax({
URL: 'https://live.ksmobile.net/live/BOYS',
data: {
page_size: 10,
page_index: current_page
},
cache: false,
type: 'GET',
datatype: 'JSON',
success: function(r) {
var max = $('#limit').VAL();
if (r.data.video_info.length < max) max = r.data.video_info.length;
for (index = 0; index < max; index++) {
var entry = r.data.video_info[index];
var level = parse Int(entry.level);
if ((level > $('#min').val()) && (level < $('#max').val())) {
count++;
var HTML = '<div class="entry ' + '"><h="' + entry + '">';
HTML += '<h3>Level: <span>' + entry.level + '</span> <span>' + entry.name + '' + '</span>id:<span>' + entry.heat;
HTML += '</div>';
$('#main').append(HTML);
}
}
You could write a custom sort function which would look something like:
function sortResults(array) {
array.sort(function(x, y) {
if (parseInt(x.level, 10) < parseInt(y.level, 10)) {
return -1;
}
if (parseInt(x.level, 10) > parseInt(y.level, 10)) {
return 1;
}
return 0;
});
}
and then call it before your for loop:
sortResults(r.data.video_info);
You could also use a library like lodash to save some trouble and then use:
r.data.video_info = _.sortBy(r.data.video_info, item => {
return _.parseInt(item.level);
});

I want to clear my table data before adding new data from the api request? i have tried to use multiple methods [duplicate]

This question already has an answer here:
JQuery clear HTML table and insert new rows
(1 answer)
Closed 3 years ago.
$("#artistButton").on('click', function () {
var artist = $("#artistSearch").val().trim()
var queryURL = "https://rest.bandsintown.com/artists/" + artist + "/events?app_id=test&date=upcoming" + artist + "?app_id=test";
console.log(artist)
$.ajax({
url: queryURL,
method: "GET"
}).then(function (response) {
var imageURL = response[0].artist.image_url;
var image = $("<img id='pictureSize'>")
var artistName = response[0].artist.name
console.log(response)
$("#artistName").html(artistName)
image.attr('src', imageURL)
$("#artistImage").html(image)
$("#venue").html(response[125].venue.name)
for (var i = 0; i < response.length || 5; i++) {
var time = moment(response[i].datetime).format("MMM Do, hh:mm");
var venueName = response[i].venue.name
var city = response[i].venue.city;
var region = response[i].venue.region
if (i == 5) {
break;
}
$(".tableData").before($("<tr><td>" + venueName + "</td>" + "<td>" + city + ', ' + region + "</td>" + "<td>" + time + "</td></tr>"))
}
});
$(".tableData").val("");
})
Wanted to answer my own question in case someone had the same issue but i simply added $("#concertInfo").find("td").remove(); after my ajax call and it will remove all table data!
You can use empty or remove function to set the table content before adding new ones.
Empty: "Remove all child nodes of the set of matched elements from the DOM."
Remove: "Remove the set of matched elements from the DOM."

How to recursively build a list using a callback and iterating through the children?

I'm unsure on how to build this list (which is a string) and then returning as one complete string.
I've worked past my last issue but I think this one is realy bugging me. buildItem() should iterate through item, and then recursively build a list while getting the totalCost from another callback. I know it works asynchronously...
buildItem(data, function(html){
$('#nestable ol').append(html);
});
Should append the 'final' html string that's created from being appended throughout the file.
function buildItem(item, callback) {
getTotalCost(item, function(totalCost) {
var html = "<li class='dd-item' data-id='" + item.id + "' data-email='" + item.email + "' data-title='" + item.corporateTitle + "' data-name='" + item.firstName + " " + item.lastName + "' id='" + item.id + "'>";
if (item.children && item.children.length > 0) {
html += "<ol class='dd-list'>";
$.each(item.children, function (index, sub) {
buildItem(item, function(subHtml){
html += subHtml;
})
})
html += "</ol>";
}
html += "</li>";
callback(html);
});
}
I know that
buildItem(item, function(subHtml){
html += subHtml;
})
shouldn't work since javascript is asynchronous. I'm just not sure on how to return from a recursive function? If I were to do something like
buildItem(item, function(subHtml){
callback(subHtml);
})
You'll get duplicate values because you'll have the starting value and it's children, but since you're also calling it back you'll get the children outside of the starting value. So it'll look like
1
a
b
c
d
e
a
b
c
d
e
So what's the best way to approach a solution? I was thinking of making another function, hypothetically a buildChild(sub) that returned html, but the same issue with asynchronous is going to come up where the return will be undefined. I've read some of the threads where you can handle asynchronous values with callbacks, but I'm not sure on how to do it with recursion here.
getTotalCost is another callback function that shouldn't mean much, I removed the line by accident but I just need the totalCost from a database.
function getTotalCost(item, callback) {
$.ajax({
dataType: "json",
url: "/retrieveData.do?item=" + item.email,
success: function(data) {
var totalCost = 0;
for (var i = 0; i < data.length; i++) {
totalCost += parseFloat(data[i].cost);
}
callback(totalCost);
}
});
}
You can simplify this with promises and async functions:
async function getTotalCost(item) {
const data = await Promise.resolve($.ajax({
dataType: "json",
url: "/retrieveData.do?item=" + item.email
}));
return data.reduce((acc, next) => acc + next.cost, 0);
}
async function buildItem(item) {
const totalCost = await getTotalCost(item);
let html = `<li class="dd-item" data-id="${item.id}" data-email="${item.email}" data-title="${item.corporateTitle}" data-name="${item.firstName} ${item.lastName}" id="${item.id}">`;
if (item.children && item.children.length > 0) {
html += '<ol class="dd-list">';
for (const childItem of item.children) {
html += await buildItem(childItem);
}
html += "</ol>";
}
html += "</li>";
return html;
}
Unfortunately, async functions aren't supported by all browsers yet, so you'll have to use Babel to transpile your code.
I also added some new ES6 features: arrow functions, const and template literals.
You can mix slow ajax requests with logic and recursion if you execute your code via synchronous executor nsynjs.
Step 1. Write your logic as if it was synchronous, and place it into function:
function process(item) {
function getTotalCost(item) {
var data = jQueryGetJSON(nsynjsCtx, "/retrieveData.do?item=" + item.email).data;
var totalCost = 0;
for (var i = 0; i < data.length; i++) {
totalCost += parseFloat(data[i].cost);
}
return totalCost;
};
function buildItem(item) {
const totalCost = getTotalCost(item);
var html = "<li class='dd-item' data-id='" + item.id + "' data-email='" + item.email + "' data-title='" + item.corporateTitle + "' data-name='" + item.firstName + " " + item.lastName + "' id='" + item.id + "'>";
if (item.children && item.children.length > 0) {
html += '<ol class="dd-list">';
for (var i=0; i<item.children.length; i++)
html += buildItem(item.children[i]);
html += "</ol>";
}
html += "</li>";
return html;
};
return buildItem(item);
};
Step 2: run it via nsynjs:
nsynjs.run(process,{},item,function (itemHTML) {
console.log("all done",itemHTML);
});
Please see more examples here: https://github.com/amaksr/nsynjs/tree/master/examples

JavaScript Callbacks for multiple functions

I'm currently trying to take results I have from an api controller, and have that json data added to a table in my razor view. I had some issues with the array I was using to fill the table not being filled with data before the table was created. I've tried to absolve that problem with callbacks, but I'm still inexperienced, and having trouble understanding from tutorials.
Here are the javascript function I have (and in order they must go 1. the $.getJson 2. the fillArray function 3. the AddToTable function) :
$(document).ready(function ()
{
$.getJSON('api/GetRestaurants/detroit').done(fillArray(data))
});
function fillArray(data, callback)
{
var restaurant =
{
Name: "",
PhoneNumber: "",
PlaceID: "",
Rating: 0,
Website: ""
};
var dataArray = new Array();
for (var k = 0; k < data.length; k++) {
restaurant.Name = data[k].Name;
restaurant.PhoneNumber = data[k].PhoneNumber;
restaurant.PlaceID = data[k].PlaceID;
restaurant.Rating = data[k].Rating;
dataArray.push(restaurant);
}
callback(AddToTable(dataArray));
}
function AddToTable(dataArray) {
document.getElementById("tbl").innerHTML =
'<tr>' +
'<th>Restaurant Name</th>' +
'<th>Restaurant PlaceID</th>'
for (var i = 0; i < dataArray.length; i++) {
+'<tr>'
+ '<td>' + dataArray[i].Name + '</td>'
+ '<td>' + dataArray[i].PlaceID + '</td>'
+ '</tr>';
}
}
The data is there, and the api controller call is successful, I just need to data to fill the array before the table uses that array.
I appreciate any help and/or comments, thanks guys :].
When you do the following:
$.getJSON('api/GetRestaurants/detroit').done(fillArray(data))
You are calling the fillArray() function and passing its result to the .done() function. Instead, you should be passing the fillArray function to the .done() function.
$.getJSON('api/GetRestaurants/detroit').done(fillArray)
I prefer to use an anonymous function when setting a callback. Then the named functions can have the signatures that make sense for them. The anonymous callback function, of course, has the signature required for it. The named functions are then called inside the anonymous callback function.
$(document).ready(function() {
$.getJSON('api/GetRestaurants/detroit').done(function(data) {
var restaurants = createRestaurantArray(data);
addRestaurantsToTable(restaurants);
});
});
function createRestaurantArray(apiData) {
var restaurants = []; // Preferred syntax over "new Array()"
for (var i = 0; i < apiData.length; i++) {
restaurants.push({
Name: apiData[i].Name,
PhoneNumber: apiData[i].PhoneNumber,
PlaceID: apiData[i].PlaceID,
Rating: apiData[i].Rating,
Website: ""
});
return restaurants;
}
function addRestaurantsToTable(restaurants) {
var html = '<tr>'
+ '<th>Restaurant Name</th>'
+ '<th>Restaurant PlaceID</th>'
+ '</tr>';
for (var i = 0; i < restaurants.length; i++) {
html += '<tr>'
+ '<td>' + restaurants[i].Name + '</td>'
+ '<td>' + restaurants[i].PlaceID + '</td>'
+ '</tr>';
}
$('#tbl').html(html);
}
Also, your fillArray() function was creating a single restaraunt object and pushing that same object to the array for each iteration of the for-loop. That means the resulting array would contain the same object over and over, and that object would have the property values set by the last iteration of the loop.
All the commands in your fillArray function appear to be synchronous (i.e. the code does not move on until they are completed) so as long as this is called before your function to add the data you should be okay.

Retrieve JSON values from Javascript array [duplicate]

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 7 years ago.
I'm new to using JSON and Javascript, but I am trying to sort various values of the JSON file provided by Reddit. In the console, I do see the array and the JSON values from the console.log(posts) print. However, the console.log(posts.length) statement returns 0 and nothing is displayed to the screen, which I suspect is due to how I am storing and/or retrieving the JSON values in the array.
var minVotes = 5;
var subreddit = "askreddit";
var posts = [];
//Retrieve JSON from Reddit using JQuery
$.getJSON("https://www.reddit.com/r/" + subreddit + "/rising.json?limit=50", function foo(result) {
$.each(result.data.children.slice(0, 50), function(i, post) {
if (post.data.ups > minVotes) {
//Push JSON data to array to be sorted later
posts.push(post.data);
}
})
})
//Sort the array
posts.sort(function(a, b) {
return parseInt(a.data.ups - a.data.num_comments) - parseInt(b.data.ups - b.data.num_comments);
});
console.log(posts);
console.log(posts.length); //returns 0 ???
//Display the content, which doesn't work
for (var i = 0; i < posts.length; i++) {
$("#reddit-content").append('<br>' + "Title: " + posts[i].title);
$("#reddit-content").append('<br>' + "Url: " + posts[i].url);
$("#reddit-content").append('<br>' + "Upvotes: " + posts[i].ups);
$("#reddit-content").append('<br>' + "Comments: " + posts[i].num_comments);
$("#reddit-content").append('<hr>');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="reddit-content"></div>
It's because of the async nature of $.getJSON. If you sort the array inside the response handler it works fine.
You also had another issue in your sort with accessing the property values. I don't believe you need to parseInt either as JSON.parse will return those values as numbers already.
var minVotes = 5;
var subreddit = "askreddit";
//Retrieve JSON from Reddit using JQuery
$.getJSON("https://www.reddit.com/r/" + subreddit + "/rising.json?limit=50", function foo(result) {
var posts = [];
$.each(result.data.children.slice(0, 50), function(i, post) {
if (post.data.ups > minVotes) {
//Push JSON data to array to be sorted later
posts.push(post.data);
}
});
//Sort the array
posts.sort(function(a, b) {
return parseInt(a.ups - a.num_comments) - parseInt(b.ups - b.num_comments);
});
console.log(posts);
console.log(posts.length);
//Display the content, which doesn't work
for (var i = 0; i < posts.length; i++) {
$("#reddit-content").append('<br>' + "Title: " + posts[i].title);
$("#reddit-content").append('<br>' + "Url: " + posts[i].url);
$("#reddit-content").append('<br>' + "Upvotes: " + posts[i].ups);
$("#reddit-content").append('<br>' + "Comments: " + posts[i].num_comments);
$("#reddit-content").append('<hr>');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="reddit-content"></div>

Categories