jQuery remove class on 2nd click and disable hover on 2nd click - javascript

I'm trying to remove class 'active' when you click on the checkbox the 2nd time, the same way Pinterest does it for Twitter/Facebook checkboxes when a user adds a pin:
Adding 'active' class on click is easy. However, I couldn't figure how to remove it once it was added. I tried this, but it didn't work:
$(".add_link_twitter.active").click(function(e) {
$(this).removeClass(activePostTwitter);
});
I have two questions:
How to remove the 'active' css class on the 2nd click on the
checkbox?
How to disable '.add_link_twitter:hover' when the Twitter
checkbox is selected?
Thanks in advance!
Here's the jQuery:
var postTwitter = ".add_link_twitter";
var activePostTwitter = "active";
$(postTwitter).click(function(e) {
$(this).addClass(activePostTwitter);
});
Here's the html:
<label class="add_link_twitter">
<input type="checkbox" name="publish_to_twitter" class="publish_to_twitter"><span>Share on Twitter</span>
</label>
Here's the css:
.add_link_twitter{
position:absolute;
left:15px;
bottom:16px;
color: #a19486;
border: 2px solid transparent;
border-color: #F0EDE8;
border-radius: 4px;
font-size: 13px;
font-weight: bold;
cursor: pointer;
padding: 7px;
padding-top: 5px;
padding-bottom: 5px;
}
.active {
border-color: #468BD0;
color: #468BD0;
background-color: whiteSmoke;
}
.add_link_twitter:hover
{
color: #A19486;
border: 2px solid transparent;
border-color: #C2B1A2;
border-radius: 4px;
background-color: white;
padding: 7px;
padding-top: 5px;
padding-bottom: 5px;
}

Instead of
$(postTwitter).click(function(e) {
$(this).addClass(activePostTwitter);
});
use
$(postTwitter).click(function(e) {
$(this).toggleClass(activePostTwitter);
});
EDIT:
The event triggers twice per click, probably because of event propagation. To work around this, assign the handler to the input and have it change the class of its parent:
$(postTwitter + " input").click(function(e) {
$(this).parent().toggleClass(activePostTwitter);
});
Confirm jsfiddle: http://jsfiddle.net/bpfqB/

This should work for both your questions:
$(function() {
"use strict";
var $postTwitter = $("label.add_link_twitter");
$postTwitter.find("input:checkbox").click(function() {
$(this).parent().toggleClass("active");
if($("input.publish_to_twitter").is(":checked")) {
$(this).parent().removeClass("hover");
}
});
$postTwitter.hover(
function() {
if($("input.publish_to_twitter").is(":checked")) {
return;
}
$(this).addClass("hover");
},
function() {
$(this).removeClass("hover");
});
});
You need to make some changes to your CSS though, you have to do the hovering with jQuery (skip the CSS hover).
DEMO

Related

Icon interfering with button click event

