I have 2 soy.js and lib-dialogs.js files.
I need to make lib-dialogs pass the value of the lineCount variable to soy.js.
I was able to do this with localStorage but because it saves in a cookie it does not update the values correctly.
In lib-dialogs there is a function called BlocklyDialogs.congratulations that calls the necessary data.
FIle:lib-dialogs.js
BlocklyDialogs.congratulations = function() {
// Add the user's code.
if (BlocklyGames.workspace) {
var linesText = document.getElementById('dialogLinesText');
linesText.textContent = '';
// Line produces warning when compiling Puzzle since there is no JavaScript
// generator. But this function is never called in Puzzle, so no matter.
var code = Blockly.JavaScript.workspaceToCode(BlocklyGames.workspace);
code = BlocklyInterface.stripCode(code);
var noComments = code.replace(/\/\/[^\n]*/g, ''); // Inline comments.
noComments = noComments.replace(/\/\*.*\*\//g, ''); /* Block comments. */
noComments = noComments.replace(/[ \t]+\n/g, '\n'); // Trailing spaces.
noComments = noComments.replace(/\n+/g, '\n'); // Blank lines.
noComments = noComments.trim();
var lineCount = noComments.split('\n').length;
var pre = document.getElementById('containerCode');
pre.textContent = code;
if (typeof prettyPrintOne == 'function') {
code = pre.innerHTML;
code = prettyPrintOne(code, 'js');
pre.innerHTML = code;
}
if (lineCount == 1) {
var text = BlocklyGames.getMsg('Games_linesOfCode1');
} else {
var text = BlocklyGames.getMsg('Games_linesOfCode2')
.replace('%1', String(lineCount));
}
linesText.appendChild(document.createTextNode(text));
}
FIle:soy.js
example "var count = BlocklyDialogs.congratulations(lineCount);"
In soy.js I need to receive the values of lineCount. I've already managed to do this using localStorage but I needed to do something more direct.
In testing I verified that the problem is in the lineCount variable because it is not passing a value to any variable even within the file itself.
I created a variable outside the blocklyDialogs.congratulations function and entered a value of 5.
I called the variable in the soy.js file and got it normally.
I need to make the lineCount pass its value.
You can use event driven programming, pub-sub model.
class EventManager {
constructor(...listeners) {
this.listeners = listeners;
}
register(fn) {
const id = this.listeners.push(fn);
return () => {
this.listeners.splice(id - 1, 1);
};
}
emit(data) {
this.listeners.forEach(fn => fn(data));
}
}
const pushEvents = new EventManager();
// JS 1
const unsubscribe1 = pushEvents.register(x => {
console.log("event:", x);
});
pushEvents.register(x => {
console.log("event:", x);
});
// JS 2
pushEvents.emit("Tets data");
//Output
// event: Tets data
// event: Tets data
unsubscribe1();
pushEvents.emit("Tets data2");
//Output
// event: Tets data2
.as-console-row {color: red!important}
Related
This problem is very annoying. So, I am making a scheduled trigger run every 24 hours. It simply gets items from one collection does some data processing then appends information to another collection. The functioning code works even when the function runs. But it will not let me save because there are "runtime" errors? Even though it was executed perfectly and returned.
Console Error
> result (JavaScript):
EJSON.parse('{"$undefined":true}')
I suppose this has something to do with returning. but when I return null I get this:
> result:
null
> result (JavaScript):
EJSON.parse('null')
when trying to save I get this at the top of the page:
runtime error during function validation
Function Code:
exports = async function() {
const usersCol = context.services.get("SchoologyDashCluster").db("SchoologyDashApp").collection("users");
const gradesCol = context.services.get("SchoologyDashCluster").db("SchoologyDashApp").collection("grades");
var usersCusor = await usersCol.find( ).toArray();
var gradesCusor = await gradesCol.find( ).toArray();
let insert = [];
for (let i = 0; i < usersCusor.length; i++) {
var user = usersCusor[i];
var userSavedGrades = gradesCusor[i].grades
var currentGrades = await getGrades(user.schoologyUID, user.consumerKey, user.secretKey);
var lastGraded = NaN;
let index = gradesCusor[i].grades.length - 1;
while (true) {
if (gradesCusor[i].grades[index].changed == 1) {
lastGraded = index;
break
}
index = index - 1;
}
console.log(lastGraded)
if (userSavedGrades[lastGraded].grades.ga == currentGrades.ga){
currentGrades = { changed : 0, time: new Date().getTime()};
} else {
currentGrades = {changed : 1, grades: currentGrades, time : new Date().getTime()};
}
gradesCol.updateOne(
{"user" : user._id},
{"$push" : {"grades" : currentGrades}}
)
}
// return usersCol.find( );
return null;
};
The answer was simple and now I feel ignorant. Instinctual I put the module imports at the top of the document. However this is incorrect and they need to be placed in the exports function, like so:
exports = function (x,y,z) {
const http = context.http;
return;
}
P.S new to js,
I made an ios like calculator in js in which the basic functioning is the user enters the first number which gets stored in a variable , screen gets cleared then the user enters the second number which again needs to be stored in a variable. I am currently having problem in storing the second number.
const getnum = () => {
let firstnum = parseFloat(ans.innerText);
console.log("firstnum" + "=" + firstnum);
};
Copied this from internet to get the second number
operationperf = (operation) => {
if (!numinmem) {
numinmem = parseFloat(ans.textContent);
operatorinmem = operation;
ans.textContent = "";
return;
}
operatorinmem = operation;
ans.textContent = getResultOfOperationAsStr();
ans.textContent = "";
};
but this causes both the variables to have the same value so if i do 50+78 the calculator performs 50+50
working demo: https://megahedron69.github.io/ios-Calculator/
javascript file: https://github.com/Megahedron69/ios-Calculator/blob/main/app.js
First of all, it seems that your numinmem variable is not being used outside the scope of operationperf function for any further processing.
Also, in your following function:
const getResultOfOperationAsStr = () => {
const currentValueNum = parseFloat(ans.textContent);
const valueNumInMemory = parseFloat(ans.textContent);
let newValueNum;
if (operatorinmem === "addition") {
newValueNum = valueNumInMemory + currentValueNum;
} else if (operatorinmem === "subtraction") {
newValueNum = valueNumInMemory - currentValueNum;
} else if (operatorinmem === "multiplication") {
newValueNum = valueNumInMemory * currentValueNum;
} else if (operatorinmem === "division") {
newValueNum = valueNumInMemory / currentValueNum;
}
return newValueNum.toString();
};
It appears that your are using the current value of the element stored in ans variable for both sides of your operations (e.g. ansValueAsFloat + ansValueAsFloat), hence, producing the undesired behavior.
My recommendation would be to set any of the variables involved in the final operation to the value of numinmem and set the other to the current value in ans.
Hope I made myself clear.
I want to write a function in javascript that reads text file and if it contains any javascript function in that text file then instead of reading it just as text, my function will read it as javascript.
Like:
const toBeRead = () => true; //This function is in text file
Above function is in text file and I want to read it as javascript. Currently I am reading this as a string but wanted to take output from it which is true.
Editing for better demonstration. Here is my function after using eval()
function readSingleFile(evt) {
var f = evt.target.files[0];
if (f) {
var r = new FileReader();
r.onload = function (e) {
var contents = e.target.result;
var ct = r.result;
var words = ct.split("\n");
let array = [];
words.map((word) => {
if (word.substring(0, 6) === "const ") {
if (word.includes("=>")) {
if (word.includes("=")) {
alert(word); //It shows const toBeRead=()=>true;
alert(eval(word)); // It shows undefined
array.push(word);
}
}
}
return array;
});
alert(array);
};
r.readAsText(f);
} else {
alert("Failed to load file");
}
}
Actually I am creating a rule for coding convention like if functions return boolean then it should start with "is/has". Like const isFuncTrue=()=>true; Don't have rule defined in Eslint!
Two methods
eval(jsstr) - not recommended
script:
Example in browser - will not run if no DOM
const str = `const toBeRead = () => true; //This function is in text file`
const scr = document.createElement("script")
scr.textContent = str;
document.body.appendChild(scr)
console.log(toBeRead())
I have an issue related to database. I am currently working with Gupshup bot programming. There are two different data persistence modes which can be read here and here. In the advanced data persistence, the following code is documented to put data into data base:
function MessageHandler(context, event) {
if(event.message=='update bug - 1452') {
jiraUpdate(context);
}
}
function jiraUpdate(context){
//connect to Jira and check for latest update and values
if(true){
context.simpledb.doPut("1452" ,"{\"status\":\"QA pending\",\"lastUpdated\":\"06\/05\/2016\",\"userName\":\"John\",\"comment\":\"Dependent on builds team to provide right build\"}");
} else{
context.sendResponse('No new updates');
}
}
function DbPutHandler(context, event) {
context.sendResponse("New update in the bug, type in the bug id to see the update");
}
If I want to change only one of column (say status or last Updated) in the table for the row with key value 1452, I am unable to do that. How can that be done?
I used the following code:
function MessageHandler(context, event) {
// var nlpToken = "xxxxxxxxxxxxxxxxxxxxxxx";//Your API.ai token
// context.sendResponse(JSON.stringify(event));
if(event.message=='deposit') {
context.sendResponse("Enter the amount to be deposited");
}
if(event.message=="1000") {
jiraUpdate(context);
}
if(event.message== "show"){
context.simpledb.doGet("1452");
}
}
function HttpResponseHandler(context, event) {
var dateJson = JSON.parse(event.getresp);
var date = dateJson.date;
context.sendResponse("Today's date is : "+date+":-)");
}
function jiraUpdate(context){
//connect to Jira and check for latest update and values
if(true){
context.simpledb.doPut("aaa" ,"{\"account_number\":\"90400\",\"balance\":\"5800\"}");
} else{
context.sendResponse('No new updates');
}
}
/** Functions declared below are required **/
function EventHandler(context, event) {
if (!context.simpledb.botleveldata.numinstance)
context.simpledb.botleveldata.numinstance = 0;
numinstances = parseInt(context.simpledb.botleveldata.numinstance) + 1;
context.simpledb.botleveldata.numinstance = numinstances;
context.sendResponse("Thanks for adding me. You are:" + numinstances);
}
function DbGetHandler(context, event) {
var bugObj = JSON.parse(event.dbval);
var bal = bugObj.balance;
var acc = bugObj.account_number;
context.sendResponse(bal);
var a = parseInt (bal,10);
var b = a +1000;
var num = b.toString();
context.simpledb.doPut.aaa.balance = num;
}
function DbPutHandler(context, event) {
context.sendResponse("testdbput keyword was last put by:" + event.dbval);
}
Since the hosted DB that is provided by Gupshup is the DynamoDB of AWS. Hence you can enter something as a key, value pair.
Hence you will have to set the right key while using doPut method to store data into the database and use the same key to get the data from the database using the doGet method.
To update the data you should first call doGet method and then update the JSON with right data and then call doPut method to update the database with the latest data.
I have also added something which is not present in the documentation, You can now make DB calls and choose which function the response goes to.
I am refactoring your example as using 3 keywords and hard coding few things just for example -
have - this will update the database with these values
{"account_number":"90400","balance":"5800"}
deposit - on this, the code will add 1000 to the balance
show - on this, the code show the balance to the user.
Code -
function MessageHandler(context, event) {
if(event.message=='have') {
var data = {"account_number":"90400","balance":"5800"};
context.simpledb.doPut(event.sender,JSON.stringify(data),insertData); //using event.sender to keep the key unique
return;
}
if(event.message=="deposit") {
context.simpledb.doGet(event.sender, updateData);
return;
}
if(event.message== "show"){
context.simpledb.doGet(event.sender);
return;
}
}
function insertData(context){
context.sendResponse("I have your data now. To update just say \"deposit\"");
}
function updateData(context,event){
var bugObj = JSON.parse(event.dbval);
var bal = bugObj.balance;
var a = parseInt(bal,10);
var b = a + 1000;
var num = b.toString();
bugObj.balance = num;
context.simpledb.doPut(event.sender,bugObj);
}
function EventHandler(context, event) {
if (!context.simpledb.botleveldata.numinstance)
context.simpledb.botleveldata.numinstance = 0;
numinstances = parseInt(context.simpledb.botleveldata.numinstance) + 1;
context.simpledb.botleveldata.numinstance = numinstances;
context.sendResponse("Thanks for adding me. You are:" + numinstances);
}
function DbGetHandler(context, event) {
var accountObj = JSON.parse(event.dbval);
context.sendResponse(accountObj);
}
function DbPutHandler(context, event) {
context.sendResponse("I have updated your data. Just say \"show\" to view the data.");
}
I'm writing a simple application where I send values to a mqtt broker given by a pot-meter (variable resistor). The thing I am trying to accomplish is that I only send changed values to save bandwidth. I am trying Object.observe, but that does not do anything. Can anybody help me?
My code:
var analogValue = 0;
every((0.5).second(), function() {
analogValue = my.sensor.analogRead();
var values = {values:[{key:'resistance', value: analogValue}]}
//another experiment here
var arr = ['resitance', analogValue];
Array.observe(arr, function(changes) {
console.log(changes);
});
arr[1] = analogValue
console.log('sent ',values,'to ',thingTopic)
client.publish(thingTopic, JSON.stringify(values));
});
var o = [analogValue];
Object.observe(o, function (changes) {
console.log(changes);
//eventually publish only changes to broker here
})
o.name = [analogValue]
You don't need to use Object.observe. You can just save the last measurement and check the new one against it. Like this:
// I'm assuming that any actual measurement will be different than 0
var lastMeasurement = 0;
every((0.5).second(), function() {
var analogValue = my.sensor.analogRead();
if (lastMeasurement !== analogValue) {
// the new value is different
var values = {values:[{key:'resistance', value: analogValue}]};
client.publish(thingTopic, JSON.stringify(values));
// update the last measurement value
lastMeasurement = analogValue;
}
});