When to Call JavaScript Toggle Function? - javascript

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>

Related

how to add button with editable title using jquery?

I have a simple section in which the user can add multiple buttons on click, I want these buttons names to be the editable meaning user can edit and save the button title as they wish.
Here is UI how it looks when use click add button
I want a user to be able to add button title by placing a mouse on enter button name.
When a user places a mouse on enter a button name a simple pop up text area will appear something like this.
$(document).ready(function() {
$('#btn').on('click', function() {
var buttonWithText = $("<div class='clickarea'>Enter button name</div>")
$(".main-container").append(buttonWithText);
})
})
.main-container {
height: 300px;
width: 400px;
background: red;
}
.clickarea {
height: 60px;
width: 50%;
/* margin: 20px; */
background: green;
display: flex;
justify-content: center;
align-items: center;
margin: 80px auto;
}
#btn {
cursor: pointer;
margin: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main-container">
</div>
<button id="btn">Add button</button>
For a very simple solution, you can use prompt:
$(document).ready(function() {
$('#btn').on('click', function() {
let text = prompt('enter button text:');
var buttonWithText = $("<div class='clickarea'>"+text+"</div>")
$(".main-container").append(buttonWithText);
})
})
.main-container {
height: 300px;
width: 400px;
background: red;
}
.clickarea {
height: 60px;
width: 50%;
/* margin: 20px; */
background: green;
display: flex;
justify-content: center;
align-items: center;
margin: 80px auto;
}
#btn {
cursor: pointer;
margin: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main-container">
</div>
<button id="btn">Add button</button>
If I understand correctly, you're desired functionality is something like below. You can achieve this by taking advantage of addEventListener and then creating a new button and adding it to the DOM on click:
EDIT:
I've updated my code based on your comment. I believe it now works according to the second scenario you have described. Let me know if this does not seem like the desired functionality.
function init() {
const buttonEl = document.querySelector('#button-el');
const buttonContainer = document.querySelector('#button-container');
const alertButtonText = e => alert(`You clicked: ${e.target.value}`);
const promptForText = e => {
const text = window.prompt('Enter button text');
if (text && text.trim().length) {
e.target.setAttribute('value', text);
e.target.removeEventListener('mouseover', promptForText);
e.target.addEventListener('click', alertButtonText);
}
}
buttonEl.addEventListener('click', e => {
const newButtonEl = document.createElement('input');
newButtonEl.setAttribute('type', 'button');
newButtonEl.addEventListener('mouseover', promptForText);
buttonContainer.appendChild(newButtonEl);
});
}
init();
#button-container>input {
height: 30px;
width: 40%;
background: green;
display: block;
align-items: center;
margin: 20px auto;
}
body {
background: red;
}
#button-el {
cursor: pointer;
margin: 20px;
}
<input id="button-el" type="button" value="Add button" />
<div id="button-container">
</div>

How to show an element only on click on it and and hide it on click on other elements?

