Override javascript - javascript

Drawing
when I hit the button on the top left on https://real-one.shifaul.repl.co/, nothing happens except the text changing to "to daily"
but what I want it is when I hit the button , it will change my javascript
the line that is running now (highlighted in blue) will stop working, and the line that is in the comment will start working, when I hit again it gets back to normal. it will go on forever
fetchTexts().then(([enQuotes, bnQuotes]) => {
const totalQuotes = enQuotes.length;
function getQuote() {
const pickedIndex = Math.floor(Math.random() * totalQuotes);
//const now = new Date(); const days = Math.floor(now/1000/60/60/24); const pickedIndex = days % totalQuotes
const newImageIndex = Math.floor(Math.random()*6); document.body.style.backgroundImage = `url(${newImageIndex}.jpg)`;
document.querySelector("#text1").innerText = enQuotes[pickedIndex];
document.querySelector("#text2").innerText = bnQuotes[pickedIndex];
}
getQuote(0);
setInterval(function() {
getQuote()
}, 24 * 60 * 60 * 1000);
});
full code: https://replit.com/join/xedbtvda-shifaul

I think that based on your code, you can do that:
var elem = document.getElementById("myButton1")
const now = new Date();
const days = Math.floor(now/1000/60/60/24);
const pickedIndex = elem.value === 'On refresh'
? Math.floor(Math.random() * totalQuotes)
: days % totalQuotes
This worked for me (I tested by lowering the value of getQuotes interval)

Related

Why can't I change this global variable from function? (JavaScript)

Simple countdown project.
Desired outcome:
global variable determines default time.
then slider value overrides that variable.
PROBLEM: slider value changes locally but global value stays the same.
I've watched tutorials all day on variable scopes and still don't see what's wrong because:
Global is declared with "var" outside function: var initialMinutes = 5
attempt to update value inside function looks like this:
const change = slider.addEventListener('change', setMins)
function setMins() {
initialMinutes = slider.value
}
I have also tried with window.variable here and there to no avail.
I hope someone can help. This is becoming difficult to scope with.
const countdown = document.getElementById('countdown')
const slider = document.getElementById('slider')
const startBtn = document.getElementById('btn-startStop')
const resetBtn = document.getElementById('btn-reset')
// Event Listeners
const change = slider.addEventListener('change', setMins)
const start = startBtn.addEventListener('click', startStop)
const reset = resetBtn.addEventListener('click', resetApp)
// Time
var initialMinutes = 15
countdown.innerHTML = initialMinutes+':00'
const initialDuration = initialMinutes * 60
let time = initialMinutes * 60
let interval = null
let status = 'stopped'
function updateCountdown() {
const minutes = Math.floor(time / 60)
let seconds = time % 60
seconds = seconds < 10 ? '0'+ seconds : seconds
if( time < 1) {
clearInterval(interval)
startBtn.innerHTML = 'START'
status = 'stopped'
countdown.innerHTML = `00:00`
} else {
countdown.innerHTML = `${minutes}:${seconds}`
time--;
}
}
function startStop() {
if(status === 'stopped') {
interval = setInterval(updateCountdown, 50)
startBtn.innerHTML = 'STOP'
status = 'running'
} else {
clearInterval(interval)
startBtn.innerHTML = 'START'
status = 'stopped'
}
}
function setMins() {
initialMinutes = slider.value
countdown.innerHTML = slider.value+':00'
}
function resetApp() {
clearInterval(interval);
document.getElementById('countdown').innerHTML = '00:00'
startBtn.innerHTML = 'START'
status = 'stopped'
}
Codepen link included for clarity:
https://codepen.io/donseverino/pen/YzWBJYV
Got it! It was not a problem of scope but of variable assignment.
updateCountdown() uses time and time = initialMinutes * 60
I thought changing initialMinutes would automatically change its value inside time but it doesn't.
Reassigning time inside the function solves it.
function setMins() {
initialMinutes = slider.value
time = initialMinutes * 60
}

Re-selecting another value and clac but old result displays in JS

