problem on check who button clicked in google script for telegram bot

problem on check who button clicked in google script for telegram bot

Hello
I have tested many codes all over the internet but I have not succeeded in solving my problem
I wrote a bot for Telegram with google script
I defined two keys with inline_keyboard
Define a code for each key according to the user’s information, but I did not succeed
I put the code
please help

var KEYBOARD_MAIN = {
  "inline_keyboard": [
    [{ "text": "button 1", 'callback_data': 'btn1' }],
    [{ "text": "button 2", 'callback_data': 'btn2' }]
  ]
};

and this code for doPost()


function doPost(e) {
  var contents = JSON.parse(e.postData.contents);

  if (contents.callback_query) {


    var data = contents.callback_query.data;
    var chat_id = contents.callback_query.from.id;

    if (data == 'btn1') {
      sendMessage(chat_id, 'btn1 clicked');

    } else if (data == 'btn2') {
      sendMessage(chat_id, 'btn2 clicked');
    }

  } else if (contents.message) {
    var chat_id = contents.message.from.id;
    var text = contents.message.text;


    var contents = JSON.parse(e.postData.contents);
    var chat_id = contents.message.chat.id;


    if (text == "/start") {
      deleteMessage(chat_id, contents.message.message_id)
      sendMessageKeyboard(chat_id, "enter your command", KEYBOARD_MAIN);

    } else if (!isNaN(parseFloat(text)) && isFinite(text)) {
      for (var i = 0; i < logins.length; i++) {
        if (chat_id == logins[i]) {
          sBot.getRange("C" + (i + 2)).setValue(text);
          replaceKeyBoard(chat_id, sBot.getRange("D" + (i + 2)).getValue());
        }
      }
    }


  }
};

Time management library [closed]

This is a broad question, but I want to ask for opinions

I’m working with Typescript, Prisma ORM and PostgreSQL stack.
I want to handle time ranges. Let’s say activeStartDate, activeEndDate of different entities.

I want to be able to match when entity A overlaps entity B, query which is active(are active) in a particular date, etc. In general being able to manage time ranges and related operations

Could you suggest a library(in typescript) or is it possible to manage these operations with postgres?

Thanks for your help

Note: I’m trying right now only querying using Prisma ORM which is not easy to read and can be imprecise

I build a News Website with Next.js Server Side rendering and the export const metadata = { title: “TEST” } is not taking action

I have developed a News Website using Next.js with Server Side Rendering. In my pages, I’m utilizing export const metadata = { title: “TEST” } to set the page title, but it doesn’t seem to have any effect. I have checked my implementation, and the metadata object appears to be correctly structured. However, the page title remains unchanged.

Repository : https://github.com/BlendEmini/NewsBlog-ssr

I would appreciate any insights or suggestions on why the metadata object is not affecting the page title as expected. If there’s a better approach or if I’m missing something crucial in the Next.js setup for server-side rendering, please guide me in the right direction. Thank you for your assistance!

I’ve tried several methods to set the page title in my Next.js News Website. Initially, I used the component, then attempted the older approach of defining metadata within the HTML, and finally, I adopted the recommended export const metadata method in each page file. Unfortunately, none of these methods have successfully changed the page title as expected. Despite meticulous checks, the title remains unaffected. I’m seeking guidance on potential issues or alternative approaches to ensure the correct display of page titles. Any assistance is appreciated.

Puppeteer – Calendar Widget will not open

