Appending to each element with a specific class - javascript

I have a jQuery script shown bellow. It is suppose to get AWS ML prediction and compare the score and depending upon the score append to a cell in a table the correct prediction. All these cells have the same class prediction. When the button is clicked and this script is triggered, it does everything correctly but when it gets to the appending part it throwing an error saying Cannot read property 'append' of undefined.
When i run the same script inside chrome console it appends correctly to the correct places. I am not really sure why this is happening.
$(document).ready(function(){
var highPred="";
$("#predict").click(function(){
var predictionTables = $(".prediction");
for (var i = 0; i < 4; i++) {
var predictedScoresAWS=[];
var params = {
Record: myData[i]
};
machinelearning.predict(params, function(err, data) {
if (err){
console.log(err, err.stack); // an error occurred
} else{
console.log(data); // successful response
// data = $.parseJSON(data);
predictedScoresAWS.push(data.Prediction.predictedScores['Reduce purge history day count']);
predictedScoresAWS.push(data.Prediction.predictedScores['Increase the java heap space']);
predictedScoresAWS.push(data.Prediction.predictedScores['Successful run']);
predictedScoresAWS.push(data.Prediction.predictedScores['Other error']);
console.log(predictedScoresAWS)
var highPredIndex = predictedScoresAWS.indexOf(Math.max(...predictedScoresAWS))
switch(highPredIndex){
case 0:
highPred='Reduce purge history day count';
break;
case 1:
highPred='Increase the java heap space';
break;
case 2:
highPred='Successful run';
break;
case 3:
highPred='Other error';
}
console.log(highPred);
console.log(predictionTables);
console.log(predictionTables[i])
while (predictedScoresAWS.length) { predictedScoresAWS.pop(); }
predictionTables[i.].append(highPred);
}
});
}
});
});

When you use a subscript with a jQuery collection it returns the DOM object, not a jQuery object. You should use .eq() to get the jQuery object, and then you can call the jQuery append() method.
predictionTables[i].append(highPred);
should be:
predictionTables.eq(i).append(highPred);
Another problem is that you're trying to use the iteration variable i in an asynchronous callback. See JavaScript closure inside loops – simple practical example and Javascript infamous Loop issue? for the problem with this and many solutions. If you can use ES6, just change var i = 0 to let i = 0.

Related

Check if variable exist or not

