jQuery toggle between two ID's - javascript

Why does the following code not work? The red square becomes green but on a second click doesn't become red again.
jQuery(document).ready(function($) {
$("#red").click(function() {
$(this).attr("id", "green");
});
$("#green").click(function() {
$(this).attr("id", "red");
});
});
div {
margin: 0 auto;
width: 100px;
height: 100px;
}
#red {
background-color: red;
}
#green {
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="red">
See also: https://codepen.io/thomasmalley/pen/OqWNaM

The issue is because you assign the event handler on load, before the #green element exists.
To fix this you need to use delegated event handlers so that the element selector is evaluated when the event occurs:
jQuery(function($) {
$(document).on('click', "#red", function() {
$(this).attr("id", "green");
});
$(document).on('click', "#green", function() {
$(this).attr("id", "red");
});
});
div {
margin: 0 auto;
width: 100px;
height: 100px;
}
#red {
background-color: red;
}
#green {
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="red"></div>
That being said, it's not great practice to be changing id attributes at runtime. They should be static. A much better idea would be to toggle a class on the element instead, which governs the styling.
jQuery(function($) {
$('#foo').click(function() {
$(this).toggleClass('green');
});
});
#foo {
margin: 0 auto;
width: 100px;
height: 100px;
background-color: red;
}
#foo.green {
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="foo"></div>

First, there is div with id red and after clicking that div it switches id to green that is dynamically so in this case we use event-delegation. Try below code -
jQuery(document).ready(function($) {
$(".parent").on('click', '#red', function() {
$(this).attr("id", "green");
});
$(".parent").on('click', '#green', function() {
$(this).attr("id", "red");
});
});
div {
margin: 0 auto;
width: 100px;
height: 100px;
}
#red {
background-color: red;
}
#green {
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="parent">
<div id="red"></div>
</div>

