Close modal on esc press (pure JS) - javascript

I'm trying to get my modal to close (have a class that sets it to display: block removed) on an esc press. Here's what I tried (which doesn't work and breaks the rest of my code):
if (modal.classList.contains('modal-visible')) {
document.addEventListener('keypress', function(e) {
let keyCode = e.keyCode;
if (keyCode === '27') {
modal.classList.remove('modal-visible');
}
}
Here's the other code from my JS file for the modal:
const modal = document.getElementById('myModal');
const closeIcon = document.querySelector('.close');
// When called, adds class that sets modal to display: block when player reaches water
function bringUpModal() {
modal.classList.add('modal-visible');
}
// Closes modal (adding class that sets it back to display: none) upon user's clicking its close icon
closeIcon.addEventListener('click', function() {
modal.classList.remove('modal-visible');
});
// Opens modal when player reaches water
Player.prototype.update = function(dt) {
if (this.y === 25) {
bringUpModal();
this.y = 400;
}
};
Doubt this is needed, but just in case, here's my CSS for the modal as well:
.modal {
display: none;
width: 33%;
height: 30%;
margin: 0 auto;
background-color: #f1f0f0;
border: 1px solid #c5c4c4;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/* Added by function bringUpModal() */
.modal-visible {
display: block;
}
.modal-content {
margin: 0 auto;
padding: 30px;
width: 80%;
display: flex;
flex-direction: column;
justify-content: center;
}

Add an event listener for the modal when the page loads, not if the modal is visible. Also, use the keydown event instead of keypress as in some browsers the keypress event is only fired if the key outputs a character
.modal {
display: none;
width: 33%;
height: 30%;
margin: 0 auto;
background-color: #f1f0f0;
border: 1px solid #c5c4c4;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/* Added by function bringUpModal() */
.modal-visible {
display: block;
}
<div id="modal" class="modal modal-visible" style="border: 2px solid black; width: 100px; height: 100px;"></div>
<script>
var modal = document.getElementById("modal");
document.addEventListener('keydown', function(e) {
let keyCode = e.keyCode;
document.getElementById("result").innerHTML = "Key Code: "+keyCode+"<br/> Key: "+e.key+"<br/>";
if (keyCode === 27) {//keycode is an Integer, not a String
modal.classList.remove('modal-visible');
document.getElementById("result").innerHTML += "Escape key pressed. Modal hidden.";
}
});
</script>
<div style="width: 100%; text-align: center;">
<span id="result"></span>
</div>

If you only create the event listener if the modal is visible, it will simply never be created. Making the modal visible afterward will not re-execute your code. The if check has already occurred, already failed, and the event listener for keydown has already not been created. At no point will it be created.
var x = 2;
if (x === 1) {
alert('yes');
}
x = 1;
In the above example, the alert never happens, even though x eventually becomes 1. Similarly, your event listener never gets created.
At the same time, the keyCode is an integer, not a string. You will want to use 27 instead of '27'.

Related

When to Call JavaScript Toggle Function?

I have a drop down menu I need to make appear and disappear using pure JavaScript (no libraries/jQuery). Thus I am developing a toggle function. However despite trying several approaches, nothing seems to work. My current idea is to create a variable to hold the state of the menu (open or closed). Once the display of the menu changes from "none" to "block", the variable should change from "closed" to "open". Then an event listener would be added to the body element so when anything is clicked, the menu closes (i.e. the display property is changed back to "none").
Unfortunately the above doesn't seem work. When I put the If/else block outside of an event listener it fires when the page loads, but not when the menuToggle variable changes. If I put it or a function inside the menuPlaceholder event listener the menu won't open, probably due to the open and close code being called basically at the same time.
Clearly I am missing something, probably related to program control or function calling. Does anyone have any insights?
The code I am working with is below. Note the alert functions peppered throughout the code are for testing purposes only.
//Puts IDs for search preference selection box into variables
var menuPlaceholder = document.getElementById('searchSelection');
var menuDisplay = document.getElementById('searchOptions');
var boxLabel = document.getElementById('searchLabel');
//Puts IDs for text input box and submission into variables
var searchBoxPlaceholder = document.getElementById('searchInput');
var searchInput = document.getElementById('searchBox');
var submitButton = document.getElementById('submit');
//Adds class to each search option and puts ID of hidde field into variable
var searchPrefSubmission = document.getElementsByClassName('buttonSearch');
var hiddenInput = document.getElementById('searchChoice');
//Global variable to indicate whether searchOptions menu is opened or closed
var menuToggle = "closed";
//Closes element when one clicks outside of it.
function hideOnClickOutside(element) {
const outsideClickListener = event => {
if (!element.contains(event.target) && isVisible(element)) { // or use: event.target.closest(selector) === null
element.style.display = 'none'
removeClickListener()
}
}
const removeClickListener = () => {
document.removeEventListener('click', outsideClickListener)
}
document.addEventListener('click', outsideClickListener)
}
const isVisible = elem => !!elem && !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length )
//When the placeholder box is clicked, the option menu appears
menuPlaceholder.addEventListener('click', function (event){
menuDisplay.style.display = "block";
menuToggle = "open";
//Add click event to searchPref buttons
for (i = 0; i < searchPrefSubmission.length; i++) {
//Assigns value of the button to both the hidden input field and the placeholder box
searchPrefSubmission[i].addEventListener('click', function(event) {
hiddenInput.value=this.value;
boxLabel.innerHTML = this.value;
menuDisplay.style.display = "none";
menuPlaceholder.style.display = "inline-block";
});
}
});
//This code causes the text input box of the search form to appear when the background box is clicked
searchBoxPlaceholder.addEventListener('click', function(event){
searchInput.style.display = "inline";
submitButton.style.display = "inline";
//hideOnClickOutside(menuDisplay);
});
if (menuToggle == "open"){
document.body.addEventListener('click', function(event){
alert('Foo!');
})
}else{
alert('Boo!');
}
/*function toggleMenu () {
//menuDisplay.style.display = "none";
alert('Boo!');
menuToggle = "closed";
}*/
body {
font-family:Montserrat, sans-serif;
}
#searchOptionPlaceholder {
display: inline-block;
}
#searchSelection {
padding: 10px 20px;
margin-right: 10px;
background-color: #F0F3F5;
display: inline-block;
color: #000000;
width: 140px;
max-width: 200px;
max-height: 35px;
border: 2px solid black;
vertical-align: middle;
}
#searchSelection img {
float: right;
}
#searchLabel {
display: inline-block;
padding-top: 10px;
vertical-align: top;
}
#searchOptions {
display: none;
background-color: #F0F3F5;
position: absolute;
z-index: 2;
}
#searchOptions ul {
background-color: #F0F3F5;
padding: 5px;
}
#searchOptions li {
list-style-type: none;
border-bottom: 2px solid black;
}
#searchOptions li:hover {
background-color: #706868;
color: #ffffff;
}
.buttonSearch {
background-color: transparent;
border: none;
padding: 10px;
font-size: 14px;
}
.searchSubHeading {
font-size: 12px;
}
#searchInput {
display: inline-block;
background-color: #F0F3F5;
padding: 10px 100px;
position: relative;
top: 0px;
max-width: 350px;
border: 2px solid black;
vertical-align: middle;
}
#searchInput img {
position: relative;
left: 80px;
}
#searchBox {
display: none;
width: 80%;
background-color: #F0F3F5;
border: none;
font-size: 1.5em;
position: relative;
right: 50px;
vertical-align: middle;
}
#submit {
border: none;
background-image: url('https://library.domains.skidmore.edu/search/magnifyingGlass.png');
background-repeat: no-repeat;
background-size: contain;
width: 50px;
height: 30px;
position: relative;
right: -80px;
vertical-align: middle;
}
#otherLinks {
margin-top: 10px;
}
#otherLinks a{
color: #000000;
}
#otherLinks a:hover{
color: #006a52;
}
<h1>Library Search</h1>
<form method="post" action="https://library.domains.skidmore.edu/search/searchBox.php" id="librarySearch">
<div id="searchSelection"><span id="searchLabel">Catalog</span><img src="down.png" height="30px" width="30px" /></div>
<div id="searchOptions">
<ul>
<li><button type="button" name="searchPref" value="Catalog" class="buttonSearch">Catalog<br /><br /><span class="searchSubHeading">Search books and DVDs</span></button></li>
<li><button type="button" name="searchPref" value="SearchMore" class="buttonSearch">SearchMore<br /><br /><span class="searchSubHeading">Search everything</span></button></li>
<li><button type="button" name="searchPref" value="Journals" class="buttonSearch">Journals<br /><br /><span class="searchSubHeading">Search journals</span></button></li>
</ul>
</div>
<div id="searchInput">
<input type="hidden" id="searchChoice" name="searchPref" value="catalog" />
<input type="search" id="searchBox" size="60" name="searchText" placeholder="Search our holdings"/><button type="submit" id="submit"></button></div>
<div id="otherLinks">Advanced Catalog Search | WorldCat | eBooks</div>
</form>
Some issues:
Adding event listeners within an event listener is in most cases a code smell: this will add those inner listeners each time the outer event is triggered. Those listeners remain attached, and so they accumulate. So, attach all event handlers in the top-level script, i.e. on page load, and then never again.
The if ... else at the end will execute on page load, and then never again. So the value of menuToggle is guaranteed to be "closed". You need to put that if...else switch inside the handler, so that it executes every time the event triggers, at which time the menuToggle variable will possibly have a modified value.
The body element does not stretch (by default) over the whole window. If you want to detect a click anywhere on the page, you should attach the listener on the document element itself, not on document.body.
When the click on the menu placeholder is handled, you should avoid that this event "bubbles" up the DOM tree up to the document, because there you have the other handler that wants to hide the menu again. You can do this with event.stopPropagation().
The global variable is not absolutely necessary, but if you use it, then I would call it menuVisible and give it a boolean value: false at first, and possibly true later.
For actually toggling the menu, I would create a function, which takes the desired visibility (false or true) as argument, and then performs the toggle.
Do not use undeclared variables, like the for loop variable i. Define it with let.
Here is your code with those changes implemented. Of course, there is still a lot that could be improved, but I believe that goes beyond the scope of this question:
var menuPlaceholder = document.getElementById('searchSelection');
var menuDisplay = document.getElementById('searchOptions');
var boxLabel = document.getElementById('searchLabel');
var searchBoxPlaceholder = document.getElementById('searchInput');
var searchInput = document.getElementById('searchBox');
var submitButton = document.getElementById('submit');
var searchPrefSubmission = document.getElementsByClassName('buttonSearch');
var hiddenInput = document.getElementById('searchChoice');
// Changed name and type of global variable:
var menuVisible = false;
// Removed some functions ...
menuPlaceholder.addEventListener('click', function (event){
// Use new function for actually setting the visibility
toggleMenu(!menuVisible);
// Avoid that click event bubbles up to the document level
event.stopPropagation();
});
// Add these event handlers on page load, not within another handler
// Define loop variable with let
for (let i = 0; i < searchPrefSubmission.length; i++) {
//Assigns value of the button to both the hidden input field and the placeholder box
searchPrefSubmission[i].addEventListener('click', function(event) {
hiddenInput.value = this.value;
boxLabel.innerHTML = this.value;
// Use the new function for setting the visibility
toggleMenu(false);
menuPlaceholder.style.display = "inline-block";
});
}
searchBoxPlaceholder.addEventListener('click', function(event){
searchInput.style.display = "inline";
submitButton.style.display = "inline";
});
// Bind handler on document itself, and call new function
document.addEventListener('click', function(event) {
toggleMenu(false);
});
// new function to perform the toggle
function toggleMenu(show) {
menuDisplay.style.display = show ? "block" : "none";
menuVisible = show;
}
body {
font-family:Montserrat, sans-serif;
}
#searchOptionPlaceholder {
display: inline-block;
}
#searchSelection {
padding: 10px 20px;
margin-right: 10px;
background-color: #F0F3F5;
display: inline-block;
color: #000000;
width: 140px;
max-width: 200px;
max-height: 35px;
border: 2px solid black;
vertical-align: middle;
}
#searchSelection img {
float: right;
}
#searchLabel {
display: inline-block;
padding-top: 10px;
vertical-align: top;
}
#searchOptions {
display: none;
background-color: #F0F3F5;
position: absolute;
z-index: 2;
}
#searchOptions ul {
background-color: #F0F3F5;
padding: 5px;
}
#searchOptions li {
list-style-type: none;
border-bottom: 2px solid black;
}
#searchOptions li:hover {
background-color: #706868;
color: #ffffff;
}
.buttonSearch {
background-color: transparent;
border: none;
padding: 10px;
font-size: 14px;
}
.searchSubHeading {
font-size: 12px;
}
#searchInput {
display: inline-block;
background-color: #F0F3F5;
padding: 10px 100px;
position: relative;
top: 0px;
max-width: 350px;
border: 2px solid black;
vertical-align: middle;
}
#searchInput img {
position: relative;
left: 80px;
}
#searchBox {
display: none;
width: 80%;
background-color: #F0F3F5;
border: none;
font-size: 1.5em;
position: relative;
right: 50px;
vertical-align: middle;
}
#submit {
border: none;
background-image: url('https://library.domains.skidmore.edu/search/magnifyingGlass.png');
background-repeat: no-repeat;
background-size: contain;
width: 50px;
height: 30px;
position: relative;
right: -80px;
vertical-align: middle;
}
#otherLinks {
margin-top: 10px;
}
#otherLinks a{
color: #000000;
}
#otherLinks a:hover{
color: #006a52;
}
<h1>Library Search</h1>
<form method="post" action="https://library.domains.skidmore.edu/search/searchBox.php" id="librarySearch">
<div id="searchSelection">
<span id="searchLabel">Catalog</span>
<img src="down.png" height="30px" width="30px" />
</div>
<div id="searchOptions">
<ul>
<li>
<button type="button" name="searchPref" value="Catalog" class="buttonSearch">
Catalog<br /><br /><span class="searchSubHeading">Search books and DVDs</span>
</button>
</li>
<li>
<button type="button" name="searchPref" value="SearchMore" class="buttonSearch">
SearchMore<br /><br /><span class="searchSubHeading">Search everything</span>
</button>
</li>
<li>
<button type="button" name="searchPref" value="Journals" class="buttonSearch">
Journals<br /><br /><span class="searchSubHeading">Search journals</span>
</button>
</li>
</ul>
</div>
<div id="searchInput">
<input type="hidden" id="searchChoice" name="searchPref" value="catalog" />
<input type="search" id="searchBox" size="60" name="searchText" placeholder="Search our holdings"/>
<button type="submit" id="submit"></button>
</div>
<div id="otherLinks">
Advanced Catalog Search |
WorldCat |
eBooks
</div>
</form>