I'm studying calc. I'm having problem with re-selecting value and calc.
Here is my whole program
https://jsfiddle.net/diessses/c9ykmsf2/6/
When user select value then press submit. it works perfectly. However when user change such as 'cb_amount' , s_month and 's_year' Then click submit below code part displays OLD result. Other part result works fine. Could you teach me write code please?
// PAY_START_END_MONTH_FMT message
const PAY_START_END_MONTH_FMT = "If loan start Month is :start ,<br> Final loan paying will be :end ";
let s_month = document.getElementById(elementId.s_month).value;
if (s_month) {
let s_year = document.getElementById(elementId.s_year).value;
let date = new Date();
date.setMonth(s_month - 1);
date.setFullYear(s_year);
let startMonth = DateManager.formatDate(date, DateManager.getFormatString().YYYY_MM);
DateManager.addMonth(date, (years * 12) - 1);
let endMonth = DateManager.formatDate(date, DateManager.getFormatString().YYYY_MM);
document.getElementById("pay_start_end_month").innerHTML = PAY_START_END_MONTH_FMT.replace(":start", startMonth).replace(":end", endMonth);
}
// CB_SENTENCE_FMT message
const CB_SENTENCE_FMT = "Combined bonus amount will be :j_actual_cb_ttl. Paying times is :j_cbTimes . mothly paying is :j_monthly_bns_payment";
if (bSecondToLastTtl > 1) {
let j_actual_cb_ttl = ValueUtils.comma(bSecondToLastTtl);
let j_cbTimes = cbTimes;
let j_monthly_bns_payment = ValueUtils.comma(monthly_b);
document.getElementById("j_cb_sentence").innerHTML = CB_SENTENCE_FMT.replace(":j_actual_cb_ttl", j_actual_cb_ttl).replace(":j_cbTimes", j_cbTimes).replace(":j_monthly_bns_payment", j_monthly_bns_payment);
}
There are a lot of variables which you are have declaration as "const". Try changing those to "let". Read about it here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const and https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let. I have forked your code and tried, seems to be updating the data based on the new values.
Forked fiddle https://jsfiddle.net/b5g73x02/. Below is what I changed.
let cbTimes = years * 2; //
let diff = amount - downpayment;
let justDevideCbAmount = cb_amount / cbTimes;
let monthly_b = (Math.floor(justDevideCbAmount / 100) * 100);
let bSecondToLastTtl = monthly_b * cbTimes;
let paymentTimes = years * 12;
let interestMod = 10000 + (interest * 100);
let ttlWInterest = parseInt(((amount - downpayment) * interestMod )/ 10000);
let ttlWInterestNegativeCb = ttlWInterest - bSecondToLastTtl;
let jstDevideMonthly = ttlWInterestNegativeCb / paymentTimes;
let secondToLastMonthlyPayment = (Math.floor(jstDevideMonthly / 100) * 100);
let firstMonthlyPayment = ttlWInterestNegativeCb - (secondToLastMonthlyPayment * (paymentTimes - 1));
let jKinri = (interest / 100).toFixed(5);
let kinriFinal = ValueUtils.comma(parseInt(ttlWInterest - (amount - downpayment)));

Google Apps Scripts: Remove data when dates < today + xx days

