Javascript onClick picks the wrong element? - javascript

for(let x = 0; x < 10; x++){container_For_Dices.push(Math.round(Math.random()*10))}
let Ids = ["Dice1","Dice2","Dice3","Dice4","Dice5","Dice6","Dice7","Dice8","Dice9","Dice10"]
let id = -1
container_For_Dices= container_For_Dices.map((value=>{
id +=1
return(
<button
className="w-20 h-20 m-2 rounded-lg bg-slate-300 content-center pt-4 shadow shadow-gray-500 text-4xl font-bold dices"
id={Ids[id]}
onClick={()=>{
var element = document.getElementById(`${Ids[id]}`)
element.classList.remove("dices")
element.style.backgroundColor = "rgba(255,255,255,0.5)"
}} >
{value}
</button>
)
}))
The problem is definitely in the onClick part, but I have no clue how to fix it. If I click on one of the elements, the 10th element gets picked. I already checked that every element got the correct id...

Try passing event argument onClick={(e)=>{ and extract element from event var element = e.target;
<button
className="w-20 h-20 m-2 rounded-lg bg-slate-300 content-center pt-4 shadow shadow-gray-500 text-4xl font-bold dices"
id={Ids[id]}
onClick={(e)=>{
var element = e.target;
element.classList.remove("dices")
element.style.backgroundColor = "rgba(255,255,255,0.5)"
}} >

Related

This code only allows the use of Carousel Post style one time

I recently learned about web development, and I want to build my own portfolio website using Github Pages. For the 'Portfolio' section, I want to use a slider using Javascript. Then, when I copy paste the code and change the title to 'Blog' section, this new section didn't apply the slider that seen in Portfolio.
I already seen multiple online sources to see where is my problem, and it shows that the getElementById only can be used one time. I try to modify the code to use querySelectorAll but it's still doesn't work.
This is the JS code that I used:
const sliderContainer = document.getElementById('sliderContainer');
const slider = document.getElementById('slider');
const cards = slider.getElementsByTagName('li');
var elementsToShow = 3;
if (document.body.clientWidth < 1000) {
elementsToShow = 1;
} else if (document.body.clientWidth < 1500) {
elementsToShow = 2;
}
var sliderContainerWidth = sliderContainer.clientWidth;
var cardWidth = sliderContainerWidth / elementsToShow;
slider.style.width = cards.length * cardWidth + 'px';
slider.style.transition = 'margin';
slider.style.transitionDuration = '1s';
for (var index = 0; index < cards.length; index++) {
const element = cards[index];
element.style.width = cardWidth + 'px';
}
function next() {
if (+slider.style.marginLeft.slice(0, -2) != -cardWidth * (cards.length - elementsToShow)) slider.style.marginLeft = +slider.style.marginLeft.slice(0, -2) - cardWidth + 'px';
}
function prev() {
if (+slider.style.marginLeft.slice(0, -2) != 0) slider.style.marginLeft = +slider.style.marginLeft.slice(0, -2) + cardWidth + 'px';
}
function autoPlay() {
prev();
if (+slider.style.marginLeft.slice(0, -2) === -cardWidth * (cards.length - elementsToShow)) {
slider.style.marginLeft = '0px';
}
setTimeout(() => {
autoPlay();
}, 3000);
}
and this is my HTML code. I use TailwindCSS for the CSS framework.
<div class="flex">
<div class="flex items-center">
<div class="w-full text-right">
<button class="bi bi-arrow-left-circle-fill mb-2 ml-2 flex h-9 w-9 items-center justify-center rounded-full border border-slate-300 text-slate-300 hover:border-primary hover:bg-primary hover:text-white"
onclick="prev()"
></button>
</div>
</div>
<div id="sliderContainer" class="overflow-hidden">
<ul id="slider" class="flex w-full">
<li>Slide 1</li>
<li>Slide 2</li>
<li>Slide 3</li>
</ul>
</div>
<div class="flex items-center">
<div class="w-full">
<button
onclick="next()"
class="bi bi-arrow-right-circle-fill mr-2 mb-2 ml-2 flex h-9 w-9 items-center justify-center rounded-full border border-slate-300 text-slate-300 hover:border-primary hover:bg-primary hover:text-white slider__btn--right"
></button>
</div>
</div>
</div>
Please help me modify the JS code so it can be use multiple times. thanks in advance!

interpolate javascript if statement into html

In a javascript file I currently have some HTML saved into a variable.
However I only want to display the middle section of the HTML on a condition. See the if code.length == 1.
var html = `<div class="flex justify-between p-3 border-b border-blue-200" id=${this.id}><div> <h5 class="font-bold text-blue-700 text-sm mb-1 pr-2"> ${Name}</h5> <p class="text-sm text-blue-500"> if (Code.length == 1) { <span class="font-semibold mr-1"><%= t("common.code") %></span> <span> </span> } </p></div></div>`
However I can't seem to get this working. Is this possible?
That line is too long to be maintainable. Break it up so you can see what's going on.
var html = `<div class="flex justify-between p-3 border-b border-blue-200" id=${this.id}><div> <h5 class="font-bold text-blue-700 text-sm mb-1 pr-2"> ${Name}</h5> <p class="text-sm text-blue-500">`;
if (Code.length == 1) {
html += `<span class="font-semibold mr-1"><%= t("common.code") %></span> <span> </span>`;
}
html += `</p></div></div>`
Use a variable
In your HTML snippet you are already using variables. Why not stick to that by making the content a variable. See snippet below with values added as an example using a variable content.
This part seems prepared server-side: <%= t("common.code") %>. You know how to do that yourself I'm assuming.
let Code = 'K';
let id = '5'; // this.id;
let Name = 'Herring';
var content = Code.length == 1 ? `<span class="font-semibold mr-1"><%= t("common.code") %></span>` : '';
var html = `<div class="flex justify-between p-3 border-b border-blue-200" id="${id}"><div>
<h5 class="font-bold text-blue-700 text-sm mb-1 pr-2">${Name}</h5>
<p class="text-sm text-blue-500">${content}</p>
</div></div>`;
console.log(html);

How to apply onClick in the input

As you can this is a string js and I want to use onClick on the input whose view is being toggled by selecting the boolean value edit. Please suggest how to use onchnage here.
Already tried normal HTML onchange (not working)
onchange="${onchnage}"
Pls, suggest if you happen to know the answer.
export const DefaultNode = (d, selectedNodeIds, edit, fomatOptions, inputOnclick) => {
const mainData = d.data.data
return `<div style='background:${selectedNodeIds.length!==0 ? (selectedNodeIds.includes(d.data.id) ? `rgba(${ fomatOptions.nodeBg.r }, ${ fomatOptions.nodeBg.g }, ${ fomatOptions.nodeBg.b }, ${ fomatOptions.nodeBg.a })`: "#fff"): `rgba(${ fomatOptions.nodeBg.r }, ${ fomatOptions.nodeBg.g }, ${ fomatOptions.nodeBg.b }, ${ fomatOptions.nodeBg.a })`};
color:${selectedNodeIds.length!==0 ?(selectedNodeIds.includes(d.data.id) ?`rgba(${ fomatOptions.textColor.r }, ${ fomatOptions.textColor.g }, ${ fomatOptions.textColor.b }, ${ fomatOptions.textColor.a })`:'#000'): `rgba(${ fomatOptions.textColor.r }, ${ fomatOptions.textColor.g }, ${ fomatOptions.textColor.b }, ${ fomatOptions.textColor.a })`}'
class=${`"w-[250px] p-3 rounded-[15px] relative border-[3px] h-[140px] ${selectedNodeIds.includes(d.data.id)? 'drop-shadow-md' :"shadow"} ${ selectedNodeIds.includes(d.data.id) && fomatOptions.fontFamily.value}"`}>
<div class='flex justify-between w-full '>
<div class="">
${edit? `<input onclick='${inputOnclick}' class="fullName text-[13px] font-semibold" value="${mainData.name}"/>` : `<div class=" text-[13px] font-semibold">${mainData.name} </div>`}
<div class=" text-[11px] opacity-70 mt-0.5 font-medium">${mainData.position } </div>
<div class='mt-2'>
<div class=" text-[11px] opacity-70 mt-0.5 font-medium">${mainData.email } </div>
<div class=" text-[11px] opacity-70 mt-0.5 font-medium">${mainData.phone } </div>
</div>
</div>
<img class='w-10 h-10 mr-2 rounded-[10px]' src=${mainData.imgUrl} />
</div>
<div class='flex pt-4 justify-between items-center'>
<p class='text-[10px] font-medium uppercase bg-theme-gray px-2 text-black rounded-full py-0.5'>${mainData.department}</p>
<p class='text-[10px] font-medium uppercase mr-2'>${mainData.location}</p>
</div>
${((selectedNodeIds.includes(d.data.id))) ? `<div class="absolute left-4 -top-5 font-semibold text-[10px] p-1 bg-gray-400 text-white rounded-t-md">
Selected
</div>`: `<p></p>`}
</div>`
}
I believe what you're missing here is the different naming conventions for default HTML event listeners in React, not all of your code is here so I'm assuming you do not have a custom function called onchange, but in React its called onChange (or onClick, etc) so you're looking something like this for your code snippet.
onChange="${onchnage}"
Also double-check to make sure you have all your syntax and spelling correct. Also for writing better JSX for returning HTML elements you can write code like the following
return (
<div>
<p>Text here</p>
</div>
);

Programmatically Set an href Link in React

I have a product that I want to programatically set a Checkout Session URL and then redirect a user when they click on an tag.
const PlanComponent = () => {
const [tiers, setTiers] = useState([]);
async function CheckoutSessionUrl(tierId) {
var result = null
await CreateCheckoutSession(
"PRODUCT_ID",
tierId,
"UID"
).then(function(response) {
result = response
})
return result;
};
async function LoadProducts() {
var result = []
await GetProducts("PRODUCT_ID").then(function(response) {
for (var i = 0; i < response.length; i++) {
var tier_id = response[i]["tier_id"]
CheckoutSessionUrl(tier_id).then(function(tier_response) {
response[i]["url"] = tier_response;
})
}
console.log("printing tiers");
console.log(response);
return response;
}).then(function(response){
result = response;
setTiers(result)
return result;
});
return result;
}
useEffect(() => {
// Some initialization logic here
LoadProducts().then(function(response) {
console.log("setting tiers")
console.log(response)
//setTiers(response)
})
}, []);
return (
<div className="bg-white">
<div className="max-w-7xl mx-auto py-24 px-4 sm:px-6 lg:px-8">
<div className="sm:flex sm:flex-col sm:align-center">
<h1 className="text-5xl font-extrabold text-gray-900 sm:text-center">Pricing Plans</h1>
<p className="mt-5 text-xl text-gray-500 sm:text-center">
Start building for free, then add a site plan to go live. Account plans unlock additional features.
</p>
</div>
<div className="mt-12 space-y-4 sm:mt-16 sm:space-y-0 sm:grid sm:grid-cols-2 sm:gap-6 lg:max-w-4xl lg:mx-auto xl:max-w-none xl:mx-0 xl:grid-cols-4">
{tiers.map((tier) => (
<div key={tier.name} className="border border-gray-200 rounded-lg shadow-sm divide-y divide-gray-200">
<div className="p-6">
<h2 className="text-lg leading-6 font-medium text-gray-900">{tier.name}</h2>
<p className="mt-4 text-sm text-gray-500">{tier.description}</p>
<p className="mt-8">
<span className="text-4xl font-extrabold text-gray-900">${tier.price}</span>{' '}
<span className="text-base font-medium text-gray-500">/mo</span>
</p>
<a
href={tier.url}
className="mt-8 block w-full bg-gray-800 border border-gray-800 rounded-md py-2 text-sm font-semibold text-white text-center hover:bg-gray-900"
>
Buy {tier.name}
</a>
</div>
<div className="pt-6 pb-8 px-6">
<h3 className="text-xs font-medium text-gray-900 tracking-wide uppercase">What's included</h3>
<ul role="list" className="mt-6 space-y-4">
{tier.users.map((feature) => (
<li key={feature} className="flex space-x-3">
{/*<CheckIcon className="flex-shrink-0 h-5 w-5 text-green-500" aria-hidden="true" />*/}
<span className="text-sm text-gray-500">{feature}</span>
</li>
))}
</ul>
</div>
</div>
))}
</div>
</div>
</div>
)
}
so if you look at the href={tier.url} it's not being set correctly. I feel like I'm not doing this correctly. Would love some feedback on how to actually get this working properly. IT looks like the tier.url new field isn't being set correctly (doesn't exist in the initial request but all the other attributes work).
The other option I wanted to do was when a user clicked a Button, it would generate a URL and redirect a user to that new external url but the navigation kept breaking.
Oh I found out what was happening. I needed to replace
await GetProducts("PRODUCT_ID").then(function(response) {
with
await GetProducts("PRODUCT_ID").then(async function(response) {

Change button based on click vuejs tailwind

I have expanded this code for my own learning abilities. I understand I can definitely shorten this down a LOT but I am trying to learn and expand my frontend experience.
So I have the code below. When localstorage it set to true/false it picks up the right v-if/else section. Now, what I need to do is set the local storage based on button click.
What is the best way to accomplish this?
<div v-if="privateChat == 'false'">
<button type="button">
<a key="privateChat" href="#" class="bg-red-900 text-gray-100 hover:bg-gray-800 hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs font-medium">
<ChatIcon class="h-6 w-6 text-white"/>
<span class="pt-2">Private Chat OFF</span>
</a>
</button>
</div>
<div v-else>
<button type="button">
<a key="privateChat" href="#" class="bg-green-900 text-gray-100 hover:bg-gray-800 hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs font-medium">
<ChatIcon class="h-6 w-6 text-white"/>
<span class="pt-2">Private Chat ON</span>
</a>
</button>
</div>
<script>
export default {
data() {
return {
privateChat: (localStorage.getItem("privateChat") === 'true') ? 'true' : 'false',
}
},
methods: {
clickPrivateChat (value) {
this.privateChat = value === true ? "true" : "false";
localStorage.setItem("privateChat", value);
},
setup() {
const enabled = ref(privateChat)
let value = localStorage.getItem("privateChat");
let privateChat = (value === 'true');
}
</script>
There are several improvements you can make...
use actual true/false values instead of "true", "false" strings
DRY: you just need one button; use a Vue computed value to show "ON" or "OFF"
use conditional :class logic to apply bg-green-900 class
script:
data() {
return {
privateChat: (localStorage.getItem("privateChat") === true) ? true : false,
}
},
computed: {
onOrOff() {
return this.privateChat ? 'ON' : 'OFF'
}
},
methods: {
clickPrivateChat (value) {
this.privateChat = !this.privateChat
localStorage.setItem("privateChat", value)
},
setup() {
const enabled = ref(privateChat)
let value = localStorage.getItem("privateChat")
let privateChat = (value === true)
}
},
markup:
<div>
<button type="button" #click="clickPrivateChat">
<a key="privateChat" href="#" :class="privateChat?'bg-green-900':''" class="bg-red-900 text-gray-100 hover:bg-gray-800 hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs font-medium">
<span class="pt-2">Private Chat {{ onOrOff }}</span>
</a>
</button>
</div>
improved Vue approach

Categories