Description: I created two buttons and two more elements (div & section).
When I click on button 1, div element will appear with background-color HotPink and/if at this moment i re-click on button 1, div element will disappear.
I also wrote a function for button 2 so that when i click on button 2, section element will appear with background-colour DarkGreen and at this moment when i click on button 2 again, section element will disappear.
I should mention that if i click on white space of body ( (document).click(event) ), both div and section elements will disapear.
Question: What function should I write to show div element when I click on button 1 and then I hide hide it when I click on button 2 or any other elements on my web page???
Demo
NOTE: I duplicated this question because I'm not interested to use any method like:
$(".button1").click(function(event){
event.stopPropagation();
if($(".div").css("display") == "none"){
$(".div").css("display","block");
$(".section").css("display","none");
}else{
$(".div").css("display","none");
}
});
$(".button2").click(function(event){
event.stopPropagation();
if($(".section").css("display") == "none"){
$(".section").css("display","block");
$(".div").css("display","none");
}else{
$(".section").css("display","none");
}
});
It would be better if you do a favour and suggest a better method instead of duplicating a line of code with different class name under different events (functions).
My codes:
HTML:
<button class="button1">
Show Div Element
</button>
<div class="div">
I am Div Element
</div>
<br><br>
<button class="button2">
Show Section Element
</button>
<section class="section">
I am Section Element
</section>
JQuery:
$(function(){
$(".button1").click(function(event){
event.stopPropagation();
if($(".div").css("display") == "none"){
$(".div").css("display","block");
}else{
$(".div").css("display","none");
}
});
$(".button2").click(function(event){
event.stopPropagation();
if($(".section").css("display") == "none"){
$(".section").css("display","block");
}else{
$(".section").css("display","none");
}
});
$(document).click(function(){
$(".div").css("display","none");
$(".section").css("display","none");
});
});
The easiest way would be to start .click functions for both button 1 & 2 with:
.css("display","none");
function hidding the other element, like this:
$(".button1").click(function(event){
$(".section").css("display","none");
event.stopPropagation();
if($(".div").css("display") == "none"){
$(".div").css("display","block");
}else{
$(".div").css("display","none");
}
});
$(".button2").click(function(event){
$(".div").css("display","none");
event.stopPropagation();
if($(".section").css("display") == "none"){
$(".section").css("display","block");
}else{
$(".section").css("display","none");
}
});
Solution without JQuery... But you can use it if you really want to.
const $ = document.querySelector.bind(document);
const $$ = document.querySelectorAll.bind(document);
$('.button1').addEventListener('click', ()=>{
toggle('div')
});
$('.button2').addEventListener('click', ()=>{
toggle('section')
});
function toggle(element){
if($('.show')){
Array.from($$('.show')).forEach((ele) => {
ele.classList.remove('show');
});
}
$(element).classList.add('show');
}
html, body {
background-color: #fafafa;
width: 100%;
height: 100%;
padding: 12px;
margin: 0;
}
.button1 {
background-color: pink;
position: relative;
display: inline-block;
padding: 8px;
border: none;
margin: 0 0 6px 0;
cursor: pointer;
}
.div {
background-color: hotpink;
display: none;
width: 160px;
height: 160px;
}
.button2 {
background-color: green;
position: relative;
display: inline-block;
padding: 8px;
color: white;
border: none;
margin: 0 0 6px 0;
cursor: pointer;
}
.section {
background-color: darkgreen;
display: none;
width: 160px;
height: 160px;
color: white;
}
.show {
display: block;
}
<button class="button1">
Show Div Element
</button>
<div class="div">
I am Div Element
</div>
<br>
<br>
<button class="button2">
Show Section Element
</button>
<section class="section">
I am Section Element
</section>
This solution relies on event bubbling, so it might break if other handlers stop propagation.
Also note that it currently relies on provided html structure, but that can be tweaked easy enough.
$(document).click(function(e) {
$elem = $(e.target)
// If the element is visible we shouldn't open it again
needToggle = $elem.is('button') && !$elem.next().hasClass("open")
$(".open").removeClass("open") // Remove all open elements
if (needToggle) {
$elem.next().toggleClass("open")
}
})
html,
body {
background-color: #fafafa;
width: 100%;
height: 100%;
padding: 12px;
margin: 0;
}
.button1 {
background-color: pink;
position: relative;
display: inline-block;
padding: 8px;
border: none;
margin: 0 0 6px 0;
cursor: pointer;
}
.div {
background-color: hotpink;
display: none;
width: 160px;
height: 160px;
}
.button2 {
background-color: green;
position: relative;
display: inline-block;
padding: 8px;
color: white;
border: none;
margin: 0 0 6px 0;
cursor: pointer;
}
.section {
background-color: darkgreen;
display: none;
width: 160px;
height: 160px;
color: white;
}
.open {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="button1">
Show Div Element
</button>
<div class="div">
I am Div Element
</div>
<br><br>
<button class="button2">
Show Section Element
</button>
<section class="section">
I am Section Element
</section>

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 give triggers to input field

I have a inputfield and I need to give two trigger. One is dropdown arrow and Another is cancel ("X") image. Here I am creating my inputfield.
My JS
var input = document.createElement("input");
input.className = 'styled-select';
input.style = 'width:30%' ;
input.id = "SearchInput";
input.type = "text";
input.title = "Madd";
input.onclick = TableExpand; // This happening when I clicking on Inputfield
My CSS for Inputfield
* {
box-sizing: border-box;
}
.styled-select {
width: 100px;
height: 20px;
border: 1px solid #95B8E7;
background-color: #fff;
vertical-align: middle;
display: inline-block;
overflow: hidden;
white-space: nowrap;
margin: 0;
padding: 0;
overflow: hidden;
overflow: -moz-hidden-unscrollable;
background: url(combo_arrow.png) no-repeat right white;
position:relative;
border-radius: 5px 5px 5px 5px;
}
.styled-select select {
background: transparent;
-webkit-appearance: none;
width: 100px;
font-size: 11px;
border: 0;
height: 17px;
position: absolute;
left: 0;
top: 0;
}
I need two trigger as I mentioned Arrow and Cross. I am able to give arrow by using background image but don't know how to give Cross image.
Also How I will use this as a trigger. I mean When I click on Cross and Dropdown one it leads me to the one function where I can write my code.
You can put the triggers as absolutely positioned elements on the input field. This way, you can add separate click events on these triggers to be able to perform whatever you want when they are clicked.
Here is an example of what you are trying to achieve:
HTML:
<div id="container">
<input type="text" id="textfield" />
<div id="triggers">
<img class="trigger" src="https://cdn3.iconfinder.com/data/icons/musthave/128/Stock%20Index%20Up.png" id="arrow" />
<img class="trigger" src="https://cdn3.iconfinder.com/data/icons/musthave/128/Remove.png" id="cross" />
</div>
</div>
CSS:
#container {
position: relative;
width: 600px;
}
#textfield {
height:30px;
width: 100%;
}
.trigger{
width: 20px;
}
#triggers {
position: absolute;
right: 0px;
top: 5px;
}
JS:
$(document).ready(function() {
$("#arrow").click(function() {
$("#textfield").val("Arrow was clicked.");
})
$("#cross").click(function() {
$("#textfield").val("Cross was clicked.");
})
})
Here is a working version:
https://jsfiddle.net/1j760ztn/
Your cross and dropdown should be separate buttons. And the javascript you need to listen for them goes like this.
<input type="text" id="theText"><button id="cross"><button id="dropdown">
<script> var cross = document.getElementById('cross'); cross.addEventListener("click", function(){ document.getElementById('theText').innerHTML = 'clicked X' }); </script>

