I am trying to use the mobile friendly hotpot code from codepen https://codepen.io/abcretrograde/pen/dKGOEL
When the user clicks on the hotspot is pops up with some text etc. I tried putting a button and a link in to popup but neither work.
In the JavaScript I have tried adding EventListeners to the buttons but they still wont fire when user clicks on them. anyone got any ideas?
in the javascript i have tried both the following, get no errors but doesn't do anything
<div class="lg-container">
<img id="skyemap" src="/assets/imgs/map.png" class="lg-image" alt="myMap" />
<div style="top: 70%; left: 50%;" class="lg-hotspot lg-hotspot--top-left">
<div class="lg-hotspot__button"></div>
<div class="lg-hotspot__label">
<h4>View More Details</h4>
</p>Click the button to view more information
<button class="btn btn-sm btn-success btnFP" id="btnFP">Visit Here</button>
</p>
</div>
</div>
<script>
const selectHotspot = (e) => {
const clickedHotspot = e.target.parentElement;
const container = clickedHotspot.parentElement;
const hotspots = container.querySelectorAll(".lg-hotspot");
hotspots.forEach(hotspot => {
if (hotspot === clickedHotspot) {
hotspot.classList.toggle("lg-hotspot--selected");
const childHP = hotspot.querySelector('.lg-hotspot__label');
const btn = childHP.querySelector('.btn');
childHP.addEventListener('click', ()=>{
alert('clicked');
});
} else {
hotspot.classList.remove("lg-hotspot--selected");
}
});
}
(() => {
const buttons = document.querySelectorAll(".lg-hotspot__button");
buttons.forEach(button => {
button.addEventListener("click", selectHotspot);
});
})();
const btnFP = document.getElementById('btnFP');
btnFP.addEventListener('click', ()=>{
alert('clicked');
});
Related
I need to render a new card that already has a function with the change event. I was trying to remove a class from the actual card (show) so it wont show the card and then add a class (show) to the oter card that I want to render. I did this code, but it doesnt work, any other ideas? thanks.
const dropdownmenucli = () => {
const print = document.getElementById ('drop2');
const dropdown= document.getElementById ('dropdowns2');
const printDocument=document.getElementById('cnd');
const delWindow=document.getElementById('exampleModal2');
const popWindow=document.getElementById('exampleModal');
dropdown.addEventListener('change', (event) => {
const value = document.getElementById('dropdowns2').value;
print.innerHTML=`
<div class="padding-b" >
<a class="text-decoration btn btn-primary" id="cnd"> Create New Document </a>
<a class="text-decoration btn btn-primary" href="/Create/${value}"> Existing Document</a>
</div>
`
})
}
const Redirect = document.getElementById('cnd') ? () => {
printDocument.addEventListener('clik',(event) => {
delWindow.classList.remove("show");
popWindow.classList.add("show");
})
}: null
dropdownmenucli()
In Laravel 8 app which uses vuejs and jquery
I found wizard made with html like :
<div class="content__inner">
<div class="ccontainer overflow-hiddenn">
<!--multisteps-form-->
<div class="multisteps-form">
<div class="multisteps-form__progress">
<button
class="multisteps-form__progress-btn js-active"
type="button"
title="Add Project Info"
>
Project Info
</button>
<button
class="multisteps-form__progress-btn"
type="button"
title="Add Product"
>
Product Details 22222
</button>
<button
class="multisteps-form__progress-btn"
type="button"
title="Project Budget & Diagram"
>
Project Budget & Diagram
</button>
<button
class="multisteps-form__progress-btn"
type="button"
title="Video & Website Link"
>
Video & Website Link
</button>
</div>
<form class="multisteps-form__form">
<!--single form panel-->
<div
class="multisteps-form__panel shadow p-4 rounded bg-white js-active"
data-animation="scaleIn"
>
<!-- <h3 class="multisteps-form__title">Your User Info</h3> -->
<div class="multisteps-form__content">
<div class="row">
<div class="col-xl-4">
<div class="submit-field">
<h5>
Project Name
<span>*</span>
</h5>
<input
type="text"
class="with-border"
id="name_project"
v-model="project.name"
/>
</div>
</div>
<div class="col-xl-4">
<div class="submit-field">
<h5>
Choose Categories
<span>*</span>
</h5>
<b-form-select
class="tzselectpicker"
v-model="project.category"
:options="project_category"
></b-form-select>
</div>
</div>
and inited js function
setStepForm() {
//DOM elements
const DOMstrings = {
stepsBtnClass: "multisteps-form__progress-btn",
stepsBtns: document.querySelectorAll(
`.multisteps-form__progress-btn`
),
stepsBar: document.querySelector(".multisteps-form__progress"),
stepsForm: document.querySelector(".multisteps-form__form"),
stepsFormTextareas: document.querySelectorAll(
".multisteps-form__textarea"
),
stepFormPanelClass: "multisteps-form__panel",
stepFormPanels: document.querySelectorAll(
".multisteps-form__panel"
),
stepPrevBtnClass: "js-btn-prev",
stepNextBtnClass: "js-btn-next"
};
console.log(" setStepForm DOMstrings::");
console.log(DOMstrings);
//remove class from a set of items
const removeClasses = (elemSet, className) => {
elemSet.forEach(elem => {
elem.classList.remove(className);
});
};
//return exect parent node of the element
const findParent = (elem, parentClass) => {
let currentNode = elem;
while (!currentNode.classList.contains(parentClass)) {
currentNode = currentNode.parentNode;
}
return currentNode;
};
//get active button step number
const getActiveStep = elem => {
return Array.from(DOMstrings.stepsBtns).indexOf(elem);
};
//set all steps before clicked (and clicked too) to active
const setActiveStep = activeStepNum => {
//remove active state from all the state
removeClasses(DOMstrings.stepsBtns, "js-active");
//set picked items to active
DOMstrings.stepsBtns.forEach((elem, index) => {
if (index <= activeStepNum) {
elem.classList.add("js-active");
}
});
};
//get active panel
const getActivePanel = () => {
let activePanel;
DOMstrings.stepFormPanels.forEach(elem => {
if (elem.classList.contains("js-active")) {
activePanel = elem;
}
});
return activePanel;
};
//open active panel (and close unactive panels)
const setActivePanel = activePanelNum => {
//remove active class from all the panels
removeClasses(DOMstrings.stepFormPanels, "js-active");
//show active panel
DOMstrings.stepFormPanels.forEach((elem, index) => {
if (index === activePanelNum) {
elem.classList.add("js-active");
setFormHeight(elem);
}
});
};
//set form height equal to current panel height
const formHeight = activePanel => {
const activePanelHeight = activePanel.offsetHeight;
DOMstrings.stepsForm.style.height = `${activePanelHeight}px`;
};
const setFormHeight = () => {
const activePanel = getActivePanel();
formHeight(activePanel);
};
//STEPS BAR CLICK FUNCTION
DOMstrings.stepsBar.addEventListener("click", e => {
//check if click target is a step button
const eventTarget = e.target;
if (
!eventTarget.classList.contains(
`${DOMstrings.stepsBtnClass}`
)
) {
return;
}
//get active button step number
const activeStep = getActiveStep(eventTarget);
//set all steps before clicked (and clicked too) to active
setActiveStep(activeStep);
//open active panel
setActivePanel(activeStep);
});
//PREV/NEXT BTNS CLICK
DOMstrings.stepsForm.addEventListener("click", e => {
const eventTarget = e.target;
//check if we clicked on `PREV` or NEXT` buttons
if (
!(
eventTarget.classList.contains(
`${DOMstrings.stepPrevBtnClass}`
) ||
eventTarget.classList.contains(
`${DOMstrings.stepNextBtnClass}`
)
)
) {
return;
}
//find active panel
const activePanel = findParent(
eventTarget,
`${DOMstrings.stepFormPanelClass}`
);
let activePanelNum = Array.from(
DOMstrings.stepFormPanels
).indexOf(activePanel);
//set active step and active panel onclick
if (
eventTarget.classList.contains(
`${DOMstrings.stepPrevBtnClass}`
)
) {
activePanelNum--;
} else {
activePanelNum++;
}
setActiveStep(activePanelNum);
setActivePanel(activePanelNum);
setTimeout(() => {
var body = $(".dashboard-content-container");
body.stop().animate(
{ scrollTop: 0 },
500,
"swing",
function() {}
);
}, 100);
});
setTimeout(() => {
setFormHeight();
}, 500);
//SETTING PROPER FORM HEIGHT ONLOAD
window.addEventListener("load", setFormHeight, false);
//SETTING PROPER FORM HEIGHT ONRESIZE
window.addEventListener("resize", setFormHeight, false);
//changing animation via animation select !!!YOU DON'T NEED THIS CODE (if you want to change animation type, just change form panels data-attr)
const setAnimationType = newType => {
DOMstrings.stepFormPanels.forEach(elem => {
elem.dataset.animation = newType;
});
};
//selector onchange - changing animation
const animationSelect = document.querySelector(
".pick-animation__select"
);
if (animationSelect != null) {
animationSelect.addEventListener("change", () => {
const newAnimationType = animationSelect.value;
setAnimationType(newAnimationType);
});
}
},
By clicking on "Next" button next step is opened, but I need to validate inputs before moving to next step.
Please any hints how can I make validation here ?
Also is it some library? I searched in net but drowned...
Thanks!
Each wizard view send wizard position in ajax.In backend based on wizard position validate fields .since you know which and all field exist in each wizard view.
For example consider you have 3 wizard steps.
Step 1 has 3 input fields
Step 2 has 2 input fields
Step 3 has 1 input fields
Suppose if you send current step is 1 then you can only validate those fields.
$validations=[
'step1'=>[
//field validation array
],
'step3'=>[
//field validation array
],
'step3'=>[
//field validation array
],
]
then based on request wizard step you can easily fetch validation rules
Validation::make($validations[$request->step]);
Or you can make all fields validate only if exists in the request
How can I manipulate CSS and read text value and save it into variable when clicking on the button. when I click on the button using jquery how can I add a CSS to the button such as class="btn-n-active".
How to make sure that only one button is selected while switching on different buttons and that button should have active CSS
I was trying to just read the single value from the options, just a single selection.
<p>
<button onclick="myFunction()" class="btn-n">DOG</button>
<button onclick="myFunction()" class="btn-n">CAT</button>
<button onclick="myFunction()" class="btn-n">LION</button>
<button onclick="myFunction()" class="btn-n">PIG</button>
</p>
const myFunction = () => {
}
It's like a quiz system where I just want to read a single value. I am not able to apply the logic
There are a bunch of options to do this. Below you will see 3 of them.
The idea is to select all buttons and remove the active class and then add it to the button you clicked on.
My jquery is a bit rusty but I suggest you use just javaScript for such a simple request
const myFunction = (event) => {
const clickedElem = event.target
const allBtns = document.querySelectorAll('.btn-n')
allBtns.forEach(btn => btn.classList.remove("btn-n-active"))
clickedElem.classList.add("btn-n-active")
}
// option 2 without adding function in html
/* const allBtns = document.querySelectorAll('.btn-n')
allBtns.forEach(btn => btn.onclick = () => {
allBtns.forEach(btn => btn.classList.remove("btn-n-active"))
btn.classList.add("btn-n-active")
}) */
//option3 simple jQuery
/* const allBtns = $('.btn-n');
allBtns.click(function() {
$(this).addClass("btn-n-active")
allBtns.not(this).removeClass("btn-n-active")
}) */
const submit = () => {
const selectedText = document.querySelector(".btn-n-active") ? document.querySelector(".btn-n-active").innerText : 'Please select one'
console.log(selectedText)
}
.btn-n-active {
background: red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>
<button onclick="myFunction(event)" class="btn-n">DOG</button>
<button onclick="myFunction(event)" class="btn-n">CAT</button>
<button onclick="myFunction(event)" class="btn-n">LION</button>
<button onclick="myFunction(event)" class="btn-n">PIG</button>
</p>
<button onclick="submit()">Click to see selected text</button>
You can find the selected answer button having the active class using the hasClass('btn-n-active')
$("button").click(function(){
$("button").removeClass("btn-n-active"); // Remove other active class
$(this).addClass("btn-n-active"); // Add active class to the clicked button
});
const myFunction = () => {
var selectedButtonText = $("button").hasClass("btn-n-active").html();
console.log("Selected answer: " + selectedButtonText);
}
I have the following element with onclick event that will color the clicked paragraph to red if user clicked on:-
<p
onClick={(e)=> e.currentTarget.style.color = "red"}
>
Click here
</p>
<p
onClick={(e)=> e.currentTarget.style.color = "red"}
>
Another Paragraph
</p>
<p
onClick={(e)=> e.currentTarget.style.color = "red"}
>
Another Paragraph
</p>
How can reset the color back to it original black color if user clicked else where on the page or clicked on another paragraph.
You can write an eventhandler for the <body> element. Click events 'bubbles' up to the <body> if they're not cancelled. You should cancel your events, so they don't 'bubble' up to the <body>:
<p onClick={(e)=> e.currentTarget.style.color = "red"; e.stopPropagation();}>
Click here
</p>
Now just set the color of all <p> elements:
<body onClick = {() => e.target.nodeName == "DIV" && (e.target.style.color = "black");}>
You really shouldn't be modifying the DOM directly from a React app. Use state instead:
function Paragraph (props) {
const [selected, setSelected] = React.useState();
const style = selected ? { color: red } : undefined;
return (
<p {...props} style={style} />
)
}
To reset it when the user clicks elsewhere, you could add an event listener to document.body while it's in the selected state. Something like this:
function Paragraph (props) {
const [selected, setSelected] = React.useState();
const style = selected ? { color: red } : undefined;
React.useEffect(() => {
if (selected) {
// you'd probably want to check to see if the click target
// is the current element; omitted here for simplicity
const onClick = () => setSelected(false);
document.body.addEventListener('click', onClick);
// remove the listener on unmount or when selected state changes
return () => document.body.removeEventListener('click', onClick);
}
}, [selected])
return (
<p {...props} style={style} />
)
}
Even better, use a className instead of an inline style:
<p {...props} className={selected ? 'selected' : ''} />
.selected { color: red; }
You can use something else then classes. Also keep in mind this way you have event click on all elements on page, so if you need it later just expand this...
Also this can be re-written in many ways to suit the needs.
const click = document.querySelectorAll(".click");
[...document.querySelectorAll('body')].forEach(el => {
el.addEventListener('click', event => {
if (event.target.className.includes("click") === true) {
click.forEach(p => {
p.style.color = "black";
})
event.target.style.color = "red";
} else {
click.forEach(p => {
p.style.color = "black";
})
}
})
})
div {
width: 100% height:100%
}
<div>test div
<p class="click"> dont Click here
</p>
test div1
</div>
<p class="click"> dont Click here
</p>
<div>test div2
<p class="click"> dont Click here
</p>
</div>
I wrote toggle script in ES6/vanilla JS. The intended functionality is super simple, you click on the toggle div and it adds an active class to another div that matches the toggle div's data-toggle property. In my toggle div, I need there to be both text and an image. It works great when you click on the text within the div, but when you click on the image within the div, the toggle is not firing. Is there something specific I need to do to include all of the children within the div?
For some reason, I can't even get this working via this code snippet editor, but it is working in my project.
const setActive = (toggles, panels, id) => {
let activePanel = panels.filter(panel => panel.getAttribute('data-toggle') == id)
let activeToggle = toggles.filter(toggle => toggle.getAttribute('data-toggle') == id)
activePanel.forEach(panel => panel.classList.add('active'))
activeToggle.forEach(toggle => toggle.classList.add('active'))
}
const removeActive = (nodes) => {
nodes.forEach(node => node.classList.remove('active'))
}
const handler = (event) => {
event.preventDefault()
let id = event.target.getAttribute('data-toggle')
let panels = Array(...document.querySelectorAll('.js-toggle-panel'))
let toggles = Array(...document.querySelectorAll('.js-toggle'))
removeActive(panels)
removeActive(toggles)
setActive(toggles, panels, id)
}
let toggles = Array(...document.querySelectorAll('.js-toggle'))
toggles.forEach(toggle => toggle.addEventListener('click', handler))
.toggle-panel {
display: none;
}
.toggle-panel .active {
display: block;
}
<div class="js-toggle toggle" data-toggle="toggle-1">
<img src="https://via.placeholder.com/50"> First toggle
</div>
<div class="js-toggle toggle" data-toggle="toggle-2">
Second toggle
</div>
<div class="js-toggle-panel toggle-panel" data-toggle="toggle-1">
<h1>Toggle 1</h1>
</div>
<div class="js-toggle-panel toggle-panel" data-toggle="toggle-2">
<h1>Second toggle!</h1>
</div>
I changed two things that I believe will resolve your issue:
I changed the selector .toggle-panel .active to .toggle-panel.active-- without that, even in the cases where the JS was working as you intended nothing was actually be made visible.
I moved your code from using event.target to event.currentTarget -- the former always points to the clicked element, whereas the latter refers to the element on which the listener has been placed.
See the snippet below.
const setActive = (toggles, panels, id) => {
let activePanel = panels.filter(panel => panel.getAttribute('data-toggle') == id)
let activeToggle = toggles.filter(toggle => toggle.getAttribute('data-toggle') == id)
activePanel.forEach(panel => panel.classList.add('active'))
activeToggle.forEach(toggle => toggle.classList.add('active'))
}
const removeActive = (nodes) => {
nodes.forEach(node => node.classList.remove('active'))
}
const handler = (event) => {
event.preventDefault()
let id = event.currentTarget.getAttribute('data-toggle')
let panels = Array(...document.querySelectorAll('.js-toggle-panel'))
let toggles = Array(...document.querySelectorAll('.js-toggle'))
removeActive(panels)
removeActive(toggles)
setActive(toggles, panels, id)
}
let toggles = Array(...document.querySelectorAll('.js-toggle'))
toggles.forEach(toggle => toggle.addEventListener('click', handler))
.toggle-panel {
display: none;
}
.toggle-panel.active {
display: block;
}
<div class="js-toggle toggle" data-toggle="toggle-1">
<img src="https://via.placeholder.com/50"> First toggle
</div>
<div class="js-toggle toggle" data-toggle="toggle-2">
Second toggle
</div>
<div class="js-toggle-panel toggle-panel" data-toggle="toggle-1">
<h1>Toggle 1</h1>
</div>
<div class="js-toggle-panel toggle-panel" data-toggle="toggle-2">
<h1>Second toggle!</h1>
</div>
Instead of event.target you should use event.currentTarget in your handler function to return node to which event listener is attached. event.target is returning <img> node, not <div> with data-toggle in your case.