JSON Property undefined in JavaScript with p5.js - javascript

I'm just beginning learning to code and this is my first post here so please forgive me if I violate any rules here....
So here is my question, it seems quite simple but I can just not figure out what is the problem. I have a JSON file like this:
{"imgj":
[
{
"id":"1",
"user_id":"1",
"tag":"siteplan",
"imageurl":"images/cb.jpg"
},
{
"id":"2",
"user_id":"2",
"tag":"floorplan",
"imageurl":"images/cbb.jpg"
},
{
"id":"3",
"user_id":"1",
"tag":"section",
"imageurl":"images/postit.png"
},
{
"id":"4",
"user_id":"2",
"tag":"siteplan",
"imageurl":"images/avatar_default.jpg"
}
]
}
and in my .js file, I'm trying to get data of img from the JSON file, but always failed.
p.preload=function(){
var url ='imglist.json';
imglist = p.loadJSON(url);
for(var i=0; i<4; i++) {
imgurl = imglist.imgj[i].imageurl;
img[i]=p.loadImage("imgurl");
}
};
The result of the console is shown as below:
console.log(typeof imglist == 'object'); //return true
console.log(imglist); //return {} imgj:(4)[{...},{...},{...},{...}]
console.log(imglist.imgj[1]); //return undefined
it seems that my JSON file is successfully read as an object, but the property of it cannot be read. It's really weird.

This should work however it's only fetch workaround. I don't know how to access this not own property made by loadJSON.
p.preload= function(){
var url ='imglist.json';
fetch(url)
.then(data=>data.json())
.then(imglist=>{
//imglist = p.loadJSON(url);
console.log(imglist.imgj[0]); // Object { id: "1", user_id: "1", tag: "siteplan", imageurl: "images/cb.jpg" }
for(let i = 0;i< imglist.imgj.length;i++) {
imgurl = imglist.imgj[i].imageurl;
img[i]=p.loadImage(imgurl);
}});
};

After a bunch of fiddling I believe loadJSON is actually asynchronous behind the scenes, so your for-loop continues to execute before the file is done loading.
You could store the imglist in a global/classwide variable and do the for-loop inside the setup or draw function instead.
var imglist;
var imgs;
p.preload = function() {
var url = 'imglist';
imglist = loadJSON(url);
}
p.setup = function() {
imgs = imglist.map(function(imglistitem) {
return loadImage(imglistitem.imageurl);
});
}
I am not quite sure how p5.js is wired behind the scenes, but the example from the reference uses the draw() function to pick apart the json:
https://p5js.org/reference/#/p5/loadJSON

Related

I want to delete multiple CRM records from Dynamics with Xrm.WebApi.online.executeMultiple

Multiple entity records have to be deleted in one call instead of multiple callbacks so trying to use Xrm.WebApi.online.executeMultiple to delete records. but the code written below is not working. Any help will be appreciated.
for (var i=0; i<Checkbox.length; i++)
{
if(Checkbox[i].checked)
{
var id = Checkbox[i].value;// GUID of the record to be deleted
Checkbox[i].checked = false;
DeleteRequests[i]={};
DeleteRequests[i].getMetadata = function(){
return{
boundParameter: undefined,
operationType: 2,
operationName: "Delete",
parameterTypes: {
}
}
}
DeleteRequests[i].etn="cme_entity";
DeleteRequests[i].payload=id;
}
}
window.parent.Xrm.WebApi.online.executeMultiple(DeleteRequests).then(
function (results) {alert("Success");},
function (error) {alert("Failed");});
Getting weird error that this operation could not be processed. Please contact Microsoft.
The issue has to do with how you are constructing the delete request objects. You need to declare a function that sets up the getMetadata function and the required entityReference object.
I've tested the below solution and it works.
var Sdk = window.Sdk || {};
Sdk.DeleteRequest = function (entityReference) {
this.entityReference = entityReference;
this.getMetadata = function () {
return {
boundParameter: null,
parameterTypes: {},
operationType: 2,
operationName: "Delete",
};
};
};
for (var i = 0; i < Checkbox.length; i++) {
if (Checkbox[i].checked) {
var id = Checkbox[i].value;
Checkbox[i].checked = false;
DeleteRequests[i] = new Sdk.DeleteRequest({ entityType: "account", id: id });
}
}
window.parent.Xrm.WebApi.online.executeMultiple(DeleteRequests).then(
function (results) { alert("Success"); },
function (error) { alert("Failed"); });
Unfortunately CRUD operations with Xrm.WebApi.online.execute and Xrm.WebApi.online.executeMultiple are not very well documented. I've written a blog post with some code samples.
The important parts are the declaration of the Sdk.DeleteRequest function as a property on window and instantiating a request object using new Sdk.DeleteRequest(). I experimented a little and determined that just simply creating a request object like you were doing before, even with the right attributes does not work either.
Hope this helps! :)