This is happening because when you load the page there is no element with the id green for a click event to be added to.
Instead, you can use event delegation by using:
$(document).on('click', '#red', function() {...}
and
$(document).on('click', '#green', function() {...}
This way, your click event will be applied to the element with the id green.
See working example below:
jQuery(document).ready(function($) {
$(document).on('click', '#red', function() {
$(this).attr("id", "green");
});
$(document).on('click', '#green', function() {
$(this).attr("id", "red");
});
});
div {
margin: 0 auto;
width: 100px;
height: 100px;
}
#red {
background-color: red;
}
#green {
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="red"></div>

Since the id is added dynamically, the code $("#green").click(function() { when loaded will not find element with id green so the click event is not set for that element. Thus you can add a listener on document level:
jQuery(document).ready(function($) {
$(document).on('click', 'div', function(){
var id = $(this).attr('id');
if(id === 'red'){
$(this).attr("id", "green");
} else {
$(this).attr("id", "red");
}
});
});
div {
margin: 0 auto;
width: 100px;
height: 100px;
}
#red {
background-color: red;
}
#green {
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="red">

change script
$(document).on('click','#red',function() {
$('#red').attr("id", "green");
});
$(document).on('click','#green',function() {
$('#green').attr("id", "red");
});

Related

toggle inline styles with JQuery - display & overflow

Could you please take a look at my code:
$(".button").click(function () {
$("#overlay").css("display", "block");
$('body').css('overflow', 'hidden');
});
I need to toggle this style when we clicked again on .button. That should be look like:
$(".button").click(function () {
$("#overlay").css("display", "none");
$('body').css('overflow', 'auto');
});
JSfiddle
Yes, use JQuery's toggleClass.
Create those 2 classes which I did in my example as .display-show & .body-show
Try this:
$(".button").click(function() {
$("#overlay").toggleClass('display-show');
$('body').toggleClass('body-show');
});
body {
overflow: hidden;
}
#overlay {
background-color: red;
opacity: 0.1;
width: 100px;
height: 100px;
}
.display-show {
display: none;
}
.body-show {
overflow: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Button
<div id="overlay"></div>
Update 1: (according to your jsfiddle)
$(".button").click(function() {
$("#overlay").toggleClass('display-show');
$('body').toggleClass('body-show');
});
body {
font-family: sans-serif;
height: 1500px;
padding: 20px;
overflow: hidden;
}
.button {
border: 0;
background: red;
color: #fff;
padding: 10px 30px;
text-decoration: none;
}
#overlay {
top: 100px;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
display: none;
}
.display-show {
display: block !important;
}
.body-show {
overflow: auto !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Button
<div id="overlay"></div>
How about this code?
(Runnable example : https://codepen.io/hoge1e3/pen/mddbJPV)
var overlayVisible=false;
$(".button").click(function () {
if (!overlayVisible) {
$("#overlay").css("display", "block");
$('body').css('overflow', 'hidden');
overlayVisible=true;
} else {
$("#overlay").css("display", "none");
$('body').css('overflow', 'auto');
overlayVisible=false;
}
});
I have using this now:
$('.button').on('click', function (e) {
$('#overlay').toggle();
if ($("#overlay").is(':visible')) {
$("#overlay").css("display", "block");
$('body').css('overflow-y', 'hidden');
}
else {
$("#overlay").css("display", "none");
$('body').css('overflow-y', 'auto');
}
});

with javascript onclick add classname to a div

I want to achieve with javascript something like when i clink on any of thumbnail (btn-1, btn-2 and btn-3) the specific class should be add to box div dynamically.
my code: JSFiddle
document.getElementById('btn-1').onclick = function() {
document.getElementById('box').className = 'bg-1';
}
#box {
background-color: darkgray;
width: 200px;
height: 200px;
}
.thumbnail {
width: 30px;
height: 30px;
border: 1px solid;
margin: 5px;
position: relative;
float: left;
}
#btn-1 {
background-color: red;
}
#btn-2 {
background-color: green;
}
#btn-3 {
background-color: blue;
}
.bg-1 {
background-color: red;
}
.bg-2 {
background-color: blue;
}
.bg-3 {
background-color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="box"></div>
<div class="thumbnail" id="btn-1"></div>
<div class="thumbnail" id="btn-2"></div>
<div class="thumbnail" id="btn-3"></div>
You javascript is working, but your CSS isn't.
You need to add !important as follows to .bg-1, .bg-2 and .bg-3
.bg-1 {
background-color: red !important;
}
Otherwise the id styling is taking preference over the class styling
You can see the classname is being added if you right click on the grey div and choose inspect element in Chrome.
Instead of bothering with classes, use simply a data- attribute like: data-bg="#f00"
$('[data-bg]').css('background', function () {
$(this).on('click', () => $('#box').css('background', this.dataset.bg));
return this.dataset.bg;
});
#box {
background: darkgray;
width: 120px; height: 120px;
}
[data-bg] {
width: 30px; height: 30px;
margin: 5px;
float: left;
}
<div id="box"></div>
<div data-bg="red"></div>
<div data-bg="#00f"></div>
<div data-bg="rgb(255,0,180)"></div>
<div data-bg="linear-gradient(to right, #E100FF, #7F00FF)"></div>
<script src="//code.jquery.com/jquery-3.1.0.js"></script>
You want to use jquery .addClass() function:
$('.myButton').addClass('myNewClass');
The function would probably look something like this:
$(function () {
$('.thumbnail').click(function() {
$('#box').addClass($(this).attr('id'));
});
})
You can get all the thumbnails as an array, and then iterate through the array and dynamically add an event listener to each, which will add the desired className to box when clicked:
var thumbnails = document.getElementsByClassName('thumbnail');
Array.from(thumbnails).forEach(function(thumbnail) {
var id = thumbnail.id;
thumbnail.addEventListener('click', function() {
document.getElementById('box').className = id.replace('btn', 'bg')
});
});

Can not get jQuerys .on to work with dynamical elements even though it's delegated