I have a button enclosing an icon. I believe the icon is interfering with my click event. I am only able to click on the icon margins to activate the onclick event, but nothing happens when I click on the icon. I replaced the icon with some text and the button onclick works perfectly fine. I have tried z-index to put the icon behind the button, but to no avail. Can someone explain why the icon blocks the click from occurring and how I can fix it?
html:
<div class="navMenu">
<button onclick="navClick()" class="navMenu-button"><i class="fas fa-bars"></i></button>
<div id="navList" class="navMenu-content">
Home
About
Resume
</div>
sass:
.navMenu{
position: relative;
display: inline-block;
margin-top:5px;
margin-left:5px;
&-button {
background-color: #615b5b;
border-radius:50%;
color: white;
padding: 7px;
opacity:0.7;
border:none;
font-size: 14px;
cursor: pointer;
}
&-button:hover, &-button:focus {
background-color: #615b5b;
}
&-content {
display: none;
position: absolute;
background-color: #f1f1f1;
min-width: 200px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
&-content .navMenu-link{
color: $body-text-color;
padding: 12px 16px;
text-decoration: none;
display: block;
}
&-content .navMenu-link:hover {
background-color: #ddd;
}
&-show {
display:block;
}
}
js:
function navClick() {
document.getElementById("navList").classList.toggle("navMenu-show");
}
window.onclick = function(event) {
if (!event.target.matches('.navMenu-button')) {
var dropdowns = document.getElementsByClassName("navMenu-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var show = dropdowns[i];
if (show.classList.contains('navMenu-show')) {
show.classList.remove('navMenu-show');
}
}
}
}
This is happening becuase your are setting an event that verifies if the element clicked contains an especific class, and indeed when it clicks the icon, it won't match because the icon does not contains the class you can solve it asking if also the parent contains the class....
window.onclick = function(event) {
if (event.target.matches('.navMenu-button') ||
event.target.parentNode.matches('.navMenu-button')
) {
console.log("it matches...");
}
}
.icon {
background:red;
}
<button class="navMenu-button">this is the button
<div class="icon">this is the icon</div>
</button>
On the other hand you could reference the click event using the "onclick" method in this case it will solve it automatically..
var button = document.querySelectorAll('.navMenu-button')[0];
button.onclick = function() {
console.log("button clicked");
}

Remove data-attr of cloned element

I'm trying to make a very simple (it looks like) thing: clone already existring html-element, modify it's attribute and append in on the page. And it doesn't work, and I have no idea why.
Here is a simple demo:
Hello World
Change color
// js
var banner = $("#banner-message")
var button = $("button")
// handle click and add class
button.on("click", function(){
var row = $('#banner-message').find('.test:first').clone(true);
row.removeData('event-num');
//row.data('event-num', 500);
$('#banner-message').find('.test:last').after(row);
})
Here is a jsfiddle demo: https://jsfiddle.net/jn1wm9da/
It neither deletes nor overrides (actually I want to delete it) already existing attribute. What I'm doing wrong?
jQuery's .data() method stores information in a jQuery object that is connected to the element, and doesn't effect data-* attributes. Data attributes are just attributes, and you should use .attr(), and .removeAttr() to add/change or remove them.
// find elements
var banner = $("#banner-message")
var button = $("button")
// handle click and add class
button.on("click", function() {
var row = $('#banner-message').find('.test:first').clone(true);
row.removeAttr('data-event-num');
row.attr('data-event-num', 500);
$('#banner-message').find('.test:last').after(row);
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#banner-message {
background: #fff;
border-radius: 4px;
padding: 20px;
font-size: 25px;
text-align: center;
transition: all 0.2s;
margin: 0 auto;
width: 300px;
}
button {
background: #0084ff;
border: none;
border-radius: 5px;
padding: 8px 14px;
font-size: 15px;
color: #fff;
}
#banner-message.alt {
background: #0084ff;
color: #fff;
margin-top: 40px;
width: 200px;
}
#banner-message.alt button {
background: #fff;
color: #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="banner-message">
<p>Hello World</p>
<button class="test" data-event-num='0'>Change color</button>
</div>
From the jQuery Documentation for removeData
Note that .removeData() will only remove data from jQuery's internal .data() cache, and any corresponding data- attributes on the element will not be removed.
Try using
row.removeAttr('data-event-num');
instead
Use row.attr('data-event-num', null); to remove the data attribute
// find elements
var banner = $("#banner-message")
var button = $("button")
// handle click and add class
button.on("click", function(){
var row = $('#banner-message').find('.test:first').clone(true);
//row.removeData('event-num');
row.attr('data-event-num', null);
$('#banner-message').find('.test:last').after(row);
})

Why can I not change the 'checked' status of a checkbox in Javascript?

Intended behaviour
I have a checkbox inside of a div element. I want both the box and the div to be clickable.
When the checkbox is clicked by the user, a class is added to the div to change its background colour. This class is then removed if the checkbox is clicked again.
When the div itself is clicked, the class with the background colour is added or removed as appropriate and the checkbox is ticked or unticked too
Currently, I have most of this working using plain javascript:
function boxPress(markNumber) {
var checkbox = "mark" + markNumber;
var element = document.getElementById(checkbox);
var markbox = "markbox" + markNumber;
if (element.getAttribute("checked") == null) {
element.setAttribute("checked", "checked");
document.getElementById(markbox).classList.add('checked');
} else {
element.removeAttribute("checked");
document.getElementById(markbox).classList.remove('checked');
}
}
.mark {
margin-bottom: 5px;
margin-top: 5px;
background-color: #FFFFFF;
border-width: 2px;
border-radius: 0px 5px 5px 0px;
border-left-style: solid;
border-left-width: 10px;
border-color: lime;
overflow: auto;
padding: 2%;
transition: background-color 0.5s linear 0s;
cursor: pointer;
}
.checked {
background-color: #66ff66;
}
.mark:hover {
background-color: #fffcaf;
}
.checked:hover {
background-color: #b3ffb3;
}
.flex-container {
display: -webkit-flex;
display: flex;
align-items: center;
margin: 0px;
padding: 0px;
}
.flex-mark {
width: 85%;
margin: 0px;
}
.flex-tick {
width: 15%;
margin: 0px;
text-align: center;
}
.flex-tick input {
width: 40px;
height: 40px;
}
<div class="mark col-12 col-m-6" id="markbox0" onclick="boxPress(0)">
<div class="flex-container">
<div class="flex-mark">
<p>Candidate introduces themself by first name, surname and role</p>
</div>
<div class="flex-tick"><input type="checkbox" id="mark0"></div>
</div>
</div>
This works perfectly, apart from where the user first interacts with the checkbox, then later with the div element.
Steps to reproduce the problem in the above snippet:
Click the div. The background changes and the checkbox is ticked.
Click the div again. The changes are reversed as expected.
Click the checkbox. The background change is applied.
Click the checkbox again. The change is reversed as expected.
Now click the div again. The background changes happen but the checkbox remains unticked
Even more interestingly, the HTML of the checkbox reads:
<input type="checkbox" id="mark0" checked="true">
Yet the browser doesn't render the box as checked.
Why is this happening, and why is it only a problem when the div click comes after the box click? It happens in both Chrome and Edge.
There is a difference between the attribute checked and the checked state of a checkbox. Fixed code below.
Explanation:
Because the checked attribute can be set in the markup to "pre-check" the checkbox the DOM has to have a checked state for the checkbox or it would be impossible to "un-check" it. A checkbox that could not be un-checked wouldn't be very useful.
When you set the attribute for the first time (with javascript) it checks the box just like if you had put it in the HTML but the DOM ignores the attribute after that because it needs to rely on the checked state as explained above.
function boxPress(markNumber) {
var checkbox = "mark" + markNumber;
var element = document.getElementById(checkbox);
var markbox = "markbox" + markNumber;
if (element.getAttribute("checked") == null) {
element.setAttribute("checked", "true");
element.checked = true;
document.getElementById(markbox).classList.add('checked');
} else {
element.removeAttribute("checked");
element.checked = false;
document.getElementById(markbox).classList.remove('checked');
}
}
.mark {
margin-bottom: 5px;
margin-top: 5px;
background-color: #FFFFFF;
border-width: 2px;
border-radius: 0px 5px 5px 0px;
border-left-style: solid;
border-left-width: 10px;
border-color: lime;
overflow: auto;
padding: 2%;
transition: background-color 0.5s linear 0s;
cursor: pointer;
}
.checked {
background-color: #66ff66;
}
.mark:hover {
background-color: #fffcaf;
}
.checked:hover {
background-color: #b3ffb3;
}
.flex-container {
display: -webkit-flex;
display: flex;
align-items: center;
margin: 0px;
padding: 0px;
}
.flex-mark {
width: 85%;
margin: 0px;
}
.flex-tick {
width: 15%;
margin: 0px;
text-align: center;
}
.flex-tick input {
width: 40px;
height: 40px;
}
<div class="mark col-12 col-m-6" id="markbox0" onclick="boxPress(0)">
<div class="flex-container">
<div class="flex-mark">
<p>Candidate introduces themself by first name, surname and role</p>
</div>
<div class="flex-tick"><input type="checkbox" id="mark0"></div>
</div>
</div>

change bPopup options dynamically to disable/enable following

I'm using a jQuery plugin called bPopup , which receives a jQuery object and creates a popup element.
it is constructed using an options element that looks like this:
{
modalClose: false,
modalColor: "#ffffff",
follow: [false, false] // Follow x, follow y
}
I want to change the "follow" property within the popup dynamically, without re-creating the popup or cloning it, but actually changing the existing popup.
in other words: I want the popup to follow when scrolling, and be able to pause that following when desired.
A fiddle displaying the problem:
https://jsfiddle.net/syoels/9tqcaq7m/11/
Thanks a lot in advance!
Ok. It was much simpler than I thought...
just find the popped up div, address it's 'bPopup' data attribute and change the follow property.
Working fiddle with the solution: https://jsfiddle.net/syoels/ydu5s9zu/
$(document).ready(function() {
$('#popupBtn').click(function() {
var popup_div = $('<div id="popup"><p>Holy guacamole! what a gorgeous popup!<br><br>scroll down and see if it follows you</p> <button id="stopFollowingBtn">Toggle follow</button></div>');
popup_div.bPopup({
follow: [true, true], //x, y
opacity: 0.6,
modalColor: 'greenYellow',
});
$('#stopFollowingBtn').click(function() {
var follow_x = $('#popup').data('bPopup').follow[0];
var follow_y = $('#popup').data('bPopup').follow[1];
$('#popup').data('bPopup').follow = [!follow_x, !follow_y];
});
});
});
body {
background: black;
height: 1000px;
}
#popup {
display: none;
position: absolute;
width: 140px;
height: 200px;
background: #ccc;
text-align: center;
border: 2px solid white;
border-radius: 3px;
box-shadow: 3px 3px 2px rgba(0, 0, 0, 0.2);
}
#popupBtn {
display: block;
margin: 10px auto;
}
#stopFollowingBtn {
background: red;
color: white;
font-weight: bold;
cursor: pointer;
padding: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-beta1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bPopup/0.11.0/jquery.bpopup.js"></script>
<body>
<button id="popupBtn">show popup</button>
</body>