I have a Google Sheet with 5 columns and dates of the last check. I want to only keep the entries when the number of days since the last check is > 10 days.
The Sheet: https://docs.google.com/spreadsheets/d/1nD7CXraydrAwOh7q7QFDLveVW76wRNU0ago4h-ORn8U/edit?usp=sharing
function check(){
/** Variables **/
var ss = SpreadsheetApp.getActiveSpreadsheet(); var sh1 = ss.getSheetByName('Data Processing');
/** Remove duplicates **/
var sh1data = sh1.getDataRange().getValues();
var sh1newData = [];
for (var i in sh1data) {
var row = sh1data[i];
var duplicate = false;
for (var j in sh1newData) {
/* DATE */
var today=new Date().valueOf();
var sec=1000; var min=60*sec; var hour=60*min; var day=24*hour; // Do the conversions
var sh1DateChecked = sh1newData[j][4].valueOf();
var diff=today-sh1DateChecked;
var days=Math.floor(diff/day); // Number of Days since the last check
if(row[0] == sh1newData[j][0] && row[1] == sh1newData[j][1] && days < 10)
{ duplicate = true; } }
if (!duplicate) { sh1newData.push(row);
}
}
sh1.clearContents();
sh1.getRange(1, 1, sh1newData.length, sh1newData[0].length).setValues(sh1newData);
}
This solution ignores the code's mention of "duplicates" and focuses on your stated question of removing dates less than 10 days old. However, if you need to remove duplicates as well, it can be easily added.
I propose you put your condition in a function that takes a row of data as input and returns a boolean (true/false) such as
function dateCheckedOlderThan10Days(row) {
return getDays(row[4]) > 10;
}
function getDays(date) {
const sec = 1000;
const min = 60 * sec;
const hour = 60 * min;
const day = 24 * hour;
return Math.floor((new Date() - date)/day);
}
(Note how you can completely extract the getDays function from your main function. That reduces the amount of code you have to think about inside each function definition.)
This function will fit perfectly into Array.prototype.filter, and the naming of the function makes it very clear what you expect to happen.
const dataOlderThan10Days = ss.getSheetByName('Data Processing')
.getDataRange()
.getValues()
.filter(dateCheckedOlderThan10Days);
Here is the checked function refactored into several functions:
Code.js
function check() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const dataSheet = ss.getSheetByName('Data Processing');
const data = dataSheet.getDataRange().getValues();
const dataOlderThan10Days = data
.slice(1) // removes header row; comment out if you don't have a header row
.filter(dateCheckedOlderThan10Days);
dataSheet.clearContents();
//dataOlderThan10Days.unshift(data[0]); // <-- if you want to restore the headers
setData(dataSheet, dataOlderThan10Days);
}
function dateCheckedOlderThan10Days(row) {
return getDays(row[HEADINGS.DATE_CHECKED]) > 10;
}
const HEADINGS = {
FIRST_NAME: 0,
LAST_NAME: 1,
SALARY: 2,
AGE: 3,
DATE_CHECKED: 4
};
function setData(sheet, data) {
sheet.getRange(1, 1, data.length, data[0].length).setValues(data);
}
function getDays(date) {
const sec = 1000;
const min = 60 * sec;
const hour = 60 * min;
const day = 24 * hour;
return Math.floor((new Date() - date)/day);
}

JavaScript: Assigning a variable if variable changed

In JAVASCRIPT:
If I have a variable which value is constantly changing (100+ times a second). How do I 'record' a specific value at a specific point in time?
Added to this, how do I base this point in time off of another variable of which value has changed?
This needs to be strictly in JavaScript. I've looked at the onChange() method, but I'm unsure if I have to use this in conjunction with HTML for it to work. If not, could someone give me an example where this is not the case?
Cheers
I'm not 100% clear on what you're trying to do, but as Ranjith says you can use setTimeout to run arbitrary code at some (approximate) future time.
This example could likely be improved if I had a bit more detail about what you're doing.
If you're in a node environment you might consider using an event emitter to broadcast changes instead of having to have the variable in scope. (This isn't particularly hard to do in a browser either if that's where you are.)
The html/css parts of this are just for displaying the values in the example; not necessary otherwise.
const rand = document.getElementById('rand');
const snapshot = document.getElementById('snapshot');
let volatile = 0;
// update the value every ~100ms
setInterval(() => {
// assign a new random value
volatile = Math.random();
// display it so we can see what's going on
rand.innerText = volatile;
}, 100);
// do whatever you want with the snapshotted value here
const snap = () => snapshot.innerText = volatile;
// grab the value every 2 seconds
setInterval(snap, 2000);
div {
margin: 2rem;
}
<div>
<div id="rand"></div>
<div id="snapshot"></div>
</div>
Ok - well you can poll variable changes ... even though you can use setters...
Lets compare:
Polling:
let previous;
let watched = 0;
let changes = 0;
let snap = () => previous = watched !== previous && ++changes && watched || previous;
let polling = setInterval(snap, 100);
let delta = 1000 * 2
let start = Date.now();
let last = start;
let now;
let dt = 0
while(start + delta > Date.now()){
now = Date.now();
dt += now - last;
last = now;
if(dt > 100){
watched++;
dt = 0;
}
}
document.getElementsByTagName('h1')[0].innerText = (changes === 0 ? 0 : 100 * watched / changes) + "% hit"
if(watched - changes === watched){
throw Error("polling missed 100%");
}
<h1><h1>
emitting:
const dataChangeEvent = new Event("mutate");
const dataAccessEvent = new Event("access");
// set mock context - as it is needed
let ctx = document.createElement('span');
// add watchable variable
add('watched', 0);
//listen for changes
let changes = 0;
ctx.addEventListener('mutate', () => changes++);
let delta = 1000 * 2
let start = Date.now();
let last = start;
let now;
let dt = 0
while(start + delta > Date.now()){
now = Date.now();
dt += now - last;
last = now;
if(dt > 100){
ctx.watched++;
dt = 0;
}
}
document.getElementsByTagName('h1')[0].innerText = (changes === 0 ? 0 : 100 * ctx.watched / changes) + "% hit"
if(ctx.watched - changes === ctx.watched){
throw Error("trigger missed 100%");
}
function add(name, value){
let store = value
Object.defineProperty(ctx, name, {
get(){
ctx.dispatchEvent(dataAccessEvent, store)
return store;
},
set(value){
ctx.dispatchEvent(dataChangeEvent, {
newVal: value,
oldVal: store,
stamp: Date.now()
});
store = value;
}
})
}
<h1></h1>
The usage of a while loop is on purpose.