Close div with click outside (parent) [duplicate]

This question already has answers here:
How do I detect a click outside an element?
(91 answers)
Closed 4 years ago.
This is not a new problem on stackoverflow, but I've tried everything without success.
I have a "popup" created with two divs. The parent ist the background and the child is the popup content. I want to hide the popup when the user clicks on the background (the parent).
It sounds extremly easy also for me but I can't achieve that.
This is my code and what I tried (it works exacly at the opposite way as I want):
let content = document.querySelector('.popup-content');
let popup = document.querySelector('.popup');
let button = document.querySelector('button');
button.onclick = () => {
popup.style.display = 'block';
content.onclick = e => {
if(e.target !== this) {
popup.style.display = 'none';
}
}
}
.popup {
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: hidden;
background-color: rgb(0,0,0);
background-color: rgba(0,0,0,0.4);
display: none;
}
.popup-content {
background-color: #fff;
margin: 10% auto;
padding: 20px;
border: 1px solid #888;
width: 25%;
min-width: 470px;
border-radius: 4px;
}
<button>
Open Popup
</button>
<div class="popup">
<div class="popup-content">
<h3>Popup Title</h3>
<p>Popup Text</p>
</div>
</div>
Can somebody help me?
You should separate both events and attach the click to the window so you can detect the clicks outside of popup-content like :
let content = document.querySelector('.popup-content');
let popup = document.querySelector('.popup');
let button = document.querySelector('button');
button.onclick = () => {
popup.style.display = 'block';
}
window.onclick = e => {
if (e.target === popup) {
popup.style.display = 'none';
}
}
.popup {
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: hidden;
background-color: rgb(0, 0, 0);
background-color: rgba(0, 0, 0, 0.4);
display: none;
}
.popup-content {
background-color: #fff;
margin: 10% auto;
padding: 20px;
border: 1px solid #888;
width: 25%;
min-width: 470px;
border-radius: 4px;
}
<button>
Open Popup
</button>
<div class="popup">
<div class="popup-content">
<h3>Popup Title</h3>
<p>Popup Text</p>
</div>
</div>
you can try something like this :
instead of adding the EventListner to close the div on the button you need to add it on the document instead. and test on target if is not your button just like this :
let popup = document.querySelector('.popup');
let button = document.querySelector('button');
// Event that hide the popin if the click happen out popin
function closeHandler(e) {
if (e.target !== popup) {
// We remove the event for better perfermance
removeCloseListner();
// We hide the popin
popup.style.display = 'none';
}
}
// Call this function when you open your popin popin
function addCloseLitnerToDocument() {
document.addEventListener("click", closeHandler);
}
function removeCloseListner() {
document.removeEventListener("click", closeHandler)
}
// Add listner to Open Popin
button.onclick = (e) => {
e.preventDefault();
e.stopPropagation();
// when popin is open
// Add listner to the document
// And show the popin
popup.style.display = 'block';
addCloseLitnerToDocument();
}