jQuery - Click registered twice

I am making a web app that utilizes several pop ups. Inside the pop up, I have customized buttons (wrapped in <label>) that upload files. When I click on the button, it fires twice. I can solve the firing twice issue with e.preventDefault(); but obviously, it doesn't open the window for the user to upload a file.
if (document.getElementById("addItemModal").style.display !== 'none'){
$("#uploadImg").on('click', function(e) {
e.preventDefault();
console.log("I clicked upload image button.");
});
$("#uploadData").on('click',function() {
console.log("I clicked upload data button.");
});
}
So it seems that the first click is what opens the window to upload files and the second click is still a mystery. Where could this second click be coming from? I've tried .unbind as well and nothing seems to work.
EDIT: Added Code - Sorry for the wait, had to take out a lot but keep it functional and true to my problem.
var modal = document.getElementById('myModal');
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
// Click Add Icon to make pop up appear
$("#myBtn").click(function() {
$("#myModal").fadeIn("fast");
$("#addModal").fadeIn("fast");
});
// Click 'x'
$("#close1").click(function() {
$("#myModal").fadeOut("fast");
});
if (document.getElementById("myModal").style.display != 'none') {
console.log("Pls don't be running twice.");
$("#upImgBtn").on('click', function(evt) {
evt.preventDefault();
console.log("I clicked upload image button.");
});
document.getElementById("upDataBtn").addEventListener('click', function() {
console.log("I clicked upload data button.");
});
}
html,
body {
height: 100%;
padding: 0;
margin: 0;
overflow: hidden;
}
/* -- Edited Headers ----------------------- */
h4 {
color: #333;
display: inline-block;
font-size: 1.6em;
letter-spacing: 3px;
font-weight: 500;
}
/* ---------------------------------------- */
.sideBar {
position: relative;
width: 18%;
height: 90%;
float: left;
z-index: 100;
border-right-style: solid;
border-right-width: thin;
border-right-color: #333;
background-color: white;
}
/* -- Header & Location ------------- */
.headbar {
height: 7%;
background-color: ghostwhite;
margin-bottom: 20px;
box-shadow: 0 3px 10px 1px #888888;
}
#myBtn {
float: right;
position: relative;
padding: 9px 3px 0 0;
cursor: pointer;
display: inline-block;
}
.uploadBtns {
padding: 10px 15px 10px 15px;
background-color: blue;
color: white;
border-radius: 5px;
cursor: pointer;
box-shadow: 0 1px 5px 0 #888;
}
#myModal {
display: none;
position: fixed;
z-index: 1000000;
padding-top: 100px;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgb(0, 0, 0);
background-color: rgba(0, 0, 0, 0.5);
}
/* Modal Content */
#addModal {
background-color: #fefefe;
margin: auto;
padding: 20px;
border: 1px solid #888;
width: 800px;
border-radius: 15px;
color: #404040;
}
/* -- Add Location Pop Up CSS ------ */
#addTable {
width: 100%;
height: 200px;
background-color: transparent;
border-collapse: collapse;
}
td {
background-color: transparent;
border-bottom: 1px solid #333;
}
tr {
height: 100px;
}
.gridTitle {
padding-left: 15px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="sideBar" class="sideBar">
<div id="headbar" class="headbar">
<h5> Home</h5>
<div id="myBtn"><span id="addIcon">+</span>
</div>
</div>
</div>
<div id="myModal">
<div id="addModal">
<h4 id="header">ADD ITEM</h4>
<span class="myClose" id="close1">×</span>
<hr>
<table id="addTable">
<tr id="step1">
<td class="gridTitle">UPLOAD</td>
<td></td>
<td colspan="2">
<label class="btn btn-file uploadBtns" id="upImgBtn">
Upload Image
<input type="file" accept="image/*" style="display: none;" id="upImg">
</label>
<label class="btn btn-file uploadBtns" style="margin-left:120px;" id="upDataBtn">
Upload Data File
<input type="file" style="display: none;" id="upData">
</label>
</td>
</tr>
</table>
</div>
</div>
EDIT2: I haven't included the script twice in my HTML either.
All this is happening because you are adding event to the label.
Here is your code in jsfiddle.
document.getElementById("upData").addEventListener('click', function() {
alert("I clicked upload data button.");
});
You can also make a control which element fired the event. You can put your event on label and alert only if the event was from label but this doesn't stop the click event to happen on the input button.
document.getElementById("upDataBtn").addEventListener('click', function(event) {
if( event.target.tagName === "LABEL" ) {
alert("I clicked upload data button.");
}
});
It is called once or twice cause of the bubbling because the input element is part of the label and is one union and therefor also received the event if the label is click (is is not bubbling, you can't do event.stopPropagation()).
If you make
document.getElementById("upDataBtn").addEventListener('click', function(event) {
console.log(event.target.tagName);
});
This will give you two tag names
LABEL
INPUT
Try this
$(document).on('click',"#upImgBtn", function(e) {
if (e.target !== this)
return;
console.log("I clicked upload image button.");
});
$(document).on('click','#upDataBtn', function(e) {
if (e.target !== this)
return;
console.log("I clicked upload data button.");
});

Categories

Resources