I have a static element, but even though i use that, .on do not bind to the dynamic selector.
this is a more simple version than the one i'm working on, but do have the same problem.
The divs are created when i click on the static element, but clicking on the dynamic elements do nothing.
Hope someone here can help me.
HTML
$(document).ready(function() {
var test = $('#test');
test.click(function() {
var html = document.createElement('div');
html.className = 'temp';
$('body').append(html);
console.log('clicked.');
});
test.on('click', '.temp', function() {
console.log('Temp div removed.');
$(this).remove();
});
});
#test {
width: 300px;
height: 75px;
background: #f00;
margin-bottom: 5px;
}
.temp {
width: 200px;
height: 50px;
background: #00f;
margin-bottom: 3px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div id="test"></div>
You need to set the event delegation to the parent of the dynamic elements. You've bounded the event to the #test element, but the .temp divs are children of the body. You can add the event to the body, or to a dedicated container for the added nodes.
$(document).ready(function() {
var test = $('#test');
var target = $('#target');
test.click(function() {
var html = document.createElement('div');
html.className = 'temp';
target.append(html);
console.log('clicked.');
});
target.on('click', '.temp', function() {
console.log('Temp div removed.');
$(this).remove();
});
});
#test {
width: 300px;
height: 75px;
background: #f00;
margin-bottom: 5px;
}
.temp {
width: 200px;
height: 50px;
background: #00f;
margin-bottom: 3px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div id="test"></div>
<div id="target"></div>

How to detect a click event to an inner div using Jquery

Im creating a menu for mobile, and I want to add a function for overlay click.
When I click on menu (purple part), it doesn't need to close, but when I click on blue section, then its need to close.
I wrote a jQuery, who gets only purple section, but when I click on blue part the alert didn't appear.
There's gonna be my JSFiddle for test, to see.
And here is my code
$('.outer-content .inner-content').on('click', function() {
$(".outer-content .inner-content").data('clicked', 'yes');
var isClicked = $('.outer-content').data('clicked');
if (isClicked == 'yes') {
alert("clicked the blue block");
} else {
alert("clicked the purple block");
}
});
.outer-content {
width: 100%;
height: 200px;
background: lightblue;
position: relative;
}
.inner-content {
width: 300px;
background: purple;
position: absolute;
margin: auto;
top: 0;
bottom: 0;
right: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="outer-content">
<div class="inner-content"></div>
</div>
Basically there are two event models in javascript. Event capturing and Event bubbling. In event bubbling, if you click on inside div, the inside div click event fired first and then the outer div click fired. while in event capturing, first the outer div event fired and than the inner div event fired. To stop event propagation, use this code in your click method.
e.stopPropagation();
JSFIDDLE
Your code:
$('.outer-content').on('click', function(e) {
alert("clicked the blue block");
});
$('.inner-content').on('click', function(e) {
alert("clicked the purple block");
e.stopPropagation();
});
.outer-content {
width: 100%;
height: 200px;
background: lightblue;
position: relative;
}
.inner-content {
width: 300px;
background: purple;
position: absolute;
margin: auto;
top: 0;
bottom: 0;
right: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="outer-content">
<div class="inner-content"></div>
</div>
$('.outer-content').on('click', function(event) {
if ($(event.target).hasClass('inner-content')) {
alert("clicked the purple block");
} else {
alert("clicked the blue block");
}
});
.outer-content {
width: 100%;
height: 200px;
background: lightblue;
position: relative;
}
.inner-content {
width: 300px;
background: purple;
position: absolute;
margin: auto;
top: 0;
bottom: 0;
right: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="outer-content">
<div class="inner-content"></div>
</div>
When I click on menu(purple part), it doesnt need to close, but when I
click on blue section, then its need to close
Why not target the blue element directly and only process any code to close when it is clicked as seen below.
If you need other code to execute when the purple element is clicked, bind to that separately.
$('.outer-content').on('click', function(e) {
if (e.target == this) {
// add "close" code here
alert("will close");
}
});
// You still can add code when clicking the purple element if needed...
$('.inner-content').on('click', function(e) {
alert("I'm purple but separate code and will not close");
});
.outer-content {
width: 100%;
height: 200px;
background: lightblue;
position: relative;
}
.inner-content {
width: 300px;
background: purple;
position: absolute;
margin: auto;
top: 0;
bottom: 0;
right: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="outer-content">
<div class="inner-content"></div>
</div>
You can do that by adding event on outer content and then use the event.target property to check the element that has been clicked
$('.outer-content').on('click', function(e) {
if( $(e.target).hasClass('outer-content')){
alert("clicked the blue block");
} else {
alert("clicked the purple block");
}
});
Due to event bubbling any event in the child element will be propagated to parent element as well.
$('.outer-content, div:not("inner-content")').on('click', function() {
$(".inner-content").slideToggle();
});
.outer-content {
width: 100%;
height: 200px;
background: lightblue;
position: relative;
}
.inner-content {
width: 300px;
background: purple;
position: absolute;
margin: auto;
top: 0;
bottom: 0;
right: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="outer-content">
<div class="inner-content"></div>
</div>
$('div').on('click', function(e) {
e.preventDefault();
e.stopImmediatePropagation()
if($(e.target).is('.inner-content')){
alert("clicked the purple block");
}else{
alert("clicked the blue block");
}
});
.outer-content{
width:100%;
height:200px;
background:lightblue;
position:relative;
}
.inner-content{
width:300px;
background:purple;
position:absolute;
margin:auto;
top:0; bottom:0; right:0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="outer-content">
<div class="inner-content"></div>
</div>

Add class to matching element without other specific class

Whenever a user clicks on the body I would like to add a class to a certain element, as long as that element doesn't have a specific class. The issue is, I re-use this element and some of these elements will have that specific class I mentioned and other will not. If one element has this class, with my current code, no element will have new class added.
Here is a fiddle showing the behaviour.
Example:
$('body').on('click', function(){
if ($('.box').hasClass('red') && !$('.box').hasClass('stay-red')) {
$('.box').addClass('blue');
}
});
html, body {
background: lightblue;
height: 100%;
}
.box {
height: 20px;
width: 20px;
margin-bottom: 10px;
}
.red {
background: red;
}
.blue {
background: blue;
}
<div class="box red stay-red"></div>
<div class="box red"></div>
It will be a lot easier with filter, and will avoid your problem:
$('body').on('click', function(){
$('.box').filter('.red:not(.stay-red)').addClass('blue');
});
html, body {
background: lightblue;
height: 100%;
}
.box {
height: 20px;
width: 20px;
margin-bottom: 10px;
}
.red {
background: red;
}
.blue {
background: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<div class="box red stay-red"></div>
<div class="box red"></div>
</body>
</html>
$('.box.red:not(.stay-red)').addClass('blue');
Is that what you want?
:not() Selector https://api.jquery.com/not-selector/
https://jsfiddle.net/7L3ub1sp/
$(function(){
$('body').on('click', function(){
$('.box').each(function(){
if ($(this).hasClass('red') && !$(this).hasClass('stay-red')) {
$(this).addClass('blue');
}
})
});
})
html, body {
background: lightblue;
height: 100%;
}
.box {
height: 20px;
width: 20px;
margin-bottom: 10px;
}
.red {
background: red;
}
.blue {
background: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<div class="box red stay-red"></div>
<div class="box red"></div>
</body>
</html>
You can use:
$('body').on('click', function(){
$('.box.red:not(.stay-red)').addClass('blue');
});
Or loop through all of them with each:
$('body').on('click', function(){
$('.box').each(function() {
if ($(this).hasClass('red') && !$(this).hasClass('stay-red')) {
$(this).addClass('blue');
}
});
});
If you want to avoid adding the new class to all elements if one of them has the other class, you can use some (or every):
var els = document.getElementsByClassName('box');
if(![].some.call(els, function(el) {
return el.classList.contains('stay-red');
}) [].forEach.call(els, function(el) {
return el.classList.add('blue');
});
Here is the body onclick you need:
$('body').on('click', function(){
$('.box.red:not(.stay-red)').removeClass('red').addClass('blue');
});
You also need to remove the class .red, even if in this precise case it works because the class .blue is defined after the class .red in the CSS

Categories

Resources