Adding mongoose object to array in nodejs

I have an array of images as this.
var newImageParams = [
{
image_string: "hello",
_type: "NORMAL"
},
{
image_string: "hello",
_type: "NORMAL"
}
]
I am using mongo db and In nodejs, I am using mongoose, Everything is fine, I Can add data to mongoose table, but after adding each image, I am trying to save the resulting object into an array, Which in console.log is happening and right as well, but when I return that array, there is nothing in it and it empty
if (newImageParams) {
for (var i = newImageParams.length - 1; i >= 0; i--) {
// allImages[i]
var newImage = new Image(Object.assign(newImageParams[i], {bike: bike._id}));
newImage.save(function(err, image){
console.log(image);
allImages.push(image);
console.log(allImages);
});
}
}
This is what I am doing, everything is right and good in console but when I finally return,
res.json({bike: bike, images: allImages });
Images array is totally empty as it was when declared? why this is happening, please help
I bet you send response before your callbacks are done.
The easy and fast fix:
if (newImageParams) {
for (var i = newImageParams.length - 1; i >= 0; i--) {
const image = Object.assign(newImageParams[i], {bike: bike._id});
var newImage = new Image(image);
allImages.push(image);
newImage.save(function(err, image){
console.log(image);
console.log(allImages);
});
}
}
I will add correct approach with async/await, the older versions would use Promise.all or async.parallel:
async function doJob() {
if (newImageParams) {
for (var i = newImageParams.length - 1; i >= 0; i--) {
const image = Object.assign(newImageParams[i], {bike: bike._id});
const newImage = new Image(image);
await newImage.save();
allImages.push(image);
}
}
}
allImages.push(image); -> that line of code is async. It's will go to event queue and your console log will call immediately.
So console.log(allImages); will return empty.
You can read more in here. It will help you in future.

Javascript array shows in console, but i cant access any properties in loops

