I have a problem in my project.
I created something like keyboard for hangman game with span.
In click situation I need to have disabled span for that letter and if user choose wrong letter the hangman image should be change.
But when I click any button it looks like it is disabled because I changed the color
. clickedLetter{
background-color :....
opacity:.1;
pointer-events: none;
}
But the letter is still clickable and when you click on disabled letter(span) the image of hangman going to change .
I want to add something to stop any action
It is my code:
document.addEventListener("click", (e) => {
if(e.target.className ==='boxForLetter')
{ e.target.classList.add("clickedLetter");}
let clickedLetter= e.target.innerHTML;
.......
....
...
.
I appreciate any thoughts about this problem
The problem is in your if statement.
You need to run the code in your if statement NOT below it. If you run your hangman code BELOW your if statement in a delegated click handler, any click will trigger the hangman code. Also, I would recommend checking if the classlist contains a class, not if the class name equals something. This is more modern and allows for more classes on the objects.
if(e.target.classList.contains('boxForLetter'))
{
//run hangman code here
e.target.classList.add("clickedLetter");
let clickedLetter= e.target.innerHTML;
}
If I understood the problem right, you want to remove the click event if it is already clicked. It may be actually done using pointer-events: none which disables the event trigger.
document.addEventListener("click", (e) => {
if (e.target.className === 'boxForLetter') {
e.target.classList.add("clickedLetter");
}
let clickedLetter = e.target.innerHTML;
});
.boxForLetter {
display: inline-block;
background-color: black;
width: 50px;
height: 50px;
cursor: pointer;
margin-right: 10px;
}
.boxForLetter.clickedLetter {
background-color: red;
opacity: 1;
pointer-events: none;
}
<div class="boxForLetter">
</div>
<div class="boxForLetter">
</div>
<div class="boxForLetter">
</div>
<div class="boxForLetter">
</div>
<div class="boxForLetter">
</div>
<div class="boxForLetter">
</div>
Related
I used the following code to toggle a button class in order to make a full-screen mobile menu.
HTML
button class="hamburger hamburger--slider" type="button">
<a href='#'><div class="hamburger-box">
<div class="hamburger-inner"></div>
</div>
</a>
document.addEventListener('DOMContentLoaded', function() {
jQuery(function($){
$('.hamburger').click(function(){
$('.hamburger--slider').toggleClass('is-active');
});
});
});
Now I would like to hide another item in my header when the toggled class .is-active is present.
The following code works to hide the item, but once the toggled class is gone, the item does not reappear but stays hidden until the page is reloaded.
jQuery(function($) {
if ($('.hamburger--slider.is-active').length) {
$('.rey-headerCart-wrapper').hide();
}
});
Appreciate any help :) !
you have to show the element again after the burger menu closes:
document.addEventListener('DOMContentLoaded', function() {
jQuery(function($){
$('.hamburger').click(function(){
$('.hamburger--slider').toggleClass('is-active');
// hide / show other element
if ($('.hamburger--slider.is-active').length) {
$('.rey-headerCart-wrapper').hide();
} else {
$('.rey-headerCart-wrapper').show();
}
});
});
});
Or in vanilla javascript:
window.addEventListener("load", () => {
document.querySelector(".hamburger").addEventListener("click", () => {
document.querySelector(".hamburger--slider").classList.toggle("is-active");
// hide / show other element
const cart = document.querySelector(".rey-headerCart-wrapper");
if (document.querySelector(".hamburger--slider.is-active")) {
cart.style.display = "none";
} else {
cart.style.display = "block";
// apply original display style
// cart.style.display = "inline-block";
// cart.style.display = "flex";
};
});
})
In order to make toggle functions like this more understandable, maintainable and extendable you need to think about your HTML structure.
In your current structure, you have a button that toggles a class on itself. Therefore any element beyond that button that has to change appearance or beaviour has to check which class that button has, or you have to extend the click-event handler in order to add these elements (that's what you did here).
This can get quite messy really fast.
A better approach could be to not toggle a class on the button but on an element that is a common parent to all elements that you want to change the behavior of.
That way anything you ever add to that wrapper already can be manipulated via CSS, without the need of changing your JS.
$('.nav-toggler').on('click', function() {
$('#nav-wrapper').toggleClass('active');
});
.menu, .cart {
padding: 1em;
margin: 2px;
}
.cart {
background: #FFF000;
}
.menu{
background: #F1F1F1;
display: none;
}
#nav-wrapper.active > .menu {
display: block;
}
#nav-wrapper.active > .cart {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="nav-wrapper">
<button class="nav-toggler">Toggle</button>
<div class="menu">My Menu</div>
<div class="cart">My Cart</div>
</div>
I have the following code in my JS file:-
var $html = $('<div class="chat self" style="justify-content: flex-end;">' +
'<p class="chat-message" style="cursor: pointer;">' +
'message' +
'</p>' +
'</div>'
);
$html.find('p').click(() => cast_vote(url, option_position, vote_count));
The click function gets called all the times when the element is clicked.
How do i make the element to be clicked only once?
Use jQuery's one() handler. According to the API, "The .one() method is identical to .on(), except that the handler for a given element and event type is unbound after its first invocation."
You're using click() which is shorthand for .on( "click", handler ). Change your code to:
$html.find('p').one('click', () => cast_vote(url, option_position, vote_count));
you could add a class like "disabled" to the element on click, then check if the element has that tag before you run the cast_vote function again.
You can add a class to the element after clicking it, and check each time one of the elements is clicked to see if it has this class.
The example below shows you how you can do this.
Demo
// Add click event to wrapping .message_box
$(".message_box").on("click", ".message", function() {
// Check if the clicked message has the clicked class
// If it doesnt, run script
if (!$(this).hasClass("clicked")) {
// Add clicked class to message
// This means no further click events will run the code below
$(this).addClass("clicked");
console.log("Clicked");
}
});
.message {
padding: 4px;
border: 1px solid grey;
border-radius: 4px;
width: auto;
clear: both;
margin: 4px;
}
.clicked {
border-left-color: blue;
}
.user1 {
float: left;
}
.user2 {
float: right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="message_box">
<div class="message user1">
Hello
</div>
<div class="message user2">
Hi!
</div>
<div class="message user1">
How are you?
</div>
<div class="message user2">
Good thanks
</div>
<div class="message user2">
and you?
</div>
</div>
How would I be able to simplify this jquery code. I feel like I am repeating myself and just wondering if there is a shorter way to write this which I'm sure there is. I am a bit new to javascript and jquery. I have created a two tabs with their own containers with miscellaneous information in them. Basically I want the container to open when it's related tab is clicked on. I also would like the tab to be highlighted when it's active. Also, how would I be able to write code to make all tab containers disappear when you click off from the tab containers.
<!-- HTML Code -->
<div class="sort-filters">
<span class="sort-by active">SORT BY</span>
<span class="filter">FILTER</span>
</div>
<div class="sort-containers">
<div class="sort-by-container">Sort by click me here</div>
<div class="filter-container">Filter click me here</div>
</div>
/* CSS */
.sort-filters {
display: flex;
width: 500px;
height: 30px;
}
.sort-by,
.filter {
background: #CCC;
color: #756661;
flex: 1;
display: flex;
justify-content: center;
align-items: center;
font-family: 'Arial', sans-serif;
cursor: pointer;
}
.sort-by-container,
.filter-container {
width: 500px;
background: #756661;
color: #FFF;
height: 100px;
display: none;
}
.active {
background: #756661;
color: #FFF;
transition: 0.2s;
}
// Jquery Code
js = $.noConflict();
var sort = js('.sort-by');
var filter = js('.filter');
var sortContainer = js('.sort-by-container');
var filterContainer = js('.filter-container');
js(sort).click(function() {
js(filterContainer).hide();
js(sortContainer).show();
js(sort).addClass('active');
js(filter).removeClass('active');
});
js(filter).click(function() {
js(sortContainer).hide();
js(filterContainer).show();
js(filter).addClass('active');
js(sort).removeClass('active');
});
In order to avoid such repetitive actions I like to stick to naming conventions, so that I can apply the ID's, classes or attributes from one element to select other elements, for instance:
<div id="tabs">
<span class="active" data-type="sort-by">SORT BY</span>
<span data-type="filter">FILTER</span>
</div>
Now, all you need is one click handler on #tabs span, and get the data-type of the span you clicked on. You can use that to filter on the classes of the other container elements.
The second thing is that you can attach handler to more than 1 element at the same time. So in your example, js('#sort-containers div').hide(); will hide all the div's that match the selector at once.
results
I changed some classes to ID's, and some classes to data attributes. Here's a fiddle: https://jsfiddle.net/mq9xk29y/
HTML:
<div id="tabs">
<span data-type="sort-by">SORT BY</span>
<span data-type="filter">FILTER</span>
</div>
<div id="sort-containers">
<div class="sort-by-container">Sort by click me here</div>
<div class="filter-container">Filter click me here</div>
</div>
JS:
js = $.noConflict();
var $tabs = js('#tabs span');
$tabs.click(function() {
var $clicked = js(this); //get the element thats clicked on
var type = $clicked.data('type'); //get the data-type value
$tabs.removeClass('active'); //remove active from all tabs
$clicked.addClass('active'); //add active to the current tab
js('#sort-containers div').hide(); //hide all containers
js('.' + type + '-container').show().addClass('active'); //add active to current container
});
As long as you follow the naming convention of data-type: bla in the tabs, and bla-container on the classes in sort-container, you never have to worry about coding for additional tabs.
There might still be things that could be further optimised, but at least it'll take care of the repetition.
When you enter my website (goerann.com) the dropdown register-box is down by default.
If I click in Register, the register-box toogles it visibility as I want, but it doesn't start hidden by default.
$(document).ready(function() {
$('#signup').click(function() {
$('.signupmenu').slideToggle("fast");
});
});
I want it to only show when you click on it. How can I make this happen?
Here's my jsfiddle (http://jsfiddle.net/bdv2doxr/)
Since you're already using the $(document).ready event, you can hide the menu there:
$(document).ready(function() {
$('.signupmenu').hide();
$('#signup').click(function() {
$('.signupmenu').slideToggle("fast");
});
});
And here is your fiddle updated.
You need to make two changes, both involving the removal of display: block. When you toggle this div, it will make the display block. Therefore, you can initialize it as display: none.
Change this:
<div class="signupmenu" style="display: block;">
to this:
<div class="signupmenu">
And also change this:
.signupmenu {
background-color: #FFF;
display: block;
...
to this:
.signupmenu {
background-color: #FFF;
display: none;
...
Updated fiddle here
For part of the site I'm working on, I have a set of sidebars that can pull out. To have them hide when the users are done with them, I've set up a div with a click event (see below) so that whenever the user clicks somewhere outside of the sidebar, the sidebar closes. The problem that I'm running into, however, is that the click event handler is grabbing the event, running its method, and then the click event seems to stop. I've tried using return true and a few other things I've found around here and the internet, but the click event just seems to die.
$('.clickaway').click(function() {
$('body').removeClass(drawerClasses.join(' '));
return true;
});
EDIT: Here is a fiddle with an example: https://jsfiddle.net/2g7zehtn/1/
The goal is to have the drawer out and still be able to click the button to change the color of the text.
The issue is your .clickaway layer is sitting above everything that's interactive, such as your button. So clicking the button, you're actually clicking the layer.
One thing you could do is apply a higher stacking order for elements you want to interact with, above the .clickaway layer. For example, if we apply position: relative, like this:
.show-drawerHotkey .ColorButton {
position: relative;
}
The element will now be in a higher stacking order (since it comes after the clickaway, and we've applied no z-index to clickaway)
Here's a fiddle that demonstrates: https://jsfiddle.net/2g7zehtn/5/
Using this somewhat famous SO answer as a guide, you can bind to the $(document).mouseup(); event and determine whether certain "toggling" conditions apply:
[EDIT] - Example updated to illustrate clicking a link outside of the containing div.
// Resource: https://stackoverflow.com/questions/1403615/use-jquery-to-hide-a-div-when-the-user-clicks-outside-of-it
var m = $('#menu');
var c = $('#menuContainer');
var i = $('#menuIcon');
i.click(function() {
m.toggle("slow");
});
$(document).mouseup(function(e) {
console.log(e.target); // <-- see what the target is...
if (!c.is(e.target) && c.has(e.target).length === 0) {
m.hide("slow");
}
});
#menuIcon {
height: 15px;
width: 15px;
background-color: steelblue;
cursor: pointer;
}
#menuContainer {
height: 600px;
width: 250px;
}
#menu {
display: none;
height: 600px;
width: 250px;
border: dashed 2px teal;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I'm a link outside of the container
<div id="menuContainer">
<div id="menuIcon"></div>
<div id="menu"></div>
</div>