Issue: I cannot select the calendar widget on hotel website (https://www.ihg.com/hotels/us/en/reservation).

Error: Node is either not clickable or not an Element

What I tried (below is my code):

const puppeteer = require('puppeteer')
const fs = require('fs/promises')

async function start(){
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto("https://www.ihg.com/hotels/us/en/reservation", {waitUntil: "domcontentloaded"});

    //! This is not working - Fill Number of NIGHTS
    await page.click('#datePicker div[class="input-adjacent-icon fa fa-calendar"]');

    // waitForSelector 
    await page.waitForSelector('span[class="datepicker-field"] span[class="input-and-icon brand-outline"]');

    await browser.close() 
}

start() 

Creating a chrome extension to dowload images

I have some images on a website that I want to download. However they are blob images and I can’t download them because my requests always get rejected (maybe I am missing a header or a payload idk since devtools dont show me). When I open devtools and look at the network traffic I can see the requst and I can get a preview of the image. I can even download that one, but I want to automate. I decided to write my own chrome extension using the devtools api to capture the responses and I am able to retrieve the blob image, however unlike in the regular devtools network tab, my blob is still fully encrypted. I want to know how I can achieve the same with my extension.

My Setup

manifest.json

{
    "manifest_version": 3,
    "name": "Sniffer",
    "description": "Base Level Extension",
    "version": "1.0",
    "devtools_page": "devtools.html",
    "permissions": [
      "tabs"
    ],
    "icons": {
      "100": "juste.png"
    }
  }

devtools.html

<script src="devtools.js"></script>

devtools.js

chrome.devtools.panels.create("MyPanel", null, 'panel.html');

panel.html

<html>
    <body>
        <div id="a"></div>
        <script src="panel.js"></script>
    </body>
</html>

panel.js

let a = document.getElementById('a');

chrome.devtools.network.onRequestFinished.addListener(request => {
  request.getContent((body) => {
    if (request.request && request.request.url) {
      if (request.request.url.includes('cornelsen.de')) {

         //continue with custom code
        //  var bodyObj = JSON.parse(body);//etc.
        li = document.createElement("li");
        li.innerText = body;
        a.appendChild(li);
      }
    }
  });
});

Output

Wouldn’t make sense to paste the blob in here since its very long, but the important thing is that it’s still encrypted and I don’t know how to decrypt it.

how can i make my rocket stay inside the container?

hi I’m new to this community and i have the following problem

i have a Vue JS 3 code about crash game i have issues in the game
the rocket and the curve after 4.5X it goes out the container
i want it to stay inside the container

  • the crashed image its gif but its not animating
    can someone help me with this issues on vue js 3?!
    this is my code:
<template>
<div class="game">
  <div class="countdownTimer" v-if="crashed && countdown > 0">
    {{ countdown }}
  </div>
  <div class="gameContainer">
    <canvas class="qqq" ref="gameCanvas"></canvas>
    <p class="currentMultiplier">{{ currentMultiplier }}x</p>
  </div>

<div class="infoContainer">
<div style="display: flex;">
<p class="balance">{{ balanceDisplay }}$</p>
<p class="crashedAt">Multiplier at crash: {{ crashedAt }}</p>
</div>
<div class="betContainer">
  <label for="betAmount">Bet Amount:</label>
  <input type="number" v-model="betAmount" />
  <button @click="placeBet" :disabled="placeBetDisabled">Place Bet</button>
</div>
</div>

<div class="buttonContainer">
    <button @click="takeProfits" :disabled="!profitsAvailable || profitsTaken">Take Profits</button>
  </div>
<div class="lastCrashesContainer">
<p>Last Crashes:</p>
<div class="lastCrashes">
<img v-for="(crash, index) in lastCrashes" :key="index" :src="crash.imageUrl" :style="{ borderColor: crash.color }" />
</div>
</div>
</div>
</template>

<script>
export default {
data() {
return {
countdown: 10,
  countdownInterval: null,
gameCanvas: null,
ctx: null,
gameRunning: false,
curvePoints: [1],
gameLoop: null,
balance: 1000,
profitsTaken: false,
crashedAtValue: '',
gameInterval: null,
gameInProgress: false,
crashed: false,
crashedImageUrl: 'https://i.ibb.co/grX0780/ezgif-com-animated-gif-maker.gif',
isCrashImageVisible: false,
};
},
computed: {
  placeBetDisabled() {
    return this.gameInProgress || this.profitsTaken;
    },
  profitsAvailable() {
      console.log('Game In Progress:', this.gameInProgress);
      console.log('Crashed:', this.crashed);
      console.log('Profits Taken:', this.profitsTaken);

      return this.gameInProgress && !this.crashed && !this.profitsTaken;
  },
  
profitsAvailable() {
      console.log('Crashed:', this.crashed);
      console.log('Profits Taken:', this.profitsTaken);

      return this.gameInProgress && !this.crashed && !this.profitsTaken;
  },

balanceDisplay() {
console.log('Balance:', this.balance);

const balanceAsNumber = parseFloat(this.balance);

if (isNaN(balanceAsNumber)) {
  console.error('Invalid balance:', this.balance);
  return 'Invalid Balance';
}

return balanceAsNumber.toFixed(2);
}, 
currentMultiplier() {
const multiplier = (this.curvePoints.length / 100).toFixed(1);
return Math.min(multiplier, 12.0);
},
crashedAt() {
return this.crashed ? this.crashedAtValue : '';
},
lastCrashes() {
return this.curvePoints.map((point) => ({
color: this.profitsTaken ? 'lime' : 'red',
}));
},
profitsAvailable() {
return !this.crashed && !this.profitsTaken;
},
},
mounted() {
this.gameCanvas = this.$refs.gameCanvas;
this.gameCanvas.width = 535;  // Adjust width to match gameContainer
this.gameCanvas.height = 462.5;  // Adjust height to match gameContainer
this.ctx = this.gameCanvas.getContext('2d');
this.ctx.strokeStyle = '#CE9CFF';  // Set the curve line color to #CE9CFF
this.ctx.lineWidth = 2;
this.preloadImage('https://i.ibb.co/PrfVJbz/hello.png');
this.preloadImage('https://i.ibb.co/grX0780/ezgif-com-animated-gif-maker.gif');
// Start the game loop
this.startGameLoop();

// Start the countdown before the game starts
this.startCountdown();
},

beforeDestroy() {
  clearInterval(this.gameLoop);
  clearInterval(this.gameInterval);
  clearInterval(this.countdownInterval);

},
methods: {
startGameLoop() {
this.gameLoop = setInterval(() => {
this.updateGame();
}, 16);
},
startCountdown() {
  this.countdown = 10;
  this.countdownInterval = setInterval(() => {
    if (this.countdown > 0) {
      this.countdown--;
    } else {
      clearInterval(this.countdownInterval);
      this.countdownInterval = null;
      this.startGame();
    }
  }, 1000);
},

preloadImage(url) {
const img = new Image();
img.onload = () => {
  console.log(`Image loaded: ${url}`);
};
img.onerror = () => {
  console.error(`Error loading image: ${url}`);
};
img.src = url;
},
updateCurvePoints() {
  const lastPoint = this.curvePoints[this.curvePoints.length - 1];
  if (this.currentMultiplier < 12.0) {
    const newX = lastPoint.x + 1;
    const newY = this.calculateCurveY(newX);
    this.curvePoints.push({ x: newX, y: newY });
  }
},
updateCurve() {
  this.ctx.clearRect(0, 0, this.gameCanvas.width, this.gameCanvas.height);
  this.ctx.beginPath();

  this.curvePoints.forEach((point) => {
    this.ctx.lineTo(point.x, point.y);
  });

  this.ctx.stroke();

  // Draw the image based on game state
  if (!this.crashed) {
    // Draw the rocket if the game is not crashed
    const lastPoint = this.curvePoints[this.curvePoints.length - 1];
    const rocketImage = new Image();
    rocketImage.src = 'https://i.ibb.co/PrfVJbz/hello.png';
    const rocketX = lastPoint.x - rocketImage.width / 1.95;
    const rocketY = lastPoint.y - rocketImage.height / 1.97;
    this.ctx.drawImage(rocketImage, rocketX, rocketY);
  } else {  
    // Draw the crash image if the game is crashed
    const crashImage = new Image();
    crashImage.src = 'https://i.ibb.co/grX0780/ezgif-com-animated-gif-maker.gif';
    const crashX = this.gameCanvas.width / 2 - crashImage.width / 2;
    const crashY = this.gameCanvas.height / 2 - crashImage.height / 2;
    
    // Ensure the crash image is drawn with animation
    this.image = document.createElement('img');
    this.image.src = crashImage.src;
    this.image.style.position = 'absolute';
    document.body.appendChild(this.image);
    this.image.style.left = crashX + "px";
    this.image.style.top = crashY + "px";
  }
}
,

// Ensure the multiplier never exceeds 12.0x
currentMultiplier() {
  const lastPoint = this.curvePoints[this.curvePoints.length - 1];
  const theoreticalMultiplier = (lastPoint.x / 100).toFixed(1);
  return Math.min(theoreticalMultiplier, 12.0);
},

getXAtMultiplier(multiplier) {
  // Calculate the X value where the multiplier is 12.0x
  const x = Math.sqrt(Math.pow(multiplier * this.gameCanvas.height, 2 / 1.75));
  return Math.min(x, this.gameCanvas.width); // Ensure x does not exceed canvas width
},

getYAtMultiplier(multiplier) {
  // Since Y is directly dependent on X, use the same equation as above
  const y = this.gameCanvas.height - Math.pow(this.getXAtMultiplier(multiplier), 1.75) / 100;
  return Math.min(y, this.gameCanvas.height); // Ensure y does not exceed canvas height
},
placeBetOrTakeProfits() {
  if (this.gameInProgress) {
    // If game is in progress, toggle between "Take Profits" and "Place Bet"
    if (this.profitsTaken) {
      this.takeProfits();
    } else {
      this.placeBet();
    }
  } else {
    // If game is not in progress, only place the bet
    this.placeBet();
  }
},
placeBet() {
      // Add logic to handle placing a bet
      if ((this.gameInProgress || this.countdown > 0) && this.balance >= this.betAmount && this.betAmount > 0) {
        // Ensure the bet amount is a positive value and does not exceed the balance
        this.balance -= this.betAmount;
        // Any additional logic related to placing a bet during the countdown or after a crash
      } else {
        console.log('Invalid bet amount or insufficient balance');
        // Handle invalid bet amount or insufficient balance
      }
    },

updateCurvePoints() {
const lastPoint = this.curvePoints[this.curvePoints.length - 1];
const newX = lastPoint.x + 1;
const newY = this.gameCanvas.height - Math.pow(newX, 1.75) / 100;

document.querySelector('.currentMultiplier').innerText = (this.curvePoints.length / 100).toFixed(1) + 'x';

this.curvePoints.push({ x: newX, y: newY });
},
updateGame() {
if (this.gameInProgress) {
this.updateCurvePoints();
this.updateCurve();
}
},
crashCurve(betAmount) {
  clearInterval(this.gameLoop);

  if (this.curvePoints.length >= 2) {
    const crashPosition = { x: this.curvePoints[this.curvePoints.length - 2].x, y: this.curvePoints[this.curvePoints.length - 2].y - 10 };
    const crashAngle = Math.atan2(
      this.curvePoints[this.curvePoints.length - 1].y - this.curvePoints[this.curvePoints.length - 2].y,
      this.curvePoints[this.curvePoints.length - 1].x - this.curvePoints[this.curvePoints.length - 2].x
    ) + Math.PI / 4;

    this.ctx.clearRect(0, 0, this.gameCanvas.width, this.gameCanvas.height); // Clear the canvas

    this.ctx.save();
    this.ctx.translate(crashPosition.x, crashPosition.y);
    this.ctx.rotate(crashAngle);

    const crashImage = new Image();
    crashImage.onload = () => {
      // Draw the animated crash image with proper size
      this.ctx.drawImage(crashImage, -crashImage.width / 2, -crashImage.height / 2, crashImage.width, crashImage.height);
      this.ctx.restore();
    };
    crashImage.onerror = (error) => {
      console.error(`Error loading crash image: ${error}`);
    };
    crashImage.src = 'https://i.ibb.co/grX0780/ezgif-com-animated-gif-maker.gif';

    const crash = document.createElement('p');
    crash.innerText = `Crash at ${this.currentMultiplier}x`;
    crash.style = 'padding: 0; margin: 0;';
    crash.style.color = this.profitsTaken ? 'lime' : 'red';

    document.querySelector('.lastCrashes').appendChild(crash);

    // Reset the game after a delay
    setTimeout(() => {
      this.resetGame();
      this.startGame();
    }, 3000); // Change the delay as needed
  } else {
    console.error('Invalid curvePoints data for crashing');
  }
},

submitBet() {
if (!this.gameInProgress && this.balance > this.betAmount) {
this.balance -= this.betAmount;
this.startGame();
}
},
takeProfits() {
      if (this.profitsAvailable) {
        console.log('Taking profits...');
        this.profitsTaken = true;

        // Calculate profit based on the current multiplier
        const profit = (this.betAmount * (this.curvePoints.length / 100)).toFixed(2);

        // Add the profit to the balance
        const newBalance = parseFloat((this.balance + parseFloat(profit)).toFixed(2));

        this.balance = newBalance;
      } else {
        console.log('Profits already taken or game not in progress');
      }
    } ,

    startGame() {
      if (this.gameRunning) {
        // Only start a new game if the game is not already running
        return;
      }
      this.curvePoints = [{ x: 0, y: this.gameCanvas.height }];
      this.resetGame(); // Reset the game-related properties
      // ... other setup code ..
this.curvePoints = [{ x: 0, y: this.gameCanvas.height }];
this.gameInProgress = true;  // Set gameInProgress to true before starting the game loop
this.profitsTaken = false; // Reset profitsTaken on starting a new game
this.crashed = false; // Reset crashed flag

// Clear previous intervals and reset canvas
clearInterval(this.gameLoop);
this.ctx.clearRect(0, 0, this.gameCanvas.width, this.gameCanvas.height);

// Set up an interval to update the game every 16ms
this.startGameLoop();

setTimeout(() => {
  this.crashCurve(this.betAmount);
}, this.getRandomCrashTime(1, 12));
},
resetGame() {
      this.gameInProgress = false;  // Set gameInProgress to false when resetting the game
      this.profitsTaken = false; // Reset profitsTaken when the game is reset
      // Reset any other necessary game-related properties
    },
startGameInterval() {
// Set up an interval to start the game every 10 seconds
this.gameInterval = setInterval(() => {
this.submitBet();
}, 10000);
},
getRandomCrashTime(min, max) {
const randomDecimal = Math.random();
const randomNumber = randomDecimal * (max - min) + min;

return randomNumber * 1000;
},
},
};
</script>

<style scoped>
.qqq{
  width: 50rem;
  height: 45rem;
}
body {
background-color: #1f1e25;
color: white;
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
}

.gameContainer {
position: relative;
margin-bottom: 20px;
width: 100%;
height: 100%;

}

.game {
  position: absolute;
  right: 5rem;
  width: 53.5rem;
height: 46.25rem;
background-image: url(../assets/img/back.png);
padding: 0.5rem;
padding-left: 0;
}

.currentMultiplier {
position: absolute;
top: 110px;
left: 70px;
font-size: 50px;
}
.countdownTimer {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 50px;
color: #FFF;
}
.infoContainer {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}

.balance {
color: lime;
font-weight: bold;
margin-right: 5px;
}

.crashedAt {
margin-right: 5px;
}

.betContainer {
display: flex;
align-items: center;
margin-bottom: 10px;
}

.betContainer label {
margin-right: 5px;
}

#betAmount {
width: 40px;
padding: 5px;
}