I really try my damndest not to ask, but i have to at this point before I tear my hair out.
By the time the js interpreter gets to this particular method, I can print it to the console no problem, it is an array of "event" objects. From FireBug I can see it, but when I try to set a loop to do anything with this array its as if it doesn't exist. I am absolutely baffled......
A few things:
I am a newbie, I have tried a for(var index in list) loop, to no avail, I have also tried a regular old for(var i = 0; i < listIn.length; i++), and I also tried to get the size of the local variable by setting var size = listIn.length.
As soon as I try to loop through it I get nothing, but I can access all the objects inside it from the FireBug console no problem. Please help, even just giving me a little hint on where I should be looking would be great.
As for the array itself, I have no problems with getting an array back from PHP in the form of: [{"Event_Id":"9", "Title":"none"}, etc etc ]
Here is my code from my main launcher JavaScript file. I will also post a sample of the JSON data that is returned. I fear that I may be overextending myself by creating a massive object in the first place called content, which is meant to hold properties such as DOM strings, settings, and common methods, but so far everything else is working.
The init() function is called when the body onload is called on the corresponding html page, and during the call to setAllEvents and setEventNavigation I am lost.
And just to add, I am trying to learn JavaScript fundamentals before I ever touch jQuery.
Thanks
var dom, S, M, currentArray, buttonArray, typesArray, topicsArray;
content = {
domElements: {},
settings: {
allContent: {},
urlList: {
allURL: "../PHP/getEventsListView.php",
typesURL: "../PHP/getTypes.php",
topicsURL: "../PHP/getTopics.php"
},
eventObjArray: [],
buttonObjArray: [],
eventTypesArray: [],
eventTopicsArray: []
},
methods: {
allCallBack: function (j) {
S.allContent = JSON.parse(j);
var list = S.allContent;
for (var index in list) {
var event = new Event(list[index]);
S.eventObjArray.push(event);
}
},
topicsCallBack: function(j) {
S.eventTopicsArray = j;
var list = JSON.parse(S.eventTopicsArray);
topicsArray = list;
M.populateTopicsDropDown(list);
},
typesCallBack: function(j) {
S.eventTypesArray = j;
var list = JSON.parse(S.eventTypesArray);
typesArray = list;
M.populateTypesDropDown(list);
},
ajax: function (url, callback) {
getAjax(url, callback);
},
testList: function (listIn) {
// test method
},
setAllEvents: function (listIn) {
// HERE IS THE PROBLEM WITH THIS ARRAY
console.log("shall we?");
for(var index in listIn) {
console.log(listIn[index]);
}
},
getAllEvents: function () {
return currentArray;
},
setAllButtons: function (listIn) {
buttonArray = listIn;
},
getAllButtons: function () {
return buttonArray;
},
setEventNavigation: function(current) {
// SAME ISSUE AS ABOVE
var l = current.length;
//console.log("length " + l);
var counter = 0;
var endIndex = l - 1;
if (current.length < 4) {
switch (l) {
case 2:
var first = current[0];
var second = current[1];
first.setNextEvent(second);
second.setPreviousEvent(first);
break;
case 3:
var first = current[0];
var second = current[1];
var third = current[2];
first.setNextEvent(second);
second.setPreviousEvent(first);
second.setNextEvent(third);
third.setPreviousEvent(second);
break;
default:
break;
}
} else {
// do something
}
},
populateTopicsDropDown: function(listTopics) {
//console.log("inside topics drop");
//console.log(listTopics);
var topicsDropDown = document.getElementById("eventTopicListBox");
for(var index in listTopics) {
var op = document.createElement("option");
op.setAttribute("id", "dd" + index);
op.innerHTML = listTopics[index].Main_Topic;
topicsDropDown.appendChild(op);
}
},
populateTypesDropDown: function(listTypes) {
//console.log("inside types drodown");
//console.log(listTypes);
var typesDropDown = document.getElementById("eventTypeListBox");
for(var index2 in listTypes) {
var op2 = document.createElement("option");
op2.setAttribute("id", "dd2" + index2);
op2.innerHTML = listTypes[index2].Main_Type;
typesDropDown.appendChild(op2);
}
}
},
init: function() {
dom = this.domElements;
S = this.settings;
M = this.methods;
currentArray = S.eventObjArray;
buttonArray = S.buttonObjArray;
topicsArray = S.eventTopicsArray;
typesArray = S.eventTypesArray;
M.ajax(S.urlList.allURL, M.allCallBack);
//var tempList = currentArray;
//console.log("temp array length: " + tempList.length);
M.setAllEvents(currentArray);
M.testList(currentArray);
M.setEventNavigation(currentArray);
//M.setEventNavigation();
M.ajax(S.urlList.topicsURL, M.topicsCallBack);
M.ajax(S.urlList.typesURL, M.typesCallBack);
}
};
The problem you have is that currentArray gets its value asynchronously, which means you are calling setAllEvents too soon. At that moment the allCallBack function has not yet been executed. That happens only after the current running code has completed (until call stack becomes emtpy), and the ajax request triggers the callback.
So you should call setAllEvents and any other code that depends on currentArray only when the Ajax call has completed.
NB: The reason that it works in the console is that by the time you request the value from the console, the ajax call has already returned the response.
Without having looked at the rest of your code, and any other problems that it might have, this solves the issue you have:
init: function() {
dom = this.domElements;
S = this.settings;
M = this.methods;
currentArray = S.eventObjArray;
buttonArray = S.buttonObjArray;
topicsArray = S.eventTopicsArray;
typesArray = S.eventTypesArray;
M.ajax(S.urlList.allURL, function (j) {
// Note that all the rest of the code is moved in this call back
// function, so that it only executes when the Ajax response is
// available:
M.allCallBack(j);
//var tempList = currentArray;
//console.log("temp array length: " + tempList.length);
M.setAllEvents(currentArray);
M.testList(currentArray);
M.setEventNavigation(currentArray);
//M.setEventNavigation();
// Note that you will need to take care with the following asynchronous
// calls as well: their effect is only available when the Ajax
// callback is triggered:
M.ajax(S.urlList.topicsURL, M.topicsCallBack); //
M.ajax(S.urlList.typesURL, M.typesCallBack);
});
}