Jquery mouseleave & mouseenter issue

How do I allow the user to click on the button that says "click me" appears on mouseenter of another button.
Here is the code -
<div class="hint"> ?</div>
<div class="desc">
This is supposed to appear on hover
This is supposed to appear on hover
This is supposed to appear on hover
This is supposed to appear on hover
<button type="button">
Click me
</button>
</div>
$(document).ready(function() {
var hint = $('.hint');
var desc = $('.desc');
hint.mouseenter(function() {
desc.show();
});
hint.mouseleave(function() {
desc.hide();
});
});
Here is the Demo
Just Place the .desc inside the .hint.
Fiddle
For the basic tooltip, you want:
<div title="This is my tooltip">
For fancier tooltips, See this
Wrap your html with another div and add mouseenter and mouseleave event to this.
var con = $('.container');
var desc = $('.desc');
con.mouseenter(function() {
desc.show();
});
con.mouseleave(function() {
desc.hide();
});
.hint {
padding: 20px;
background: white;
width: 10px;
height: 10px;
border-radius: 50%;
}
.desc {
display: none;
width: 200px;
background: white;
z-index: 3;
border: 1px solid #CCC;
border-radius: 3px;
top: 20px;
left: -5px;
padding: 12px;
color: #666;
font-size: 12px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="hint"> ?</div>
<div class="desc">
This is supposed to appear on hover This is supposed to appear on hover This is supposed to appear on hover This is supposed to appear on hover
<button type="button">
Click me
</button>
</div>
</div>
Make the .desc div a child of your .hint
$(document).ready(function() {
var hint = $('.hint');
var desc = $('.desc');
hint.mouseenter(function() {
desc.show();
});
hint.mouseleave(function() {
desc.hide();
});
});
.hint {
padding: 20px;
background: white;
width: 10px;
height: 10px;
border-radius: 50%;
text-align: center;
position: relative;
}
.desc {
display: none;
width: 200px;
background: white;
z-index: 3;
border: 1px solid #CCC;
border-radius: 3px;
top: 20px;
left: -5px;
padding: 12px;
color: #666;
font-size: 12px;
position: absolute;
top: 50%;
left: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="hint"> ?<div class="desc">
This is supposed to appear on hover
This is supposed to appear on hover
This is supposed to appear on hover
This is supposed to appear on hover
<button type="button">
Click me
</button>
</div></div>
See fiddle
Updated Fiddle.
If you can't change the structure of your HTML code try to wait a little before hidding a desc div using setTimeout() so if the user enter mouse inside this div you will not hide it by clearing the timeout check the example bellow :
$(document).ready(function() {
var hide_timeout;
var hide_after = 100; //100 ms
var hint = $('.hint');
var desc = $('.desc');
hint.mouseenter(function() {
desc.show();
});
hint.mouseleave(function() {
hide_timeout = setTimeout(function(){
desc.hide();
},hide_after);
});
desc.mouseenter(function() {
clearTimeout(hide_timeout);
});
desc.mouseleave(function() {
desc.hide();
});
});
Hope this helps.
$(document).ready(function() {
var hide_timeout;
var hide_after = 100; //100 ms
var hint = $('.hint');
var desc = $('.desc');
hint.mouseenter(function() {
desc.show();
});
hint.mouseleave(function() {
hide_timeout = setTimeout(function(){
desc.hide();
},hide_after);
});
desc.mouseenter(function() {
clearTimeout(hide_timeout);
});
desc.mouseleave(function() {
desc.hide();
});
});
.hint {
padding: 20px;
background: white;
width: 10px;
height: 10px;
border-radius: 50%;
}
.desc {
display: none;
width: 200px;
background: white;
z-index: 3;
border: 1px solid #CCC;
border-radius: 3px;
top: 20px;
left: -5px;
padding: 12px;
color: #666;
font-size: 12px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="hint"> ?</div>
<div class="desc">
This is supposed to appear on hover
This is supposed to appear on hover
This is supposed to appear on hover
This is supposed to appear on hover
<button type="button">
Click me
</button>
</div>
You have 2 options
1 - You can add the show() and hide() when the tooltip is hover : Fiddle
2 - You can use only css to show or hide it. Not sure you need JS for simple things like that.
This Demo shows what I think you want to achieve. The trick is to also catch the event that is triggerd, when the mouse enters a other element.
$('*').not('.hint').not('.desc').not('.desc>button').mouseenter(function() {
desc.hide();
});
$(function(){
$('.desc').hide();
$(document).on('mouseenter','.hint',function(){
$('.desc').show();
})
});

Categories