.buttonContainer {
margin-bottom: 10px;
width: 400px;
}

button {
  display: flex;
width: 17rem;
padding: 0.75rem 1rem;
justify-content: center;
align-items: center;
gap: 0.625rem;
border-radius: 0.5rem;
border: 1px solid rgba(255, 255, 255, 0.20);
background: var(--Style, linear-gradient(180deg, #B352FF 0%, #CE9CFF 100%));
backdrop-filter: blur(4px);
color: #FFF;
text-align: center;
font-family: Satoshi;
font-size: 0.875rem;
font-style: normal;
font-weight: 700;
line-height: 1.25rem; /* 142.857% */
}


.countdownTimer {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 50px;
  color: #FFF;
  background-color: #333;
  padding: 10px 20px;
  border-radius: 5px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100px;
  height: 100px;
}

.lastCrashesContainer {
margin-top: 20px;
}

.lastCrashesContainer p {
font-weight: bold;
}

.lastCrashes {
margin-top: 5px;
}
</style>

this is when the rocket and the curve go out the box

I tried To ensure that the curve and the rocket stay within the gameContainer div
and i tried to make the crashed img to be animated but its not working
i tried using chat gpt but with no luck

Nextjs/React expand box (accordion) animation failed with tailwindcss

I am trying to make animation for an expandable box (accordion).

This is what I want to achieve: the child component is by default set as display:none. When I hover my mouse to its parent component, the child is shown, and the width/height of the parent is adjusted accordingly.

However the animation is not working

Here is a minimal reproduction:

export default function Home() {
  return (
    <main className="flex w-[50vw] p-10 items-center justify-center">
      <div className="border-black group border-2 transition-all min-w-5 min-h-5 w-auto h-auto bg-red-300">
        <div className="hidden w-20 group-hover:block bg-gray-200">
          placeholder
        </div>
      </div>
    </main>
  );
}

I noticed that the animation would work if i were to set the size of the parent manually like this:

export default function Home() {
  return (
    <main className="flex w-[50vw] p-10 items-center justify-center">
      <div className="border-black group border-2 transition-all w-5 h-5 hover:w-10 hover:h-10 bg-red-300">
        <div className="hidden w-20 group-hover:block bg-gray-200">
          placeholder
        </div>
      </div>
    </main>
  );
}

But this is not desired: as we have to place magic numbers for parent’s size.

Is it possible to let the first version of my code to work?

Thanks in advance.

when change checkbox from Yes to No not sent value correctly to submit function when click approve button?

I work on asp.net MVC application I face issue when change check box (Yes to No) OR (No to Yes)

not detect value true or false correctly .

I have two check box

Yes represent true value

No represent false value

I don’t need to change checkbox to radio button because this is user requirement as checkbox .

when select Yes or No for first time it send value correctly

but when I select Yes or No for second time it not send value correctly and send only value false to approve button when select Yes or No .

What I Try

1 – User UI for Yes or No

<td style="width: 50%; font-weight: bold; padding-top: 10px;">
      @Html.Label("Did you try to retain the staff?", htmlAttributes: new { @class = "control-label col-md-5" })
      <div class="col-md-7">
          <input type="checkbox" id="RetainStuff" name="RetainStuff" value="true" class="retaindtuff-checkbox" @(Model.RetainStuff == true ? "checked" : "") />
          Yes
          &nbsp;&nbsp;
          <input type="checkbox" id="RetainStuff" name="RetainStuff" value="false" class="retaindtuff-checkbox" @(Model.RetainStuff == false ? "checked" : "") />
          No
      </div>
  </td>
   <a id="approveControlsId" onclick="submit();" class="btn btn-primary" style="min-width: 100px;margin-top:5px;"><i class="glyphicon glyphicon-ok"></i> Approve </a>

2 – when change Yes or No check box to get value true or false of retain stuff checkbox i use jQuery as below :

 $('.retaindtuff-checkbox').on('change', function () {
     $('.retaindtuff-checkbox').not(this).prop('checked', false);
     var selectedValue = $(this).val();
     $('#RetainStuff').val(selectedValue);

 });

3 – when click approve button value of check box
not send correctly to submit() function

function submit() {
        
            var ResignationRequester = new Object();
            ResignationRequester.RequestNo = document.getElementById("RequestNo").innerHTML.trim();
   
  

        var RetainStuffElement = document.getElementById("RetainStuff");

        if (RetainStuffElement) {
           
            var RetainStuffElementExist = document.querySelector('input[name="RetainStuff"]:checked');
          
            if (RetainStuffElementExist && RetainStuffElementExist.value === "false") {
                ResignationRequester.RetainStuff = RetainStuffElementExist.value;
                
                ResignationRequester.RetainStuff = null;
                return false;
            } 
            else if (RetainStuffElementExist) {
                ResignationRequester.RetainStuff = RetainStuffElementExist.value;
               
            } 
            else {
                ResignationRequester.RetainStuff = null;
                
                return false;
            }
        }
        else {
            ResignationRequester.RetainStuff = "";

        }
 
            if (ResignationRequester != null) {
                $.ajax({
                    type: "POST",
                    url: '@Url.Action("ApprovalIndex", "Resignation")',
                    data: JSON.stringify(ResignationRequester),
                    contentType: "application/json; charset=utf-8",
            
                    datatype: "html",
                    success: function (response) {
                        
                    }
                    
                });
            }
    }  

4 – action result calling ApprovalIndex on resignation controller

[HttpPost] 
public async Task<ActionResult> ApprovalIndex(ResignationRequester REQ) 
{ 
//update approve status 
} 

so why checkbox yes or no working on first time only

Image for page i work on it

image show issue

Handling european decimal format in Svelte input component: synchronization and parsing sssues

I am writing an input component in Svelte. I have encountered a problem. My application is intended for the European market. In Europe, we use a comma as decimal separator.

The problem is that if the user enters a number in the European format (e.g. 12,5) into the input, Javascript will receive this as a String and mathematical operations cannot be performed on it.

So I wrote a workaround for this problem – the user is shown what they typed into the input (12,5), and the formatted value (12.5) is binded. However, the problem is that if the parent updates the input value, it is not synchronised with the displayed value. For example, when value is set to "" by the parent, the change will not be visible in the input.

<script>
    export let value;
    export let type = 'text';

    let displayValue = value;
    
    const handleInput = (e) => {
        if (type === 'number') {
            value = formatInputNumber(e.target.value);
            displayValue = e.target.value;
        } else {
            value = e.target.value;
            displayValue = e.target.value;
        }
    };
</script>

<input
    {type}
    value={displayValue}
    on:input={handleInput}
    pattern={type === 'number' ? '[0-9]+([,.][0-9]+)?' : ''}
    {...$$restProps}
/>

A working live example: https://svelte.dev/repl/4f10a5ed9e164d4c969d61c8fd154ede?version=4.2.9

Currently, as a workaround, I use the formatInputNumber function every time I do some mathematical operation on values from an input. However, this is an impractical approach – my application mainly relies on mathematical operations and there are many such inputs. It is easy to accidentally forget to use this function and such a notation looks ugly.

never ending loop for user populated arraylist

I need to write a method to take user input car specs and add them into an ArrayList. This needs to accept any amount of specs the user wants to input, including none.
This is my first post here, so apologies for any poor syntax.

public static ArrayList getTrim() {

Scanner t = new Scanner(System.in);
System.out.println("Enter car trim");
ArrayList<String> trim = new ArrayList<>();

while (t.hasNext()) {
trim.add(t.next());
}

return trim;

}

I thought this condition would return false if whitespace was entered. This continues iterating and can only be exited manually.

I also tried

if (t.hasNext()) {
trim.add(t.next());
}

else {
t.close();
}

This iterates once and then returns the ArrayList, but I need to be able to input more. Changing my if or while condition to hasNextLine() gives the same results stated, here I used hasNext() because car trim levels have certain format expectations. I do not understand why hasNext() will not return as false when no input is given.

How to use dynamic component names in qwik?

I wanted to dynamically use either html <button> or qwik <Link> based on whether href prop is present, but the link doesn’t seem to work this way and clicking on it does nothing

import { Slot, component$ } from "@builder.io/qwik";
import { Link } from "@builder.io/qwik-city";

interface ButtonProps {
  href?: string;
}

export const Button = component$<ButtonProps>(({ href }) => {
  const Component = href ? Link : "button";

  return (
    <Component class="cursor-pointer select-none bg-blue-600 px-4 py-2 text-white">
      <Slot />
    </Component>
  );
});

Can I mock an undefined variable to test a JS file?

I have an API gateway platform running, and inside the APIs, we have the interceptors (written in Rhino.js, to be more specific), that map body, call other APIs, etc.

The problem is we have environment variables that the files use. For example, we have a variable called $call that stores information about the call (request, response, body, etc). When we try to run tests in these files, the error says that “$call is not defined”.

An example here:

const requestBody = JSON.parse($call.request.getBody().getString("utf-8"));

This $call is defined by the platform, and not another JS file. I don’t have the access to the definition.

The test code:

describe("errorResponse method", () => {
            it("Should get errorResponse result successfully", () => {
                let errorResult = mochaExample.errorResponse("Bad Request", 200);
                errorResult.includes("Bad Request").should.be.true;
            });
        });  

And here, the error message:

ReferenceError: $call is not defined

Is there a way to define/mock this variable in the test.js file to run the tests?

I’m using Mocha and Chai to test JavaScript files.

I tried to use Rewire, proxyquire and sinon to mock/define this variable, but without success. I tried to declare this variable in the beginning of the test.js file, before the require, but without success

Uncaught ReferenceError: can’t access lexical declaration ‘amtSavingsInput’ before initialization

I have three forms which do some calculations and then chart them. Everything worked for form 1/chart 1 and form2/chart2 but when I coded form3/chart3/ in the same way it broke. The steps are the same and its only the calculation thats different. I have tried many different ways like only loading after the DOM is loaded to get it working but to no avail.

The error I get is “Uncaught ReferenceError: can’t access lexical declaration ‘amtSavingsInput’ before initialization”

This is the code for form3/chart3:

// Get the input fields and chart canvas
let amtSavingsInput = document.getElementById('amt_Savings');
let yieldSavingsInput = document.getElementById('yield_Savings');
let amtVanguardInput = document.getElementById('amt_Vanguard');
let yieldVanguardInput = document.getElementById('yield_Vanguard');

// Get the cashInChart canvas element
const moneyMapChartElement = document.getElementById('moneyMapChart');

// Set the initial data for the chart
const chart3 = {
  labels: ['1', '2', '3', '4', '5'],
  datasets: [
    {
      label: '',
      data: [],
      backgroundColor: 'rgba(75, 192, 192, 0.6)',
      borderWidth: 1
    }
  ]
};

// Create the chart
const moneyMapChart = new Chart(moneyMapChartElement, {
  type: 'bar',
  data: chart3,
  options: {
    responsive: false,
    scales: {
      y: {
        type: 'linear', // Set the scale type to 'linear'
        beginAtZero: true
      }
    }
  }
});

// Function to calculate and update the chart
function updateChart() {
  let amtSavings = parseFloat(amtSavingsInput.value);
  let yieldSavings = parseFloat(yieldSavingsInput.value);
  let amtVanguard = parseFloat(amtVanguardInput.value);
  let yieldVanguard = parseFloat(yieldVanguardInput.value);

  // Convert monthly savings to yearly savings
  amtSavings *= 12;
  amtVanguard *= 12;

  const years = 5; // Set the desired number of years

  const capitals = calculateCapitalGrowth(amtSavings, yieldSavings, amtVanguard, yieldVanguard, years);

  // Update the chart data
  moneyMapChart.data.datasets[0].data = capitals;
  moneyMapChart.update();
}

// Add event listeners to input fields
amtSavingsInput.addEventListener('input', updateChart);
yieldSavingsInput.addEventListener('input', updateChart);
amtVanguardInput.addEventListener('input', updateChart);
yieldVanguardInput.addEventListener('input', updateChart);

with a basic html bootstrap form:

  <div class="col-md-6">
                <h2>Savings and Investments</h2>
                <p>Growing wealth is about holding onto money. Choose how much of your £<span class="inline-block"
                        id="cashLeftDisplay2"></span> (cash leftover) that you will save or invest.</p>
                <form> <!-- Savings & Investments form-->
                    <div class="mb-3">
                        <label for="amt_Savings" class="form-label">Amount in a Savings Account</label>
                        <input type="text" class="form-control" id="amt_Savings" value="0" placeholder="0">
                      </div>
                      <div class="mb-3">
                        <label for="yield_Savings" class="form-label">Yearly Interest % Earned</label>
                        <input type="text" class="form-control" id="yield_Savings" value="0" placeholder="0">
                      </div>
                      <div class="mb-3">
                        <label for="amt_Vanguard" class="form-label">Amount in Vanguard Account</label>
                        <input type="text" class="form-control" id="amt_Vanguard" value="0" placeholder="0">
                      </div>
                      <div class="mb-3">
                        <label for="yield_Vanguard" class="form-label">Benchmark % Return</label>
                        <input type="text" class="form-control" id="yield_Vanguard" value="0" placeholder="0">
                      </div> 
                </form>
                <button class="btn btn-primary" id="nextButton">Next</button>
            </div>

How to get this code to work without the if statement

I can’t seen to figure out how to do it: https://jsfiddle.net/3par6zfe/

How would I be able to remove the if statement from this code and for it to be able to work?

function createResetHandler(player) {
  const myModal = document.querySelector("#myModal");
  const close = document.querySelector(".close");
  const ytplayer0 = document.querySelector("#ytplayer0");

  function clickMenu() {
    if (player && player.getIframe() && ytplayer0 && player.getIframe().id === ytplayer0.id) {
      player.destroy();
      myModal.classList.remove("open");
      console.log("hit");
    }
  }

  close.addEventListener("click", clickMenu);
  myModal.addEventListener("click", clickMenu);
}

Code:

<div id="myModal" class="modal open">
  <div class="modal-content">
    <div class="blog-pager close">
      <a title="Exit" aria-label="Close"></a>
    </div>
    <div class="ratio-keeper">
      <div id="ytplayer0" data-id="1Q1aDAnBsU8"></div>
    </div>
  </div>
</div>
<!-- end modal -->

<div class="container">
  <div class="ratio-keeper">
    <div id="ytplayer1" data-id="1Q1aDAnBsU8"></div>
  </div>
</div>
<div class="container">
  <div class="ratio-keeper">
    <div id="ytplayer2" data-id="1Q1aDAnBsU8"></div>
  </div>
</div>
<div class="container">
  <div class="ratio-keeper">
    <div id="ytplayer3" data-id="1Q1aDAnBsU8"></div>
  </div>
</div>
<div class="container">
  <div class="ratio-keeper">
    <div id="ytplayer4" data-id="1Q1aDAnBsU8"></div>
  </div>
   </div>
  <div class="container">
  <div class="ratio-keeper">
    <div id="ytplayer5" data-id="1Q1aDAnBsU8"></div>
  </div>
</div>


/ modal code
(function (d) {
  const myModal = d.querySelector("#myModal");
  const close = d.querySelector(".close");
  close.addEventListener("click", clickMenu);
    myModal.addEventListener("click", clickMenu);
  function clickMenu() {
    myModal.classList.remove("open");
  }
})(document);
//end modal code


//code from fiddle below

const tag = document.createElement("script");
tag.src = "https://www.youtube.com/iframe_api";
const firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

let players = [];

function createResetHandler(player) {
  const myModal = document.querySelector("#myModal");
  const close = document.querySelector(".close");
  const ytplayer0 = document.querySelector("#ytplayer0");

  function clickMenu() {
    if (player && player.getIframe() && ytplayer0 && player.getIframe().id === ytplayer0.id) {
      player.destroy();
      myModal.classList.remove("open");
      console.log("hit");
    }
  }

  close.addEventListener("click", clickMenu);
  myModal.addEventListener("click", clickMenu);
}

function onPlayerReady(event) {
  player = event.target;
  player.setVolume(100);
  createResetHandler(player);
}

function onPlayerStateChange(event) {
  if (event.data === YT.PlayerState.PLAYING) {
    for (let i = 0; i < players.length; i++) {
      if (players[i] !== event.target) players[i].pauseVideo();
    }
  }
}

function onYouTubeIframeAPIReady() {
  const divElements = document.querySelectorAll('.ratio-keeper div');
  for (let i = 0; i < divElements.length; i++) {
    players[i] = new YT.Player(divElements[i].id, {
      height: '361',
      host: 'https://www.youtube-nocookie.com',
      width: '642',
      videoId: divElements[i].getAttribute('data-id'),
      playerVars: {
        autoplay: 0,
        cc_load_policy: 0,
        controls: 1,
        disablekb: 1,
        fs: 0,
        iv_load_policy: 3,
      },
      events: {
        'onReady': onPlayerReady,
        'onStateChange': onPlayerStateChange
      }
    });
  }
}