How to add dynamic listener and get value of target

I've created a custom dropdown and would like to get the text content of the clicked element within.
Dropdown elements are created dynamically as are the event listeners but the listeners seem not to be working correctly.
Dropdown example:
I can see the listeners on each div within the dev tools.
Event listener of child div:
The first div in the dropdown fills the input with it's value but the others do not.
(function() {
let departments = ['Accounting', 'Human Resources', 'IT', 'Warehouse'];
let element = document.getElementById('dd-Department');
departments.forEach(v => {
let div = document.createElement('div');
div.appendChild(document.createTextNode(v));
div.addEventListener('click', () => {
element.parentNode.querySelector('input').value = v;
});
element.appendChild(div);
});
})();
.form-question {
display: flex;
flex-direction: column;
justify-content: center;
margin: 0 0 3rem;
min-height: 3rem;
}
.form-question__title {
color: #342357;
font-size: 1.5rem;
padding: 1rem;
}
.input-container {
border-bottom: solid 2px #333333;
position: relative;
}
input[readonly] {
cursor: pointer;
}
.input-container input {
border: none;
box-sizing: border-box;
outline: 0;
padding: .75rem;
position: relative;
width: 100%;
}
.input-container:focus-within .dropdown {
transform: scaleY(1);
}
.dropdown {
background: #ffffff;
box-shadow: 0 5px 12px #333333;
left: 0;
max-height: 300px;
overflow-y: auto;
padding: 0;
position: absolute;
right: 0;
top: calc(100% + 2px);
transform: scaleY(0);
transform-origin: top;
transition: transform .3s;
z-index: 10;
}
.dropdown div {
border-bottom: 2px solid #777777;
cursor: pointer;
padding: 8px;
z-index: 20;
}
.dropdown div:hover {
background: #dddddd;
font-weight: 800;
}
<div class="form-question">
<div class="form-question__title">
<span>Department</span>
</div>
<div class="form-question--dropdown input-container">
<input type="text" name="Department" readonly="readonly"></input>
<div id="dd-Department" class="dropdown"></div>
</div>
</div>
I also took a stab at event delegation, but could not get the text content of the clicked div. The target is the parent of the intended div, thus the text content was all child values combined.
let element = document.getElementById('dd-Department');
element.addEventListener('click', e => {
if (e.target && e.target.classList.contains('dropdown')) {
e.target.parentNode.parentNode.querySelector('input').value = e.target.textContent;
}
}, true);
Event Delegation on click of child div:
Am I missing something here?
UPDATE
Thank you #dawn for pointing out css as the problem.
I've worked around this by changing
.input-container:focus-within .dropdown
to
.input-container.active .dropdown
and adding the active class with javascript.
document.querySelectorAll('.input-container').forEach(v => {
v.onclick = () => v.classList.toggle('active');
});
Issue now is that on click of anything other than the input-container the dropdown is still active.
The following works but feels like a hack.
document.querySelectorAll('.input-container').forEach(v => {
v.addEventListener('focus', () => v.classList.add('active'), true);
v.addEventListener('blur', () => setTimeout(() => v.classList.remove('active'), 75), true);
});
Are there more elegant solutions?
This situation is a problem with css,When you click on the div,The first thing that triggers is "transform: scaleY(0)" and the ".dropdown" has invisible,so Cannot trigger click event.
Don't use input:focus-within to control the Visibilityof the drop-down box, because when you click the drop-down box, the input has lost focus.

