Foreach in JS array - javascript

I am beginner in JS. I have this sample array:
{"record-164": {"tomany": true, "fileName": "164"},"record-165": {"tomany": true, "fileName": "165"}}
and code JS:
var data = JSON.parse(json);
if (data["tomany"] == true && data["fileName"] !=""){
var fileName = data["fileName"];
$.ajax({
headers: {
'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')
},
cache: false,
type: 'POST',
url: '{{ route('deleteDJS') }}?id=' + fileName + '&type={{ $pageType }}',
data: {filename: fileName, id: fileName, type: '{{ $pageType }}'},
success: function (data) {
console.log("Delete file" +fileName);
refreshFileList();
//updatePhotoList();
},
error: function (e) {
console.log(e);
}
});
alert('Limit plików został przekroczony. Możesz dodać maksymalnie: ');
return;
}
The above code does not work correctly.
I would like the js script to delete it when the file has the parameter: tomany == true.
The delete function works correctly.
Problem is with file name and tomany parameters - I have many files - not one to delete/parse.
How can I repair this?

Use for in to iterate your object as below.
for(var item in data){
if (data[item]["tomany"] == true && data[item]["fileName"] !=""){
// perform your task here
}
}

First that is an object its not array.
You can distinguish object and array using this
starts with { -> object
example
const d = {'name':'your-name', 'age':23};
starts with [ -> array
const d_array = [{'name':'your-name', 'age':23},{'name':'your-name-2', 'age':26}];
You can iterate your object like this and then do the ajax.
const data = {"record-164": {"tomany": true, "fileName": "164"},"record-165": {"tomany": true, "fileName": "165"}}
for(let key in data){
console.log(data[key]["tomany"]);
console.log(data[key]["fileName"]);
}

Instead of iterating over the data and doing an AJAX call if the conditions are met it might be better to split up the code so you're doing one job at a time.
1) Iterate over the object and produce an array of AJAX promises based on the conditions.
2) Use jQuery's $.when to wait until all the calls have been made and then
3) Update the file list based on the results
const data = {"record-164": {"tomany": true, "fileName": "164"}, "record-165": {"tomany": true, "fileName": "165"}};
function doFetch(filename) {
return $.ajax({ ... });
}
function getPromises(data) {
return Object.keys(data).reduce((acc, obj) => {
const { tomany, fileName } = obj;
if (tomany && filename){
const promise = doFetch(filename);
return acc.concat(promise);
}
return acc;
}, []);
}
$.when.apply(null, getPromises()).then(result => {
updateFilenames(result);
});

Iterate the data object and access tomany field of each object to decide on deletion.
Object.keys(data).forEach(key => {
console.log(key);
if (data[key]["tomany"] == true && data[key]["fileName"] != "") {
var fileName = data[key]["fileName"];
console.log("Going to delete file: " + fileName);
}
});
Here is your modified code. I have commented out the actual API call part to make it executable.
var json = '{ "record-164": { "tomany": true, "fileName": "164" }, "record-165": { "tomany": true, "fileName": "165" } }';
var data = JSON.parse(json);
function doSomething() {
Object.keys(data).forEach(key => {
console.log(key);
if (data[key]["tomany"] == true && data[key]["fileName"] != "") {
var fileName = data[key]["fileName"];
console.log("Going to delete file: " + fileName);
// $.ajax({
// headers: {
// 'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')
// },
// cache: false,
// type: 'POST',
// url: '{{ route("deleteDJS") }}?id=' + fileName + '&type={{ $pageType }}',
// data: { filename: fileName, id: fileName, type: '{{ $pageType }}' },
// success: function (data) {
// console.log("Delete file" + fileName);
// refreshFileList();
// //updatePhotoList();
// },
// error: function (e) {
// console.log(e);
// }
// });
console.log('Limit plików został przekroczony. Możesz dodać maksymalnie: ');
return;
}
});
}
doSomething();

You can do something like this.
var json = {
"record-164": {
"tomany": true,
"fileName": "164"
},
"record-165": {
"tomany": true,
"fileName": "165"
}
}
function cleanJson(data, keys) {
for (let i in data) {
if (keys.includes(i)){
delete data[i];
//Do you file delete here
}else if (typeof data[i] === 'object') cleanJson(data[i], keys)
}
}
cleanJson(json, 'tomany')
console.log(json)

Related

How to cancel pending api call, when dialogBox is closed