I'm using API Jira
I'm doing some functions but before to use function, I need to verified if a value exist or not
If he exists so I can launch functions else do nothing.
I'm doing this :
// Call the file functions.js
var functions = require('./functions.js')
/*
Function getAllIssueForSCII displays all the issues in the form of a JSON and that browses all the keys that are in the SCII project
Function pushInitialization initializes the computer score card to 80 on Jira
*/
functions.getAllIssueForSCII().then(function(json){
for (let i=0; i<json.issues.length;i++){
if(json.issues[i].fields.customfield_14038 = null){ // i'm doing this
console.log(json.issues[i].key);
functions.pushInitialization(json.issues[i].key);
}
}
});
/*
A delay is added so that Jira can correctly recover the value 80.
Thanks to this value, we can do all the calculation (Function calculate)
Function pushComputerScoreCard push the final value into the computer score card.
Function generateJSON generates a JSON.
Function replaceCharacter solve the problem of array inside the JSON
*/
setTimeout(function() {
functions.getAllIssueForSCII().then(function(json){
for (let i=0; i<json.issues.length;i++){
functions.calculate(json.issues[i]);
functions.pushComputerScoreCard(json.issues[i].key);
functions.generateJSON(json.issues[i].key);
functions.replaceCharacter();
}
});
}, 1000)
My problem: After the settimeout, he recover value already exist and do the calcul...
I need to verified my condition in all of the script .
Thanks for your help
You are assigning null value in an if condition:
if(json.issues[i].fields.customfield_14038 = null){ // i'm doing this
You need to compare values:
if(json.issues[i].fields.customfield_14038 === null){ // You need to do this:

p5.js sound: How to remove individual cues with removeCue()

The p5.js sound library documentation says that removeCue() can be used to cancel cued events. It says it takes an ID input that is returned from addCue().
When I invoke addCue and store the result to a variable it does not return an ID. It returns NaN.
The image below is a code example I wrote using the p5.js code editor.
How do I get the id ?
OK, i found the issue.
Its an issue with the library https://github.com/processing/p5.js/blob/master/lib/addons/p5.sound.js
look at this link https://github.com/processing/p5.js/blob/master/lib/addons/p5.sound.js#L2178
its using var id = this._cueIDCounter++; but _cueIDCounter was never defined.
so i tried to define it like the following for your code:
Object.defineProperty(mySound,'_cueIDCounter',{value:1,writable:true});
now it returned the id.
so then i tried to remove the cue with removeCue but to my surprise there is also an issue which is getting error Uncaught TypeError: Cannot read property 'splice' of undefined
so then i looked again at the library code and i realised on the following line https://github.com/processing/p5.js/blob/master/lib/addons/p5.sound.js#L2198 within the removeCue function there is an error the current code is
p5.SoundFile.prototype.removeCue = function (id) {
var cueLength = this._cues.length;
for (var i = 0; i < cueLength; i++) {
var cue = this._cues[i];
if (cue.id === id) {
this.cues.splice(i, 1);
}
}
if (this._cues.length === 0) {
}
};
but it should be using this._cues.splice(i, 1); instead of this.cues.splice(i, 1);

MongoDB JavaScript Yield large set of results

I'm trying to query a large set of results from a MongoDB over Python. I do this via JavaScript, because I want to get something like the grandchildren in a tree-like structure. My code looks like the following:
col = db.getCollection(...)
var res = new Array();
col.find( { "type" : ["example"] } ).forEach(
function(entry)
{
v1 = col.find( {"_id" : entry["..."]} )
... (walk through the structure) ...
vn = ...
res.push([v1["_id"], vn["data"]]);
}
);
return res;
Now, I'm having the problem, that the resulting array becomes very (too) large and the memory gets exceeded. Is there a way, to yield the results instead of pushing them into an array?
Alright, I think I know, what you mean. I created a structure like the following:
var bulksize = 1000;
var col = db.getCollection("..");
var queryRes = col.find( { ... } )
process = function(entity) { ... }
nextEntries = function()
{
var res = new Array();
for(var i=0; i<bulksize; i++)
{
if(hasNext())
res.push(process(queryRes.next()));
else
break;
}
return res;
}
hasNext = function()
{
return queryRes.hasNext();
}
The script separates the results into bulks of 1000 entries. And from Python side eval the noted script and then I do the following:
while database.eval('hasNext()'):
print "test"
for res in database.eval('return nextEntries()'):
doSth(res)
The interesting thing is, that the console always says:
test
test
test
test
test
test
Then I get the error:
pymongo.errors.OperationFailure: command SON([('$eval', Code('return nextEntries()', {})), ('args', ())]) failed: invoke failed: JS Error: ReferenceError: nextEntries is not defined nofile_a:0
This means, that the first calls of nextEntries() work, but then the function is not there, anymore. Could it be, that MongoDB does something like a clearing of the JavaScript cache? The problem does not depend on the bulksize (tested with 10, 100, 1000, 10000 and always the same result).
Alright, I found a line in the source code of MongoDB, which clears all JavaScripts that are used more than 10 times. So if no changes on the database server are wanted, it is necessary to query the database multiple times and send bulks to the client by selecting amounts of items with help of the skip() and limit() functions. This works surprisingly fast. Thanks for your help.

Why is this javascript object property undefined?

I am using an approach described in detail at Dictionary Lookups in Javascript (see the section"A Client-Side Solution") to create an object that contains a property for each word in the scrabble dictionary.
var dict = {};
//ajax call to read dictionary.txt file
$.get("dictionary.txt", parseResults);
function parseResults(txt) {
var words = txt.split( "\n");
for (var i=0; i < words.length; i++){
dict[ words[i] ] = true;
}
console.log(dict.AAH);
console.log(dict);
if (dict.AAH == true) {
console.log('dict.AAH is true!');
}
}
(updated code to use an earlier answer from Phil)
I can't figure out why dict.AAH is returning undefined, but the dict object looks fine in the console. Screenshots from Firebug below.
Console:
Drilled down into "Object { }"
How can I check a given word ("AAH", in this case) and have it return true if it is a property in the dict object defined as true?
Live example
Code on Github
The problem isn't your code. You have invisible characters in your words, which you fail to clean up.
You can verify this by using this as your results parser
function parseResults(txt) {
// clean the words when we split the txt
var words = txt.split("\n")
.map($.trim)
.splice(0,3); // Keep only 3 first ones
if(btoa(words[2]) !== btoa('AAH')){ // Compare in Base64
console.log('YOU HAVE HIDDEN CHARS!');
}
}
And you can fix it by whitelisting your characters.
function parseResults(txt) {
// clean the words when we split the txt
var words = txt.split("\n").map(function(el){
return el.match(/[a-zA-Z0-9]/g).join('');
});
for (var i=0; i < words.length; i++){
dict[ words[i] ] = true;
}
console.log(dict.AAH);
console.log(dict);
if (dict.AAH == true) {
console.log('dict.AAH is true!');
}
}
I would recommend cleaning it up on the server side since running regex on every element in an array as large as seen in your live site might cause performance issues.
It's probably a race condition. You're loading the dictionary in a GET and then immediately (while the request is being made) those console.log commands are being called (and the one comes back undefined). Then the data is actually loaded by the time you debug. Everything should be done in a callback or deferred. It's an understandable quirk of debuggers that's caught me up before.
Get ajax requests are asynchronous. This means that while the whole operation that occurs in the ajax request is going, javascript keeps reading the next lines.
The problem then is you are logging values that the ajax request did not manage to retrieve early enough.
To get around the issue you can include the log calls inside your ajax request callback as below
var dict = {};
//ajax call to read dictionary.txt file
$.get("dictionary.txt", function( txt ){
var words = txt.split( "\n");
for (var i=0; i < words.length; i++){
dict[ words[i] ] = true;
}
//Now inside these console.log will run once you DO have the data
console.log(dict.AAH);
console.log(dict);
});
//Stuff out here will run whether or not asynchronous request has finished
I WOULD RECOMMEND USING THE WHEN METHOD IN JQUERY FOR THIS TYPE OF SCENARIOS EVEN MORE AS THE BEST SOLUTION
HERE IS HOW WHAT I THINK WOULD BE MOST PROPER FOR COMPLEX PROJECTS
var dict = {};
//ajax call to read dictionary.txt file
function getDictionary(){
return $.ajax("dictionary.txt");
}
/*I recommend this technique because this will allow you to easily extend your
code to maybe way for more than one ajax request in the future. You can stack
as many asynchronous operations as you want inside the when statement*/
$.when(getDictionary()).then(function(txt){//Added txt here...forgot callback param before
var words = txt.split( "\n");
for (var i=0; i < words.length; i++){
dict[ words[i] ] = true;
}
//Now inside these console.log will run once you DO have the data
console.log(dict.AAH);
console.log(dict);
});
You're trying to output dict before it has been populated by the $.get success handler.
Try this:
// If the browser doesn't have String.trim() available, add it...
if (!String.prototype.trim) {
String.prototype.trim=function(){return this.replace(/^\s\s*/, '').replace(/\s\s*$/, '');};
String.prototype.ltrim=function(){return this.replace(/^\s+/,'');};
String.prototype.rtrim=function(){return this.replace(/\s+$/,'');};
String.prototype.fulltrim=function(){return this.replace(/(?:(?:^|\n)\s+|\s+(?:$|\n))/g,'').replace(/\s+/g,' ');};
}
/**
* Parses the response returned by the AJAX call
*
* Response parsing logic must be executed only after the
* response has been received. To do so, we have to encapsulate
* it in a function and use it as a onSuccess callback when we
* place our AJAX call.
**/
function parseResults(txt) {
// clean the words when we split the txt
var words = txt.split("\n").map($.trim);
for (var i=0; i < words.length; i++){
dict[ words[i] ] = true;
}
console.log(dict.AAH);
console.log(dict);
if (dict.AAH == true) {
console.log('dict.AAH is true!');
}
}
// global object containing retrieved words.
var dict = {};
//ajax call to read dictionary.txt file
$.get("dictionary.txt", parseResults);
As another user commented, jQuery's $.when lets you chain such code.
By the way, if all you want to do is know if a word is in the results you can do:
function parseResults(txt) {
// clean the words when we split the txt
var words = txt.split("\n").map($.trim);
if ($.inArray('AAH', words)) {
console.log('AAH is in the result set');
}
}
I think the problem lays in that you have dict defined as an object but use it as an array.
Replace var dict = {} by var dict = new Array() and your code should work (tried with your live example on Google Chrome).

Javascript Variable Sometimes Undefined

I know this question has been asked several times, but I couldn't seem to find a solution that worked for me in any of the previous questions. I have a variable that gets set when my HTML page is done loading, but sometimes when my code tries to access that variable, it says that it is undefined. I'm not sure why, since I believe I am waiting for everything to load properly. This exception seems to happen randomly, as most of the time all the code runs fine. Here's a simplified version of my code:
var globalVar;
function initStuff(filePath) {
// I wait till the HTML page is fully loaded before doing anything
$(document).ready(function(){
var video = document.getElementById("videoElementID");
// My parseFile() function seems to run smoothly
var arrayOfStuff = parseFile(filePath);
if (arrayOfStuff == null) {
console.error("Unable to properly parse the file.");
} else {
setGlobalVariable(arrayOfStuff);
video.addEventListener("play", updateVideoFrame, false);
}
});
}
function setGlobalVariable(arrayOfStuff) {
window.globalVar = arrayOfStuff;
}
function updateVideoFrame() {
// A bunch of other code happens first
// This is the line that fails occasionally, saying
// "window.globalVar[0].aProperty.anArray[0] is undefined"
var test = window.globalVar[0].aProperty.anArray[0].aProperty;
}
The only thing that I can think of that might be causing this problem is some sort of synchronicity issue. I don't see why that would be the case, though. Help please!
Edit:
In case the asynchronicity issue is coming from my parseFile(xmlFile) method, here is what I'm doing there. I thought it couldn't possibly be causing the issue, since I force the method to happen synchronously, but in case I'm wrong, here it is:
function parseKML(xmlFile) {
var arrayOfStuff = new Array();
// Turn the AJAX asynchronicity off for the following GET command
$.ajaxSetup( { async : false } );
// Open the XML file
$.get(xmlFile, {}, function(xml) {
var doc = $("Document", xml);
// Code for parsing the XML file is here
// arrayOfStuff() gets populated here
});
// Once I'm done processing the XML file, I turn asynchronicity back on, since that is AJAX's default state
$.ajaxSetup( { async : true } );
return arrayOfStuff;
}
The first thing you should do in your code is figure out which part of:
window.globalVar[0].aProperty.anArray[0]
is undefined.
Since you have multiple chained property references and array references, it could be many different places in the chain. I'd suggest either set a breakpoint right before your reference it examine what's in it or use several console.log() statement sto output each nested piece of the structure in order to find out where your problem is.
console.log("globalVar = " + globalVar);
console.log("globalVar[0] = " + globalVar[0]);
console.log("globalVar[0].aProperty = " + globalVar[0].aProperty);
console.log("globalVar[0].aProperty.anArray = " + globalVar[0].aProperty.anArray);
console.log("globalVar[0].aProperty.anArray[0] = " + globalVar[0].aProperty.anArray[0]);
If the problem is that globalVar isn't yet set, then you have a timing problem or an initialization problem.
If the problem is that one of the other properties isn't set, then you aren't initializing globalVar with what you think you are.
You may also want to write your code more defensibly so it fails gracefully if some of your data isn't set properly.
You need to use defensive programming.
http://www.javascriptref.com/pdf/ch23_ed2.pdf
Example:
var video = document.getElementById("videoElementID") || 0;
-
if( video && video.addEventListener ){
video.addEventListener("play", updateVideoFrame, false);
}
Here's another version of your code.
window.globalVar = globalVar || [];
function setGlobalVariable(arrayOfStuff) {
window.globalVar = arrayOfStuff;
}
function updateVideoFrame() {
// A bunch of other code happens first
// This is the line that fails occasionally, saying
// "window.globalVar[0].aProperty.anArray[0] is undefined"
if( window.globalVar ){
var g = window.globalVar || [];
var d = (g[0] || {})["aProperty"];
// etc...
}else{
console.error( "test error." );
}
}
function initStuff(filePath) {
// I wait till the HTML page is fully loaded before doing anything
$(document).ready(function () {
var video = $("#videoElementID");
// My parseFile() function seems to run smoothly
var arrayOfStuff = parseFile(filePath) || [];
if (arrayOfStuff == null || video == null ) {
console.error("Unable to properly parse the file.");
} else {
setGlobalVariable(arrayOfStuff);
video.bind("play", updateVideoFrame);
}
});
}

Categories

Resources