How to induce some function when onmouseleave and also click the left mouse button?

I have got code like below:
Now I would like to add functionality that increase the counter not only when I leave the box/square, BUT ALSO click the left mouse button outside the box/square. So the counter will be increasing only when the mouse leave the box/square and also click outside of the box/square.
var counter = 0;
function myLeaveFunction() {
document.getElementById("demo").innerHTML = counter += 1;
}
div {
width: 100px;
height: 100px;
border: 1px solid black;
margin: 10px;
float: left;
padding: 30px;
text-align: center;
background-color: lightgray;
}
<div onmouseleave="myLeaveFunction()">
<p>onmouseleave: <br> <span id="demo">Mouse over and leave me AND CLICK OUTSIDE THE BOX!</span></p>
</div>
Add a boolean to check if mouse had left the div and bind a click handler to the document:
var counter = 0;
var mouseLeft = false;
function myLeaveFunction() {
document.getElementById("demo").innerHTML = counter+=1;
mouseLeft = true;
}
function clickBody() {
if (mouseLeft == true)
document.getElementById("demo").innerHTML = counter+=1;
mouseLeft = false;
}
document.onclick = clickBody;
This example will add an event listener to the body when the mouse leaves the box and will increase the counter when a click event occurs. The new event listener is then removed:
var counter = 0;
function myLeaveFunction() {
document.body.addEventListener("click", myClickHandler);
function myClickHandler() {
document.getElementById("demo").innerHTML = counter += 1;
document.body.removeEventListener("click", myClickHandler);
}
}
body {
margin: 0;
height: 100vh;
width: 100%;
}
div {
width: 100px;
height: 100px;
border: 1px solid black;
margin: 10px;
float: left;
padding: 30px;
text-align: center;
background-color: lightgray;
}
<body>
<div onmouseleave="myLeaveFunction()" onclick="event.stopPropagation()">
<p>onmouseleave: <br> <span id="demo">Mouse over and leave me AND CLICK OUTSIDE THE BOX!</span></p>
</div>
</body>
JSFiddle if this doesn't work
Like this?
Once you left the box AND you click outside of it. The counter will be increased.
var showPopup = function (id) {
document.getElementById(id).style.display = "block";
}
var hidePopup = function (id) {
document.getElementById(id).style.display = "none";
}
// Button Click
document.getElementById('myButton').onclick = (ev) => {
showPopup('myPopup');
ev.stopPropagation(); // prevent immediate close (because button is "outside" too)
}
// Click outside to close popup
document.getElementsByTagName('body')[0].onclick = (ev) => {
let popup = document.getElementById('myPopup');
if( ev.path.indexOf(popup) == -1 ) { hidePopup('myPopup') }
};
hidePopup('myPopup');
body {
width: 100vw;
height: 100vh;
}
div {
width: 100px;
height: 100px;
border: 1px solid black;
padding: 30px;
text-align: center;
background-color: lightgray;
position: absolute;
margin: 10px;
display: none;
}
<div id='myPopup'>
<p>onmouseleave: <br> <span id="demo">Mouse over and leave me AND CLICK OUTSIDE THE BOX!</span></p>
</div>
<button id='myButton'>Show!</button>
Take a look
This may be helful too Bootstrap Modal