I have to upload some files, for each file api is being called. Now if user want to cancel the upload using cancel button in a dialog box.
Please suggest how to reach to this solution.
I am using react and javascript for the file upload.
File upload component is in a different component.
api call is at utils page as shown
_bulkUpload: function(query, rType,sucessCount,failureCount,name) {
Api._callAPI(Url.BULK_UPLOAD, 'POST', query, (type, dt) => {
if(type=="success"){
let data = dt.res_data;
dispatcher.dispatch({
type:'DRAFT_BULK_UPLOAD',
response: sucessCount,
name: name,
});
dispatcher.dispatch({
type:'SNACKBAR',
str: dt.res_str,
toastType:0,
});
/*dispatcher.dispatch({
type:'DRAFT_BULK_UPLOAD',
response: count
});*/
} else {
dispatcher.dispatch({
type:'BULK_FAILED',
response: failureCount,
name: name
});
dispatcher.dispatch({
type: 'SNACKBAR',
str: Api._showErrorMsg(dt.status,dt.responseJSON||'')
});
}
dispatcher.dispatch({
type: 'LOADER',
loader: false
});
}, rType);
},
Api._callAPI function is calling a component as shown.
_callAPI : function(url,method,data,target,cType){
if(data && data.org_id && ([Url.PRELOGIN_CREATE_SUPER_USER,Url.PRELOGIN_CREATE_USER].indexOf(url) !== -1)){
// data.org_id = this._getKey('org_id');
}
else{
if([Url.SSO_CHECK,Url.PRELOGIN_FETCH,Url.LOGIN,Url.PRELOGIN_SEND_OTP,Url.PRELOGIN_VERIFY_OTP,Url.PRELOGIN_VERIFY_EMAIL,Url.COUNTRYCODE_TYPEAHEAD].indexOf(url) === -1)
if(!this._getKey('id') || !this._getKey('value')){
return false;
}
}
$.ajax({
url: BASEURL+url,
method: method,
data: data,
processData: (cType == 'multipart/form-data' ? false :true),
dataType: (cType == 'multipart/form-data' ? '' :'json'),
beforeSend: (xhr) => {
if(this._getKey('id') && this._getKey('value')){
xhr.setRequestHeader('XYZ-ID',this._getKey('id'));
xhr.setRequestHeader('XYZ-VALUE',this._getKey('value'));
if (this._getKey('viewType') == 'Privileged') {
xhr.setRequestHeader('XYZ-HASROLE','Y');
}
else{
xhr.setRequestHeader('XYZ-HASROLE','N');
}
xhr.setRequestHeader('x-csrfvalue',Math.random());
if (this._getKey('delegation_bit') === 'true') {
xhr.setRequestHeader('XYZ-DELEGATOR', this._getKey('delegator_id'));
xhr.setRequestHeader('XYZ-DELEGATION-ID', this._getKey('delegation_id'));
}
}
},
contentType: cType ? false : "application/x-www-form-urlencoded",
success: (data,textStatus, jqXHR) => {
if(jqXHR.getResponseHeader('XYZ-ID')){
this._setKey('id',jqXHR.getResponseHeader('XYZ-ID'));
}
if(jqXHR.getResponseHeader('XYZ-VALUE')){
this._setKey('value',jqXHR.getResponseHeader('XYZ-VALUE'));
}
/*dispatcher.dispatch({
type: 'LOADER',
loader: false
});*/
target('success',data);
},
error: (jqXhr,textStatus,error) => {
dispatcher.dispatch({
type: 'LOADER',
loader: false
});
if(jqXhr.status == 401){
this._clearStorage();
// try {
// sessionStorage.setItem('lastVisitedPage', window.location.hash.split("#")[1].split("?")[0]);
// } catch (ex) {
// console.log("Does not support CRUD with Storage");
// }
this._redirectToLogin();
} else{
target('error',jqXhr,textStatus,error);
}
}
});
},
File Upload and api call part
_handleFileUpload(){
let {failedBillCounter,statusArr} = this.state;
let sucessCount = 0;
let failureCount = 0;
var count=failedBillCounter;
let newFiles = document.getElementById('myFile').files;
let arr = [];
if(newFiles.length > 25){
UserInfoStores.showToast(Errors.MAX_NO_OF_FILE);
document.getElementById('myFile').value = "";
return false;
}
this.setState({fileCount:newFiles.length})
document.getElementById('draftBillBar').style.display = 'block';
//let newData = new FormData();
for(let i=0;i< newFiles.length;i++){
let newData = new FormData();
let files = [];
let txn_attachments = [];
if(newFiles[i].size/(1024*1024) > 15){
count=count+1;
statusArr.push({name:newFiles[i].name,type:'failed'})
this.setState({
statusArr,
failedBillCounter:count,
failCounterFlag:true,
},()=>this.progressBar());
}
else{
newData.append('files-'+i,newFiles[i],newFiles[i].name);
txn_attachments.push('files-'+i);
newData.append('txn_attachments', txn_attachments);
newData.append('source', 'web');
newData.txn_attachments = JSON.stringify(txn_attachments);
DraftAction.draftBulkUpload(newData,'multipart/form-data', sucessCount,failureCount,newFiles[i].name)
}
}
}
you must make a function to cancel the upload make a global variable for your ajaxCall
var ajaxCall;
_callAPI : function(...) {
...
...
ajaxCall = $.ajax({ ... });
}
// make a function to call when user click the cancel upload button
_cancelAjaxCall : function() {
ajaxCall.abort();
}
hope it works...

