I am trying to learn React.
One of the tasks I am trying to do is to convert my existing html/js/css files to React.
My question is:
Is there a simple, universal way to include JavaScript routines into React without changing anything in the JavaScript routine?
I have tried various ways given in various tutorials but am yet to find some method to simple use the routines without any changes.
Specifically, I have tried the following methods:
Using React-script-tag
Using Helmet
JavaScript DOM method.
I personally liked the third method but it gave me an error as follows:
Uncaught SyntaxError: Unexpected token '<' (at newfunction.js:1:1)
The javascript file was named newfunction.js and the script was as follows:
const loveMe = document.querySelector('.loveMe');
const times = document.querySelector('#times');
let clickTime = 0;
let timesClicked = 0;
loveMe.addEventListener('click', (e) => {
if (clickTime === 0) {
clickTime = new Date().getTime();
} else {
if (new Date().getTime() - clickTime < 800) {
createHeart(e);
clickTime = 0;
} else {
clickTime = new Date().getTime();
}
}
});
const createHeart = (e) => {
const heart = document.createElement('i');
heart.classList.add('fas');
heart.classList.add('fa-heart');
const x = e.clientX;
const y = e.clientY;
const leftOffset = e.target.offsetLeft;
const topOffset = e.target.offsetTop;
const xInside = x - leftOffset;
const yInside = y - topOffset;
heart.style.top = `${yInside}px`;
heart.style.left = `${xInside}px`;
loveMe.appendChild(heart);
times.innerHTML = ++timesClicked;
setTimeout(() => heart.remove(), 1000);
};
Would really appreciate some help in getting around this issue.
Many thanks
Related
I am using around 60000 + 10000 Images for creating the training and validation dataset using a generator
( Images used are the MNIST Images of Handwritten Digits in the PNG Format ).
But when I fit the model using them, "Cleanup called" message logs are constantly getting printed.
function* dataGenerator(type) {
const dataRoot = `MNIST/${type}-Data`;
const labels = fs.readdirSync(dataRoot);
for (let _idx = 0; _idx < labels.length; _idx++) {
const label = labels[_idx];
const files = fs.readdirSync(`${dataRoot}/${label}`);
for (let idx = 0; idx < files.length; idx++) {
const img = fs.readFileSync(`${dataRoot}/${label}/${files[idx]}`);
const imageTensor = tf.node.decodePng(img, 1);
const oneHotArr = new Array(labels.length).fill(0);
oneHotArr[label] = 1;
const oneHotTensor = tf.tensor1d(oneHotArr);
yield { xs: imageTensor, ys: oneHotTensor };
};
};
}
const trainingDataset = tf.data.generator(() => dataGenerator("Training"))
.shuffle(100)
.batch(100);
const validationDataset = tf.data.generator(() => dataGenerator("Validation"))
.shuffle(100)
.batch(100);
// Fitting the model
await model.fitDataset(trainingDataset, {
epochs: 5,
validationData: validationDataset
});
What am I doing wrong ?
nothing. message is info-only and comes from underlying tensorflow c library (where it was introduced at the wrong message level) used by tfjs-node.
planned upgrade of shared library from 2.7.3 to 2.9.1 will take care of that - it should be part of tfjs 3.21 once its released.
I have a Vue 2 serverless web application which uses OpenLayers. I ran into an interesting programming issue that applies to other applications as well where I need to execute 3 methods in sequence many times.
for(let i = 0 ; i < this.dateArraySurface10.length - 1 ; i++)
{
waterfall([
this.setTimeSurface10(),
this.map.renderSync(),
this.myCallback(),
],
function(err){
console.log("Waterfall done",err);
});
}
This is my attempt to call the three functions which do the following three things
this.setTiimeSurface10() : updates the TIME parameter of the ImageWMS source layer already added to the map.
this.map.renderSync() : is a OpenLayers method called on the global map object to ensure all layers are rendered.
this.myCallback() : is a function that extracts the map canvas and adds it to a GIF object as a frame.
My problem is I need those three methods to run in that sequence 72 times and although I can hardcode them with setTimeout I need a more abstract way of doing this so I can allow users to add many layers and export to GIF no matter what. I have tried to add an event listener on the this.map object but something is not working properly.
Programmatically how would one ensure all three methods are excuted in sequence inside the for loop in the most pure Javascript way?
In case it helps here are the two methods :
setTimeSurface10: function () {
if (this.currentTimeSurface10 === null) {
this.currentTimeSurface10 = this.startTimeSurface10;
} else if (this.currentTimeSurface10 >= this.endTimeSurface10) {
this.currentTimeSurface10 = this.startTimeSurface10;
} else {
this.currentTimeSurface10 = new Date(
this.currentTimeSurface10.setMinutes(this.currentTimeSurface10.getMinutes() + 60)
);
}
this.surface10.getSource().updateParams({ TIME: this.currentTimeSurface10.toISOString().split(".")[0] + "Z" });
},
myCallback: function () {
const mapCanvas = document.createElement('canvas');
const divElement = document.querySelector(".map");
mapCanvas.width = divElement.offsetWidth;//size[0];
mapCanvas.height = divElement.offsetHeight;//size[1];
const mapContext = mapCanvas.getContext('2d');
Array.prototype.forEach.call(
document.querySelectorAll('.ol-layer canvas'),
function (canvas) {
if (canvas.width > 0) {
const opacity = canvas.parentNode.style.opacity;
mapContext.globalAlpha = opacity === '' ? 1 : Number(opacity);
const transform = canvas.style.transform;
const matrix = transform
.match(/^matrix\(([^\(]*)\)$/)[1] //eslint-disable-line
.split(',')
.map(Number);
CanvasRenderingContext2D.prototype.setTransform.apply(mapContext,matrix);
mapContext.drawImage(canvas, 0, 0);
}
}
);
this.gif.addFrame(mapCanvas, {copy:true, delay: 200});
}
Answered at my other question but here is the answer again.
Thanks to some help from Mr. Hocevar at OpenLayers (whom I suggest you support if you can on Github Sponsor) I got an answer for anyone interested.
async mapToCanvasList() {
for(let i = 0 ; i < this.dateArraySurface10.length - 1 ; i++)
{
this.setTimeSurface10();
await new Promise(resolve => this.map.once('rendercomplete', resolve));
this.myCallback();
}
this.gif.on('finished', function(blob) {
window.open(URL.createObjectURL(blob));
});
this.gif.render();
},
myCallback: function () {
const mapCanvas = document.createElement('canvas');
const divElement = document.querySelector(".map");
mapCanvas.width = divElement.offsetWidth;//size[0];
mapCanvas.height = divElement.offsetHeight;//size[1];
const mapContext = mapCanvas.getContext('2d');
Array.prototype.forEach.call(
document.querySelectorAll('.ol-layer canvas'),
function (canvas) {
if (canvas.width > 0) {
const opacity = canvas.parentNode.style.opacity;
mapContext.globalAlpha = opacity === '' ? 1 : Number(opacity);
const transform = canvas.style.transform;
const matrix = transform
.match(/^matrix\(([^\(]*)\)$/)[1] //eslint-disable-line
.split(',')
.map(Number);
CanvasRenderingContext2D.prototype.setTransform.apply(mapContext,matrix);
mapContext.drawImage(canvas, 0, 0);
}
}
);
this.gif.addFrame(mapCanvas, {copy:true, delay: 200});
}
As you can see rendering the entire method asynchronous and adding an await promise for the rendercomplete event ensures that the loop waits and executes myCallback which adds the rendered context as a frame to the GIF object.
I'm trying to create a data generator, which I verified was working by itself in pure js. TFJS documentation for it is here, with two examples:
https://js.tensorflow.org/api/latest/#data.generator
I'd like to use a tf.data.generator as this datasets requires elaborate preprocessing. A minimal example is as follows:
const tf = require('#tensorflow/tfjs-node');
class dataGeneratorGenerator {
constructor(test) {
this.test = test
}
* dataGenerator() {
let len = this.test.length
let idx = 0
while (idx < len) {
idx++
console.log(idx)
yield this.test[idx]
}
}
}
let dgg = new dataGeneratorGenerator(['hi', 'hi2', 'hi3'])
let trainDs = tf.data.generator(dgg.dataGenerator);
trainDs.forEachAsync(e => console.log(e));
The error is as follows:
TypeError: Error thrown while iterating through a dataset: Cannot read property 'test' of undefined
Iterating through our datagenerator in pure javascript works:
let dgg = new dataGeneratorGenerator(['hi', 'hi2', 'hi3'])
let dg = dgg.dataGenerator()
console.log(dgg.next())
console.log(dgg.next())
console.log(dgg.next())
My understanding is that we are only passing dataGenerator into tf.data.generator instead of the entire class. Then, how is it possible to input variables into tf.data.generator? Thanks.
One can simply use an arrow function.
const tf = require('#tensorflow/tfjs-node');
function* dataGenerator(test) {
let len = test.length
let idx = 0
while (idx < len) {
idx++
console.log(idx)
}
}
let trainDs = tf.data.generator(() => dataGenerator(['hi', 'hi2', 'hi3']));
trainDs.forEachAsync(e => console.log(e));
I can't find out what is going wrong in my code. Thank you.
I have attached the link to code via codepen.
https://codepen.io/tenzin12/pen/rNmmPbv
`const confirmBtn = document.querySelector(".confirm");
const tipField = document.querySelector(".p1");
const totalField = document.querySelector(".p2");
const tipPercentage = document.querySelector("#tip").children;
const customTip = document.querySelector(".custom").value;
const inputAmt = document.querySelector("#amount").value;
const totalPerson = document.querySelector(".number_of_people").value;
const calcFunction = (bill, percent, diners) => {
const percentage = percent / 100;
const tipPerPerson = (bill * percentage) / diners;
const finalBillPerPerson = bill / diners;
const finalWithTip = finalBillPerPerson + tipPerPerson;
tipField.textContent = tipPerPerson;
totalField.textContent = finalWithTip;
};
for (let i = 0; i < tipPercentage.length; i++) {
tipPercentage[i].addEventListener("click", () => {
if (parseInt(totalPerson) > 0) {
if (tipPercentage[i].value.toUpperCase() === "CUSTOM") {
calcFunction(parseFloat(inputAmt), parseInt(customTip), parseInt(totalPerson));
}
}
calcFunction(parseFloat(inputAmt), parseInt(tipPercentage[i].value), parseInt(totalPerson));
});
}
`
When you need to run calculations on element values, you need to collect those values at the time of calculation. You were collecting them up front - but then when you were calculating the function, it was using those old values. I moved those into your function. Note how I got rid of most of the parseInt and parseFloat functions in favor of the minimal + operator which does the same thing.
Additionally, I simplified the code a little and put in a validation to prevent totals being run on 0 people or 0 amounts. Finally, I changed your for loop into an HTMLCollection forEach loop. I find it is easier to read and maintain
const confirmBtn = document.querySelector(".confirm");
const tipField = document.querySelector(".p1");
const totalField = document.querySelector(".p2");
const tipPercButtons = document.querySelectorAll("#tip input.percentage");
const calcFunction = (bill, percent, diners) => {
const percentage = percent / 100;
const tipPerPerson = (bill * percentage) / diners;
const finalBillPerPerson = bill / diners;
const finalWithTip = finalBillPerPerson + tipPerPerson;
tipField.textContent = tipPerPerson;
totalField.textContent = finalWithTip;
};
tipPercButtons.forEach((el) =>
el.addEventListener("click", (e) => {
const customTip = +document.querySelector(".custom").value;
const inputAmt = +document.querySelector("#amount").value;
const totalPerson = +document.querySelector(".number_of_people").value;
if (isNaN(totalPerson) || isNaN(inputAmt)) {
alert("Please designate the number of people and the amount of the bill")
return;
}
if (totalPerson === 0) return;
let val
if (e.target.value.toUpperCase() === "CUSTOM") val = customTip;
else val = parseInt(e.target.value);
calcFunction(inputAmt, val, totalPerson);
})
);
Updated pen: https://codepen.io/john-tyner/pen/MWmmLMQ?editors=1111
i analysed your code there is some error in fetching the input value in the code.
below is the correct code. Hope this might work
make the following little changes in your code:
const inputAmt = document.querySelector("#amount");
const totalPerson = document.querySelector(".number_of_people");
and this at the bottom outside the if block
calcFunction(
parseFloat(inputAmt.value),
parseInt(tipPercentage[i].value),
parseInt(totalPerson.value)
);
overall your calculator is So interesting.
I'm trying to make bomberman using vanilla JS, for my examination project.
I am a little stuck right now with how to take out the bombs in the array and push them into the array again after they explode.
They need to explode after 2 seconds.
My code for bombs:
function bombPlayerOne() {
let ss = new createjs.SpriteSheet(game.q.getResult('bomb'))
let temp = new createjs.Sprite(ss, "bombIt");
temp.x = playerOne.x;
temp.y = playerOne.y;
game.stage.addChild(temp);
powerUps.bombs.push(temp);
console.log("player one placed a bomb");
for (var i = powerUps.bombs.length - 1; i > 0; i--) {
powerUps.bombs.splice;
// TODO : tween bomber ud...
powerUps.bombs.push;
}
}
function bombPlayerTwo() {
let ss = new createjs.SpriteSheet(game.q.getResult('bomb'))
let temp = new createjs.Sprite(ss, "bombIt");
temp.x = playerTwo.x;
temp.y = playerTwo.y;
game.stage.addChild(temp);
powerUps.bombs.push(temp);
console.log("player two placed a bomb");
for (var i = powerUps.bombs.length - 1; i > 0; i--) {
powerUps.bombs.splice;
// TODO : tween bomber ud...
powerUps.bombs.push;
}
}
So you have a few options, and FYI this isn't necessarily a javascript question so much as how do you handle game logic/code design type of question.
1) A bomb when placed contains a reference back to it's owner. ie
bomb.owner = playerOne
2) You have a manager that controls the state of a level, which keeps track of bombs
LevelManager.player1Bombs = ....
3) You have an array of bombs placed belonging to each player, which you then update during your logic update calls.
function gameUpdate(long milliSecondsSinceLastFrame){
for(bomb in playerOne.placedBombs){
if(bomb.isExploded){
//do other cleanup
playerOne.availableBombs ++;
}
}
//... do same for player 2 etc
}
All of them have their own advantages/disadvantages.