straight to the point
i have the following javascript and jquery code which update some checked rowsand do some stuff on each datatables row. here is my code:
function checkUpdate(){
setInterval(function(){
var listLength = updateList.length;
if(listLength > 0){
for(var r=0; r<listLength; r++){
// console.log(r)
var clID = updateList[r];
// console.log(clID)
var rRow = $('#dataTable tbody tr').find('td[data-clientid="'+clID+'"]').parent('tr');
// console.log(rRow)
var rRowIndex = rRow.index();
// console.log(rRowIndex)
var rRowDataIndex = oTable.fnGetPosition(rRow[0]);
console.log(rRowDataIndex)
$.ajax({
url: '/cgi-bin/if-Clients-list.jpl',
data: 'session=' + recievedSession + '&clientid=' + clID + '&outputformat=json',
dataType: 'json',
success: function(rowData){
// console.log(rowData)
var newRow = [];
var newOrderedRow = [];
console.log(rRowDataIndex)
newRow.push(rRowDataIndex+1, "");
for (var title in rowData[0]){
newRow.push(rowData[0][title]);
}
console.log(newRow)
},
});
};
}
},2000)
};
here is the problem:
after $.ajax() call, rRowDataIndex variable does not update or it updates but there is a problem in scopes and priorities that i couldn't understand
if i check 2 rows or more all the console.log(newRow)'s first elements will be the same
can anyone help me?
PS. i can nor present any code on web
thanks every body
You need to wrap the AJAX call in a closure to capture the value of rRowDataIndex each time through the loop.
function checkUpdate() {
setInterval(function () {
var listLength = updateList.length;
if (listLength > 0) {
for (var r = 0; r < listLength; r++) {
// console.log(r)
var clID = updateList[r];
// console.log(clID)
var rRow = $('#dataTable tbody tr').find('td[data-clientid="' + clID + '"]').parent('tr');
// console.log(rRow)
var rRowIndex = rRow.index();
// console.log(rRowIndex)
var rRowDataIndex = oTable.fnGetPosition(rRow[0]);
console.log(rRowDataIndex)
(function (rRowDataIndex) {
$.ajax({
url: '/cgi-bin/if-Clients-list.jpl',
data: 'session=' + recievedSession + '&clientid=' + clID + '&outputformat=json',
dataType: 'json',
success: function (rowData) {
// console.log(rowData)
var newRow = [];
var newOrderedRow = [];
console.log(rRowDataIndex)
newRow.push(rRowDataIndex + 1, "");
for (var title in rowData[0]) {
newRow.push(rowData[0][title]);
}
console.log(newRow)
},
});
})(rRowDataIndex);
};
}
}, 2000);
}
Related
I'm a relative newbie to javascript and I'm trying to make multiple ajax calls within a for loop. It loops through the elements of an array using a different url for an ajax call each time it goes through the loop. The problem is that the value of the variable 'test' is always equal to "condition4". I'm used to other languages where the value of 'test' would be "condition1", then "condition2" etc as it goes through the for loop. Here is a simplified version of my code:
var myData = [];
var cnt = 0;
var link;
var myCounter = 0;
var myArray = ["condition1", "condition2", "condition3", "condition4"];
for (x = 0; x < myArray.length; x++) {
link = "https://test.com/" + myArray[x];
myCounter = x;
GetJSON(function (results) {
for (i = 0; i < results.data.length; i++) {
var id = results.data[i].identifier;
var test = myArray[myCounter];
myData[cnt] = { "id": id, "test": test };
cnt++;
}
});
}
function GetJSON(callback) {
$.ajax({
url: link,
type: 'GET',
dataType: 'json',
success: function (results) {
callback(results);
}
});
}
I think you can solve this issue by sending and receiving myCounter value to server
for (x = 0; x < myArray.length; x++) {
link = "https://test.com/" + myArray[x];
myCounter = x;
$.ajax({
url: link,
type: 'GET',
dataType: 'json',
data: { myCounter: myCounter}
success: function(results) {
for (i = 0; i < results.data.length; i++) {
var id = results.data[i].identifier;
var test = results.data[i].myCounter
myData[cnt] = {
"id": id,
"test": test
};
cnt++;
}
}
});
}
When you are executing the loop, it attaches the myCounter reference. Then, due to the async task, when it finishes and call 'myCounter', it has already achieved the number 4. So, when it call 'myCounter', it is 4. To isolate the scope, you need to create a new scope every iteration and isolating each value of 'myCounter'
for (x = 0; x < myArray.length; x++) {
link = "https://test.com/" + myArray[x];
myCounter = x;
//IIFE
(function() {
var ownCounter = myCounter; //Isolating counter
GetJSON(function (results) {
for (i = 0; i < results.data.length; i++) {
var id = results.data[i].identifier;
var test = myArray[ownCounter];
myData[cnt] = { "id": id, "test": test };
cnt++;
}
});
})();
}
Or...
for (let x = 0; x < myArray.length; x++) {
link = "https://test.com/" + myArray[x];
myCounter = x;
GetJSON(function (results) {
for (i = 0; i < results.data.length; i++) {
var id = results.data[i].identifier;
var test = myArray[x];
myData[cnt] = { "id": id, "test": test };
cnt++;
}
});
}
I have the following function:
function getData(a,url) {
var deferreds = [];
var i = 1;
for (i = 1; i <= a.length; i++) {
var count = i;
var back = a[i]['link'];
var path = "http://example.com";
deferreds.push(
$.ajax({
url:path,
data:{back:back,link:url},
type:"POST",
async: true,
delay: count
}).done(function(data) {
//success function here
}));
}
return deferreds;
}
My question is how to make this script to run a queue, for example I have 2000 requests, how to put them in a queue of 100 one by one?
Maybe in this way (Of course is a simplification)
var completed = 0;
var limit_simultaneous = 100;
var total_requests = 2134 // Assign your var
function send_block() {
for (i = 0; i < limit_simultaneous; i++) {
$.ajax({
url:path,
data:{back:back,link:url},
type:"POST",
async: true,
}).done(function(data) {
completed++;
send_next_block();
//success function here
}));
}
}
function send_next_block()
{
if (completed == limit_simultaneous && total_requests > 0) {
total_requests = total_requests - completed;
if (total_requests < limit_simultaneous) {
limit_simultaneous = total_requests;
}
completed = 0;
// Fire again
send_block(); // Send another 100
}
}
I hope it helps.
EDIT Edit to take account about the total requests. Maybe is not a working code, but it is the idea.
Javascript Code:
function createdivs()
{
var i = 1;
$.ajax({ url: 'displaycontent.php',
data: {action:'test'},
type: 'post',
datatype: 'json',
success: function(output) {
var a = JSON.parse(output);
var b = a.length;
var i;
for (i = 0; i < b;i++){
console.log(a[i]['idi']);
console.log(a[i]['pgmname']);
console.log(a[i]['comp']);
console.log(a[i]['datephp']);
if (a[i]['idi'] != 0){
for (var j=0 ;j < 1;j++)
{
var editp = document.createElement("button","span");
document.getElementById('contentdisplay'+i).appendChild(editp);
editp.className = "glyphicon glyphicon-pencil";
editp.id = "editprogramsbutton"+i;
$("#editprogramsbutton"+i).click(function(){
editp.value = i;
alert(i);
});
}
}
}
}
});
}
Suppose if the loop runs for 3 times, I can create three buttons with id's as editprogramsbutton0, editprogramsbutton1, editprogramsbutton2. The problem is when I alert using
$("#editprogramsbutton"+i).click(function(){
editp.value = i;
alert(i);
});
I always get the value as 3 no matter which button I press. I know that the value of 'i' is set to 3 and it'll display the last updated value whenever I press the button. I want values like "0" when I press "editprogramsbutton0", "1" when I press "editprogramsbutton1" and so on.. Can someone please explain the logic of how to do this with possible changes in the code. Thank you in advance.
This is the key, you have to define the value outside of the click function, otherwise it will update the value to the last i set. Then call either e.target.value (make sure e is defined in the function call) or this.value (as inside an event handler this refers to the element that was clicked)
editp.value = i;
editp.addEventListener('click', function(e) {
alert(e.target.value);
}, false);
In the hidden snippet below I've simplified your script and removed unnecessary lines and document calls.
function createdivs() {
$.ajax({
url: 'displaycontent.php',
data: { action: 'test' },
type: 'post',
datatype: 'json',
success: function (output) {
var a = JSON.parse(output);
var fullDisplay = document.getElementById('fulldisplay');
for (var i = 0; i < a.length; i++) {
console.log(a[i]['idi']);
console.log(a[i]['pgmname']);
console.log(a[i]['comp']);
console.log(a[i]['datephp']);
if (a[i]['idi'] != 0) {
fullDisplay.style.visibility = "visible";
var list = document.createElement("div");
list.className = "container content-rows content";
list.id = "contentdisplay" + i;
var sno = document.createElement("span");
sno.className = "col-md-1 snocontent text_center_align";
sno.id = "snocontent" + i;
sno.innerHTML = a[i]['idi'];
list.appendChild(sno);
var pgmno = document.createElement("span");
pgmno.className = "col-md-3 pgmnamecontent";
pgmno.id = "pgmnocontent" + i;
pgmno.innerHTML = a[i]['pgmname'];
list.appendChild(pgmno);
var cmpno = document.createElement("span");
cmpno.className = "col-md-3 cmpcontent";
cmpno.id = "cmpnocontent" + i;
cmpno.innerHTML = a[i]['comp'];
list.appendChild(cmpno);
var dateno = document.createElement("span");
dateno.className = "col-md-2 datecontent";
dateno.id = "datenocontent" + i;
dateno.innerHTML = a[i]['datephp'];
list.appendChild(dateno);
var addtra = document.createElement("button", "span");
addtra.className = "glyphicon glyphicon-king";
addtra.id = "addtrainersbutton" + i;
list.appendChild(addtra);
var editp = document.createElement("button", "span");
editp.className = "glyphicon glyphicon-pencil";
editp.id = "editprogramsbutton" + i;
editp.value = i;
editp.addEventListener('click', function(e) {
alert(e.target.value);
}, false);
list.appendChild(editp);
var assigntra = document.createElement("button", "span");
assigntra.className = "glyphicon glyphicon-user";
assigntra.id = "assigntrainersbutton" + i;
list.appendChild(assigntra);
var deletep = document.createElement("button", "span");
deletep.className = "glyphicon glyphicon-pencil";
deletep.id = "deleteprogrambutton" + i;
list.appendChild(deletep);
fullDisplay.appendChild(list);
}
}
}
});
}
I am trying to dynamically populate the jquery chosen plugin both with "optgroup" and "option". I therefore have nested ajax requests and forloops:
$.ajax({
url: '#Html.Raw(Url.Action("GetCat", "MController"))',
data: { ID: metada },
success: function (data) {
var categories = data.split(",");
for (i = 0; i < categories.length; i++) {
$.ajax({
url: '#Html.Raw(Url.Action("GetCat", "MController"))',
data: { ID: cetada },
success: function (data) {
$("#picker").append("<optgroup label='" + categories[i] + "'>");
var subcategories = data.split(",");
for (i = 0; i < subcategories.length; i++) {
$("#picker").append("<option value='"+subcategories[i]+"'>" + subcategories[i] + "</option>")
}
$("#picker").append("</optgroup>");
}
});
}
$("#picker").trigger('chosen:updated');
}
});
Currently when I run the above the chosen select is empty and no options or optgroups are visible.
I think you need to use promises for this:
var promises = [];
for (var i = 0; i < categories.length; i++) {
promises.push(
(function(innerI){
return $.ajax({
url: '#Html.Raw(Url.Action("GetCat", "MController"))',
data: { ID: cetada },
success: function (data) {
var optgroup = $('<optgroup>').attr('label', categories[innerI]);
var subcategories = data.split(",");
for (var i = 0; i < subcategories.length; i++) {
var option = $('<option>').val(subcategories[i]).text(subcategories[i]);
optgroup.append(option);
}
$("#picker").append(optgroup);
}
});
})(i)); // unbind i to make closure work.
}
$.when.apply($, promises).then(function() {
$("#picker").trigger('chosen:updated');
});
UPDATE1:
I missed closures on first look, now th code is updated.
UPDATE2:
Rewrote working with tags inside success callback of ajax request.
UPDATE3:
Here is simple demo, I've commented some non-important code to show how it works.
I'm trying to make an XML based menu with JavaScript, XML and jQuery. I've been successful at getting the categories of the menu, but haven't been able to generate the items in the categories.
My script is as follows, and later in this thread, I've asked for suggestions for this code:
var animalsXMLurl = 'http://dl.dropboxusercontent.com/u/27854284/Stuff/Online/XML_animals.xml';
$(function() {
$.ajax({
url: animalsXMLurl, // name of file you want to parse
dataType: "xml",
success: function parse(xmlResponse) {
var data = $("item", xmlResponse).map(function() {
return {
id: $("animal_id", this).text(),
title: $("animal_title", this).text(),
url: $("animal_url", this).text(),
category: $("animal_category", this).text().split('/'),
};
}).get();
var first_item = category_gen(data, 0);
$('ul.w-nav-list.level_2').append(first_item);
var categnumber = new Array();
for (i = 1; i <= data.length; i++) //for splitting id, and getting 0 for category_number (1 or 2 or 3...and so on)
{
categnumber[i] = data[i].id.split('_');
console.log(categnumber[i][0]);
for (j = 1; j <= data.length; j++) //appending via a function.
{
var data_text = category_or_animal(data, categnumber, j);
console.log(data_text);
$('ul.w-nav-list.level_2').append(data_text);
}
}
function category_or_animal(d, catg, k) {
var catg1 = new Array();
var catg2 = new Array();
var catg1 = d[k].id.split('_');
if (d[k - 1]) {
var catg2 = d[k - 1].id.split('_');
//if(d[k-1].id)
if (catg1[0] != catg2[0])
return category_gen(d, k);
} else
return '</ul>' + animal_gen(d, k);
}
function category_gen(d, z) {
var category_var = '<li class="w-nav-item level_2 has_sublevel"><a class="w-nav-anchor level_2" href="javascript:void(0);"><span class="w-nav-title">' + d[z].category + '</span><span class="w-nav-arrow"></span></a><ul class="w-nav-list level_3">';
return category_var;
}
function animal_gen(d, z) {
var animal_var = '<li class="w-nav-item level_3"><a class="w-nav-anchor level_3" href="animals/' + d[z].url + '"><span class="w-nav-title">' + d[z].title + '</span><span class="w-nav-arrow"></span></a></li>';
return animal_var;
}
}, error: function() {
console.log('Error: Animals info xml could not be loaded.');
}
});
});
Here's the JSFiddle link for the above code: http://jsfiddle.net/mohitk117/d7XmQ/4/
In the above code I need some alterations, with which I think the code might work, so I'm asking for suggestions:
Here's the function that's calling separate functions with arguments to generate the menu in above code:
function category_or_animal(d, catg, k) {
var catg1 = new Array();
var catg2 = new Array();
var catg1 = d[k].id.split('_');
if (d[k - 1]) {
var catg2 = d[k - 1].id.split('_');
//if(d[k-1].id)
if (catg1[0] != catg2[0])
return category_gen(d, k);
} else
return animal_gen(d, k) + '</ul>';
}
At the if(catg1[0] != catg2[0]) it checks if the split string 1_2 or 1_3 is equal to 1_1 or 1_2 respectively. By split, I mean the first element: 1 .... if you have a look at the xml: [ :: Animals XML :: ], you'll see that the animal_id is in the format of %category_number% _ %item_number% ... So I need to create the menu with CATEGORY > ITEM (item=animal name)
Now if I could return category_gen() + animal() with animal(){ in a for loop for all the matching category id numbers} then maybe this could be complete! But I don't of a count script for conditioning the for loop (i=0;i<=count();i++)...
Would anyone know of how to get this script functioning?
Hard to tell what the provided JSFiddle is trying to do.
This is my best stab at it. I used JQuery to parse the XML out into categories and generate lists of items.
http://jsfiddle.net/d7XmQ/8/
"use strict";
var animalsXMLurl = 'http://dl.dropboxusercontent.com/u/27854284/Stuff/Online/XML_animals.xml';
$(function () {
var $menu = $('#menu');
$.ajax({
url: animalsXMLurl, // name of file you want to parse
dataType: "xml",
success: handleResponse,
error: function () {
console.log('Error: Animals info xml could not be loaded.');
}
});
function handleResponse(xmlResponse) {
var $data = parseResponse(xmlResponse);
createMenu($data);
}
function parseResponse(xmlResponse) {
return $("item", xmlResponse).map(function () {
var $this = $(this);
return {
id: $this.find("animal_id").text(),
title: $this.find("animal_title").text(),
url: $this.find("animal_url").text(),
category: $this.find("animal_category").text()
};
});
}
function createMenu($data) {
var categories = {};
$data.each(function (i, dataItem) {
if (typeof categories[dataItem.category] === 'undefined') {
categories[dataItem.category] = [];
}
categories[dataItem.category].push(dataItem);
});
$.each(categories, function (category, categoryItems) {
var categoryItems = categories[category];
$menu.append($('<h2>').text(category));
$menu.append(createList(categoryItems));
});
}
function createList(categoryItems) {
var $list = $('<ul>');
$.each(categoryItems, function (i, dataItem) {
$list.append(createItem(dataItem));
});
return $list;
}
function createItem(dataItem) {
return $('<li>').text(dataItem.title);
}
});
You can solve this without using any for/while loop or forEach.
function myCounter(inputWords) {
return inputWords.reduce( (countWords, word) => {
countWords[word] = ++countWords[word] || 1;
return countWords;
}, {});
}
Hope it helps you!