jQuery Execute function after asynchronous data load

I have created a jQuery function extending its own object $. This function translate those elements attached to the element this:
$.fn.extend({
translate: function(sourceLang, targetLang) {
if($(this).text().trim().length < 1 || !isNaN(parseInt($(this).text().trim())) || sourceLang == targetLang)
return;
let $function = this;
$($function).each(function() {
let $each = this;
$.ajax({
url: 'https://translate.yandex.net/api/v1.5/tr.json/translate',
method: 'GET',
dataType: 'JSONP',
crossDomain: true,
data: {
key: /* my-secret-key */,
text: $($each).text(),
lang: sourceLang + '-' + targetLang
},
success: function(response) {
try {
if(response.code !== 200)
throw "Response: " + response.code;
$($each).text(response.text[0])
} catch(error) {
console.error('Translation error on element: ', $($function).text());
console.error('Message returned by the server:', error);
}
},
error: function(xhr, status, error) {
console.error('Translation error on element: ', $($function).text());
console.error('Message returned by the server:', xhr.responseText);
}
});
});
}
});
After loading the code I do this:
$(document).ready(function() {
let lang = $('html').attr('lang').split('-')[0];
$('td td:visible').translate(lang, "en");
});
Note: the HTML tag looks like this <html lang="es-ES"> depending on the logged user language.
The issue I have is the table loads after a couple of seconds (since we are not in Production environment they could be more than 30). Therefore the previous code block is not useful.
Note: the <tbody> tag is created when the data is added.
What I have tried is:
1. Create a setInterval() and clearInterval() when the $('td:visible').length is greater than 0:
let iv = setInterval(function() {
let lang = $('html').attr('lang').split('-')[0];
let rows = $('tbody td:visible');
if(rows.length > 0) {
rows.translate(lang, "en");
clearInterval(iv);
}
}, 1000);
2. Set a .delay() before the translation:
let isTranslated = false;
while(!isTranslated) {
let lang = $('html').attr('lang').split('-')[0];
let rows = $('tbody td:visible');
if(rows.length > 0) {
rows.delay(1000).translate(lang, "en");
isTranslated = true;
}
}
The memory consumed by the browser is greater than 200MB. I also tried with $('table').on('DOMSubstreeModified', 'tbody', function() {}) but it didn't work.
So, what approach would you recommend to use this translation plugin on this table after it loads its tbody?
Edit 1:
I have changed my code so I perform less API requests, thanks to the recommendation of #lucifer63:
let $function = this;
let collection = [];
let translation = '';
$(this).each(function() {
collection.push($(this).text());
});
let text = collection.join('::');
$.ajax({
url: 'https://translate.yandex.net/api/v1.5/tr.json/translate',
method: 'GET',
dataType: 'JSONP',
crossDomain: true,
data: {
key: /* my-secret-key */,
text: text,
lang: sourceLang + '-' + targetLang
},
success: function(response) {
try {
if(response.code !== 200) {
throw "Response: " + response.code;
}
translation = response.text[0].split('::');
$($function).each(function() {
$(this).text(translation.shift());
});
} catch(error) {
console.error('Message returned by the server:', error);
}
},
error: function(xhr, status, error) {
console.error('Message returned by the server:', xhr.responseText);
}
});
But still, I need to figure out how to print after data has loaded.
Well... I think I found the answer I was seeking:
$('body').on('DOMNodeInserted', 'table', function() {
$('td:visible').translate('es', 'en');
});
It seems it is working correctly.

Parsing an array posted to nodejs server using querystring