StopPropagation allowing click on parent

I have the following code where I have a label where I prevent the default action so that I can instead focus on the an editable span when it is clicked instead of an input. However, if the user clicks on the span, I want it to ignore the click event bound to the parent so I use stopPropagation.
However, it doesn't seem to work and the parent click event is still fired:
var $quantitySpan = $('.quantity-span'),
$quantityTextbox = $('.textbox'),
$quantityHolder = $('.product-checkbox__quantity');
$quantitySpan
.on('click', e => {
e.stopPropagation(); // I thought this would stop the bubbling up to the parents click event
console.log('span clicked');
})
.on('keyup', () => {
$quantityTextbox.val($quantitySpan.text());
})
.on('blur', () => {
const textVal = $quantitySpan.text();
if (isNaN(textVal) || textVal === '') {
$quantitySpan.text("0");
$quantityTextbox.val("0");
}
});
$quantityHolder.on('click', (e) => {
e.preventDefault();
console.log(e.target, e.currentTarget); // this seems to suggest that the target is the label that has been clicked allthough it changes the target to the input and not the span (even though I have prevented the default action of the label and stopped propagation on the span)
});
* {
box-sizing: border-box;
}
.product-checkbox__quantity {
display: block;
padding-top: 1rem;
}
.product-checkbox__quantity-holder {
margin-top: 0.5rem;
display: flex;
flex-direction: row;
border: 1px solid #c6c6c6;
background: #FFF;
border-radius: 5px;
padding: 1rem 1.25rem;
width: 100%;
overflow: hidden;
position: relative;
}
.product-checkbox__quantity-holder .off-screen {
position: fixed;
left: 105%;
top: 125%;
border: 0;
outline: 0;
}
.product-checkbox__quantity-holder .quantity-span {
outline: none;
flex-shrink: 1;
padding-right: 0.5em;
max-width: 80%;
white-space: nowrap;
overflow: hidden;
}
.product-checkbox__quantity-unit {
flex-grow: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label class="product-checkbox__quantity">
Quantity:
<br>
<span class="product-checkbox__quantity-holder">
<input type="text" name="Quantities[VARIANT2]" autocomplete="off" class="product-checkbox__quantity-input textbox off-screen" id="quantity-variant2" value="0" data-unit="m2" data-rule-required="true" data-msg-required="required" data-rule-integer="true" data-msg-integer="Integers only"><span class="quantity-span" contenteditable="true">0</span>
<span class="product-checkbox__quantity-unit">m<sup>2</sup></span>
</span>
<span class="field-validation-valid" data-valmsg-for="quantity-variant2" data-valmsg-replace="true"></span>
</label>
How do I change the above code so that when you click on the 0, it registers as a click on the span instead of on the label / input (or how do I see I have clicked the span in the label click event)
Weirdly, if you inspect the 0, it says that it is the span, so not sure why the target is changed to the input in the console.log
You also need to add preventDefault() together with stopPropagation().
$quantitySpan
.on('click', e => {
e.stopPropagation();
e.preventDefault();
console.log('span clicked');
})

Categories

Resources