Values won't to an array with a callback - JavaScript

I have this code:
rtclient.listFiles = function(callback) {
gapi.client.load('drive', 'v2', function() {
gapi.client.drive.files.list({
'maxResults': 20
}).execute(callback);
});
}
which I try to assign to an array using this code:
var arrayStore;
rtclient.listFiles(function(x) {
for(var i in x.items) {
arrayStore.push(x.items[i].id);
}})
However, the array arrayStore is not storing anything. This is using the Google Drive API and I am trying to access some file IDs to iterate over. Can anyone help?
the point is you should have a error like:
TypeError: Cannot call method 'push' of undefined
because you haven't defined it as an array, the other point is don't use for(...in) for arrays, you can find reasons about that in this post:
Why is using “for…in” with array iteration such a bad idea?
var arrayStore = [];
rtclient.listFiles(function(x) {
for(var i = 0; i < x.items.length; i++) {
arrayStore.push(x.items[i].id);
}
});
The other important point as #toothbrush has commented is, since the Google Drive API is asynchronous, you can't access the contents of arrayStore immediately, in other word to continue your scenario you should do something like this:
var arrayStore = [];
rtclient.listFiles(function(x) {
for(var i = 0; i < x.items.length; i++) {
arrayStore.push(x.items[i].id);
}
nextStep();
});
function nextStep(){
//here you would have access to arrayStore
console.log(arrayStore);
}

Paging Through Records Using jQuery

I have a JSON result that contains numerous records. I'd like to show the first one, but have a next button to view the second, and so on. I don't want the page to refresh which is why I'm hoping a combination of JavaScript, jQuery, and even a third party AJAX library can help.
Any suggestions?
Hope this helps:
var noName = {
data: null
,currentIndex : 0
,init: function(data) {
this.data = data;
this.show(this.data.length - 1); // show last
}
,show: function(index) {
var jsonObj = this.data[index];
if(!jsonObj) {
alert("No more data");
return;
}
this.currentIndex = index;
var title = jsonObj.title;
var text = jsonObj.text;
var next = $("<a>").attr("href","#").click(this.nextHandler).text("next");
var previous = $("<a>").attr("href","#").click(this.previousHandler).text("previous");
$("body").html("<h2>"+title+"</h2><p>"+text+"</p>");
$("body").append(previous);
$("body").append(document.createTextNode(" "));
$("body").append(next);
}
,nextHandler: function() {
noName.show(noName.currentIndex + 1);
}
,previousHandler: function() {
noName.show(noName.currentIndex - 1);
}
};
window.onload = function() {
var data = [
{"title": "Hello there", "text": "Some text"},
{"title": "Another title", "text": "Other"}
];
noName.init(data);
};
I use jqgrid for just this purpose. Works like a charm.
http://www.trirand.com/blog/
I would personally load the json data into a global variable and page it that way. Hope you don't mind my assumptions on the context of survey data I think I remember you from yesterday.
var surveyData = "[{prop1: 'value', prop2:'value'},{prop1: 'value', prop2:'value'}]"
$.curPage = 0;
$.fn.loadQuestion = function(question) {
return this.each(function() {
$(this).empty().append(question.prop1);
// other appends for other question elements
});
}
$(document).ready(function() {
$.questions = JSON.parse(surveyData); // from the json2 library json.org
$('.questionDiv').loadQuestion($.questions[0]);
$('.nextButton').click(funciton(e) {
if ($.questions.length >= $.curPage+1)
$('.questionDiv').loadQuestion($.questions[$.curPage++]);
else
$('.questionDiv').empty().append('Finished');
});
});
~ UnTested
I'll have to admit that #sktrdie approach of creating a whole plugin for handling the survey would be nice. IMO this method is really a path of least resistance solution.

Categories

Resources