I always use querystring to parse data posted by client. But this is the first time I am posting an array, and I'm having same issue.
client side:
$.ajax({
url: 'myurl',
type: "POST",
data: {ids: ["str1","str2","str3"]},
success: function (msg) {
location.reload();
},
error: function (msg) {
alert("ServerError");
},
cache: false,
});
server side:
var body='';
req.on('data', function(chunk) {
body += chunk.toString();
});
req.on('end', function() {
var parsedbody = querystring.parse(body);
console.log(parsedbody);// {'ids[]':["str1","str2","str3"]}
My problem? Well, first note the comment: the key is ids[] intead of simply ids. So strange and annoyng. And the big problem: if I pass an array with one string like this:
data of ajax request--> data: { ids: ["str1"] }
the console.log becomes
console.log(parsedbody);// {'ids[]':"str1"}
console.log(parsedbody['ids[]'].length);// 4 (instead of 1)
As you can see my array become a string and this is a problem.
You could just easily create your own wrapper around querystring.parse(). Example:
var qs = require('querystring');
function parseQS(str) {
var result = qs.parse(str),
keys = Object.keys(result);
for (var i = 0, len = keys.length, key, newKey; i < len; ++i) {
key = keys[i];
if (key.slice(-2) === '[]') {
newKey = key.slice(0, -2);
if (!Array.isArray(result[key]))
result[newKey] = [ result[key] ];
else
result[newKey] = result[key];
delete result[key];
}
}
return result;
}
console.dir(parseQS('foo[]=bar&baz=bla&quux[]=123&quux[]=456'));
// outputs:
// { baz: 'bla',
// foo: [ 'bar' ],
// quux: [ '123', '456' ] }

Jquery Queue requests integration once First Request Success and then call the next request

Is there any way to integration Jquery Queue requests handling Once first request got the Success response then call the next request.
FYI I've used ajaxManager as below code but it is not waiting for previous request success response.
$(function() {
ajaxManager.run();
for (key in Reports) {
var Url = Reports[key];
if ( Url != '' ) {
sendRequest(Url, key);
}
}
});
function sendRequest(Url, act_id) {
ajaxManager.addReq({
async: false,
cache: false,
url: Url,
type: "POST",
data: {},
dataType: "jsonp",
success: function(response) {
console.log(response);
}
});
}
Is there any other way which can handle this.
Thanks.
Here is a simple example of how you can do this (i saved the reports in an array)
var reports = [11, 12, 14, 15];
function doTheReport() {
if (reports.length === 0) {
alert('All reports are done now.');
return;
}
var report_Id = reports.pop();
$.ajax({
url: "/DoTheReport",
complete: function () {
doTheReport();
}
});
};
Utilizing jQuery.queue() , jQuery.dequeue() ,
Try
$(function () {
// requests url and data objects
var Reports = [{
"url": "url1",
"data": JSON.stringify([1])
}, {
"url": "url2",
"data": JSON.stringify([2])
}, {
"url": "url3",
"data": JSON.stringify([3])
}];
// all responses
var responses = [];
// jQuery.deferred , resolved when all requests completed
var requests = new $.Deferred() || $(requests);
// do stuff when all requests completed
requests.done(function (data) {
console.log(data);
alert(data.length + " requests completed");
$.each(data, function (k, v) {
$("#results").append(v + "\n")
})
});
// `request` fn
var request = function (url, data) {
return $.post(url, {
json: data
}, "json")
};
// `response` fn
var response = function (data, textStatus, jqxhr) {
// if response `textStatus` === `success` , do stuff
if (textStatus === "success") {
console.log(data, textStatus);
responses.push([textStatus, data, $.now()]);
// if items in queue , dequeue next item
if ($.queue(requests, "ajax").length) {
$.dequeue(requests, "ajax")
} else {
// if items not in queue , resolve requests
requests.resolve(responses)
}
};
};
// `error` fn
// var error = function() {};
// create queue of `request` functions
$.each(Reports, function (k, v) {
$.queue(requests, "ajax", function () {
return request(v.url, v.data)
.then(response /* , error */ )
})
});
// dequeue first item in queue
$.dequeue(requests, "ajax")
})
jsfiddle http://jsfiddle.net/guest271314/mgqhzejh/

How to trim JSON Object removing whitespace

I hava a common ajax.post method which accepts data from function parameter. Now i want to trim the properties of data. Below is the code.
function PostToServer(options) {
var defaults = {
'url': null,
'data': null,
'onSuccess': null,
'onError': null
};
var parameters = $.extend(defaults, options);
$.ajax({
url: parameters.url,
type: "POST",
data: JSON.stringify(parameters.data),
contentType: "application/json",
success: function (res) {
if ($.isFunction(parameters.onSuccess)) {
parameters.onSuccess(res);
}
},
error: function (xhr, status, error) {
if ($.isFunction(parameters.onError)) {
parameters.onError(xhr, status, error);
}
}
});
}
Now in this function i want to trim the 'parameters.data' object so that it removes whitespace from both ends. but i dont know what comes in 'parameters.data' so i can not access its properties and use trim function.
Please help.
Try this:
$.each(res, function(index) {
var that = this;
$.each(that, function(key, value) {
var newKey = $.trim(key);
if (typeof value === 'string')
{
that[newKey] = $.trim(value);
}
if (newKey !== key) {
delete that[key];
}
});
});

Categories

Resources