Vue.js timing calculations are not matching plain JavaScript version

I'm trying to create a 'beats per minute' (BPM) calculator, identical (for now) to the one you can find here. But for some reason, when I use the BPM calculator at that link on a test song, it gets within 1 BPM of the actual value of 85.94 within of 7 keypresses and just gets more accurate from there, ending within 0.05 of the actual BPM, whereas with my (essentially identically-coded) Vue.js version, it starts much higher (182-->126-->110) and goes down from there, but even after 60 keypresses it's still off by ~2 BPM, and after a full song, it was still off by about 0.37 BPM.
Here's the code for the plain-JavaScript version at that link:
var count = 0;
var msecsFirst = 0;
var msecsPrevious = 0;
function ResetCount()
{
count = 0;
document.TAP_DISPLAY.T_AVG.value = "";
document.TAP_DISPLAY.T_TAP.value = "";
document.TAP_DISPLAY.T_RESET.blur();
}
function TapForBPM(e)
{
document.TAP_DISPLAY.T_WAIT.blur();
timeSeconds = new Date;
msecs = timeSeconds.getTime();
if ((msecs - msecsPrevious) > 1000 * document.TAP_DISPLAY.T_WAIT.value)
{
count = 0;
}
if (count == 0)
{
document.TAP_DISPLAY.T_AVG.value = "First Beat";
document.TAP_DISPLAY.T_TAP.value = "First Beat";
msecsFirst = msecs;
count = 1;
}
else
{
bpmAvg = 60000 * count / (msecs - msecsFirst);
document.TAP_DISPLAY.T_AVG.value = Math.round(bpmAvg * 100) / 100;
document.TAP_DISPLAY.T_WHOLE.value = Math.round(bpmAvg);
count++;
document.TAP_DISPLAY.T_TAP.value = count;
}
msecsPrevious = msecs;
return true;
}
document.onkeypress = TapForBPM;
// End -->
And here's my version:
computed: {
tappedOutBpm: function() {
let totalElapsedSeconds = (this.timeOfLastBpmKeypress - this.timeOfFirstBpmKeypress) / 1000.0
let bpm = (this.numberOfTapsForBpm / totalElapsedSeconds) * 60.0
return Math.round(100*bpm)/100;
},
},
methods: {
tapForBPM: function() {
let now = new Date;
now = now.getTime();
// let now = window.performance.now()
if (this.timeOfFirstBpmKeypress === 0 || now - this.timeOfLastBpmKeypress > 5000) {
this.timeOfFirstBpmKeypress = now
this.timeOfLastBpmKeypress = now
this.numberOfTapsForBpm = 1
} else {
this.timeOfLastBpmKeypress = now
this.numberOfTapsForBpm++
}
}
}
I figured it out by stepping through both of our code.
The problem was that I was setting the number of taps to 1 as soon as the user tapped the key the first time, when in reality it's not taps that I want to count, but beats, and the first beat requires not one tap, but two: the start and the end of that beat. So what I should do is rename the variable to numberOfTappedOutBeats and set it to 0 after the first tap rather than 1.

Categories

Resources