jQuery trigger() stopPropagation() not working - bubbling occurring? - javascript

I'm working on a site that has buttons that are generated dynamically.
I'm using jQuery to toggle classes of hidden elements $('.toggle-button').on('click') (i.e. off-canvas cart, sidebar, etc.) based on data attributes
I'm using trigger('click') for the dynamic buttons and passing data through to trigger the correct hidden element. The problem is trigger() is bubbling to other buttons that have class toggle-button or that's what I think the problem is...
I've tried event.stopPropagation() but it doesn't seem to be working.
Here's a simplified version of the code I'm working with.
jQuery(document).ready(function($){
$('.toggle-button').on('click', function(event, triggerData){
console.log('toggle button triggered');
toggleClass = '';
targetSelector = '';
targetElement = '';
if ( !triggerData ) {
toggleClass = $(this).attr('data-toggle');
targetSelector = $(this).attr('data-target');
} else {
toggleClass = triggerData.toggleClass;
targetSelector = triggerData.targetSelector;
}
targetElement = $(targetSelector);
targetElement.toggleClass(toggleClass);
});
$(document).on('click', '.view-cart', function(event){
event.preventDefault();
console.log('view cart button clicked');
$('.toggle-button').trigger('click', {
toggleClass : 'show',
targetSelector : '.cart'
});
});
});
jQuery(document).ready(function($) {
$('.toggle-button').on('click', function(event, triggerData) {
console.log('toggle button triggered');
toggleClass = '';
targetSelector = '';
targetElement = '';
if (!triggerData) {
toggleClass = $(this).attr('data-toggle');
targetSelector = $(this).attr('data-target');
} else {
toggleClass = triggerData.toggleClass;
targetSelector = triggerData.targetSelector;
}
targetElement = $(targetSelector);
targetElement.toggleClass(toggleClass);
});
$(document).on('click', '.view-cart', function(event) {
event.preventDefault();
console.log('view cart button clicked');
$('.toggle-button').trigger('click', {
toggleClass: 'show',
targetSelector: '.cart'
});
});
});
.cart,
.info {
display: block;
padding: 30px;
width: 200px;
border: 1px solid #000;
visibility: hidden;
}
.cart.show,
.info.show {
visibility: visible;
}
.product {
display: inline-block;
width: 150px;
margin: 15px;
background: #e3e3e3;
text-align: center;
}
.product a {
display: block;
padding: 15px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<button class="toggle-button" data-toggle="show" data-target=".cart">View Cart</button>
<button class="toggle-button" data-toggle="show" data-target=".info">View Info</button>
<hr>
<div class="product">
<img src="https://via.placeholder.com/150">
View Cart
</div>
<div class="product">
<img src="https://via.placeholder.com/150">
View Cart
</div>
<div class="product">
<img src="https://via.placeholder.com/150">
View Cart
</div>
<div class="product">
<img src="https://via.placeholder.com/150">
View Cart
</div>
<div class="cart">
<span>This is your cart</span>
</div>
<div class="info">
<span>This is additional info</span>
</div>
</body>
</html>

there are two button with class toggle-button ...whose click event is being triggered correctly - while the problem is, that probably only one of them should be triggered. either select the element to click by a combined class attribute or by id attribute. those events are not bubbling at all, the selector just matches two elements - and that's why it subsequently clicks onto two elements.

Your code has two .toggle-button element, so $('.toggle-button').trigger() is running two times.
I recommend to name different class names of these basically.
But there is a other way not to do so, you can use :first selector as shown below.
https://api.jquery.com/first-selector/
jQuery(document).ready(function($){
$('.toggle-button').on('click', function(event, triggerData){
console.log('toggle button triggered');
toggleClass = '';
targetSelector = '';
targetElement = '';
if ( !triggerData ) {
toggleClass = $(this).attr('data-toggle');
targetSelector = $(this).attr('data-target');
} else {
toggleClass = triggerData.toggleClass;
targetSelector = triggerData.targetSelector;
}
targetElement = $(targetSelector);
targetElement.toggleClass(toggleClass);
});
$(document).on('click', '.view-cart', function(event){
event.preventDefault();
console.log('view cart button clicked');
$('.toggle-button:first').trigger('click', {
toggleClass : 'show',
targetSelector : '.cart'
});
});
});

Related

keep moving an element up and down while mouse button is pressed

Everything works here but I need to keep moving act up and down while mouse button is pressed, without repeated clicks.
Any help?
$('button').on('click', function(){
let a = $('.act');
a.insertBefore(a.prev());
});
$('button').on('contextmenu', function(e){
e.preventDefault();
let a = $('.act');
a.insertAfter(a.next());
});
.act{background:gold;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div class='title act'>LOREM</div>
<div class='title'>IPSUM</div>
<div class='title'>DOLOR</div>
<div class='title'>SIT</div>
<div class='title'>AMET</div>
</div>
<br>
<button>CLICK</button>
Instead of the click and contextmenu events you'll have to use mouse events, here is an example:
let intervalId;
const a = $('.act');
$('button').on('mousedown', function(event) {
function fn () {
if (event.button == 0) {
a.insertBefore(a.prev());
} else if (event.button == 2) {
a.insertAfter(a.next());
}
return fn;
};
intervalId = setInterval(fn(), 500);
});
$(document).on('mouseup', function(event) {
clearInterval(intervalId);
});
$('button').on('contextmenu', function(event) {
event.preventDefault();
});
.act {
background: gold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div class='title act'>LOREM</div>
<div class='title'>IPSUM</div>
<div class='title'>DOLOR</div>
<div class='title'>SIT</div>
<div class='title'>AMET</div>
</div>
<br>
<button>CLICK</button>
In this example, I'm using an interval to move the element every 500 milliseconds while the mouse pointer is down, I'm also preventing the contextmenu event so that the context menu will not consume the mouseup event itself.
I've made a fiddle to illustrate:
https://jsfiddle.net/10cgxohk/
html:
<p class="">x</p>
css:
.move {
animation: MoveUpDown 1s linear infinite;
position: relative;
left: 0;
bottom: 0;
}
#keyframes MoveUpDown {
0%, 100% {
bottom: 0;
}
50% {
bottom: 15px;
}
}
javascript:
$('body').on('mousedown', function() {
$('p').addClass('move');
$('body').on('mouseup', function() {
$('p').removeClass('move');
$('body').off('mouseup');
console.log('here');
})
});
This is really rough and creates an issue if you have other 'mouseup' callbacks on the body, but if that's not a worry for you then it should work. The javascript is adding a class to the element, and the class is animated in css

Hide pop-up by clicking outside it (problems with Philip Waltons solution)

I know the question of closing a pop-up by clicking outside of it has been asked before. I have a somewhat complex pop-up and the solution offered by Phillip Walton isn't working for me.
His code simply made my page blurry but stopped the popup from appearing.
$(document).on('click', function(event) {
if (!$(event.target).closest('.maincontainer').length) {
popup.classList.remove('popup--open');
popup.style.display = 'none';
popupAccessory.style.display = 'none';
popupAccessory.classList.remove('popup--accessory--open');
maincontainer.classList.remove('blurfilter');
}
});
I also tried:
window.addEventListener('click', function(event) {
if (event.target != popup) {
popup.classList.remove('popup--open');
popup.style.display = 'none';
popupAccessory.style.display = 'none';
popupAccessory.classList.remove('popup--accessory--open');
maincontainer.classList.remove('blurfilter');
}
}, true);
This closes the popup when I click anywhere, including on the popup itself. I want it to close only when I click on part of the screen that isn't the popup.
The code to open the popup:
function openpopup() {
popup.style.display = 'initial';
setTimeout(function(){
popup.classList.add('popup--open');
popup.style.boxShadow = '0 0 45px 2px white';
maincontainer.classList.add('blurfilter')}, 10);
for (let i = 0; i < listitems.length; i++ ) {
setTimeout(function() {
listitems[i].classList.add('visible');
}, 100);
}
}
I added the event listener to a button
popupOpenbtn.addEventListener('click', openpopup);
The HTML structure:-
<div class="maincontainer>
...all my page content...
</div>
<div class="popup">
...popup contents...
</div
I would suggest using only css classes to style your popup and use JS only to add, remove and toggle that class. Not sure how close to your working exercise is this fiddle but I've prepared this to show how the document/window click event can be checked to successfully open/close the popup window.
var popupOverlay = document.querySelector('#popup__overlay');
var popupOpenButton = document.querySelector('#popupOpenButton');
var popupCloseButton = document.querySelector('#popupCloseButton');
var mainContainer = document.querySelector('main');
function closestById(el, id) {
while (el.id != id) {
el = el.parentNode;
if (!el) {
return null;
}
}
return el;
}
popupOpenButton.addEventListener('click', function(event) {
popupOverlay.classList.toggle('isVisible');
});
popupCloseButton.addEventListener('click', function(event) {
popupOverlay.classList.toggle('isVisible');
});
mainContainer.addEventListener('click', function(event) {
if (popupOverlay.classList.contains('isVisible') && !closestById(event.target, 'popup__overlay') && event.target !== popupOpenButton) {
popupOverlay.classList.toggle('isVisible');
}
});
#popup__overlay {
display: none;
background-color: rgba(180, 180, 180, 0.5);
position: absolute;
top: 100px;
bottom: 100px;
left: 100px;
right: 100px;
z-index: 9999;
text-align: center;
}
#popup__overlay.isVisible {
display: block;
}
main {
height: 100vh;
}
<aside id="popup__overlay">
<div class="popup">
<h2>Popup title</h2>
<p>
Lorem ipsum
</p>
<button id="popupCloseButton">Close popup</button>
</div>
</aside>
<main>
<div class="buttonWrapper">
<button id="popupOpenButton">Open popup</button>
</div>
</main>

Parent listener $(this) listening to all selected child elements

When user clicks on add an item a new item append on the parent element, then clicking on that item a textarea prompts to edit its text.
HTML DOM / JS Fiddle
<div class="editor"></div>
add an item
<div class="options">
<br><b>Item Text</b> <br>
<textarea class="itemtext"></textarea>
</div>
JS(jQuery) / JS Fiddle
var $item = "<div class='item'>Text here...</div>",
$itembtn = $('a.additem'),
$editor = $('div.editor'),
$opt = $('div.options');
$itembtn.on('click', function(e){
e.preventDefault();
$editor.show();
$editor.append($item);
});
$($editor).on('click', 'div.item', function(){
var $this = $(this);
$opt.show();
$opt.find('textarea').val($this.text());
$opt.find('textarea').on('keyup', function(){
$this.text($opt.find('textarea').val());
});
});
$($editor).on('blur', 'div.item', function(){
$opt.hide();
});
But it seems that $(this) is not pointing to a single clicked element, instead it is pointing to all the clicked/selected child elements!
And also the blur event is not working!
How i can point $this to only one selected item but not all the clicked items?
Well, this was easy...
Change this:
$($editor).on('click', 'div.item', function(){
var $this = $(this);
console.log($this);
$opt.show();
$opt.find('textarea').val($this.text());
$opt.find('textarea').on('keyup', function(){
$this.text($opt.find('textarea').val());
});
});
Into this:
$($editor).on('click', 'div.item', function(){
var $this = $(this);
console.log($this);
$opt.show();
$opt.find('textarea').unbind('keyup').keyup(function(){
$this.text($opt.find('textarea').val());
}).val($this.text());
});
Since you are adding .on([...]) per element, you are adding always a new event listener. You can .unbind() it so it won't be tied to that element. And then you re-bind it.
In this context, using .on() is BAD
One way is to keep a variable of your current 'active' div (clicked div), and use that to set the text.
Fiddle
var $item = "<div class='item'>Text here...</div>",
$itembtn = $('a.additem'),
$editor = $('div.editor'),
$opt = $('div.options'),
$txt = $opt.find('textarea'),
$curtxt;
$itembtn.on('click', function(e){
e.preventDefault();
$editor.show();
$($item).appendTo($editor).click(function(){
$curtxt = $(this);
$txt.val($curtxt.text());
$opt.show();
$txt.select().focus();
});
});
$txt.keyup(function(){
$curtxt.html($txt.val().replace(/\r?\n/g, '<br>'));
}).blur(function(){
$opt.hide();
});
Before adding the keyup event destroy the keyup event you added on click of the div and yes its done
Use $(element).off('keyup') to unbind the previous keyup event and then add the current event using $(element).on('keyup',function).
Check the snippet
var $item = "<div class='item'>Text here...</div>",
$itembtn = $('a.additem'),
$editor = $('div.editor'),
$opt = $('div.options');
$itembtn.on('click', function(e){
e.preventDefault();
$editor.show();
$editor.append($item);
});
$($editor).on('click', 'div.item', function(){
var $this = $(this);
$opt.show();
var txtEd = $opt.find('textarea');
txtEd.val($this.text());
txtEd.off('keyup').on('keyup', function(){
$this.text($opt.find('textarea').val());
});
});
$($editor).on('blur', 'div.item', function(){
$opt.hide();
});
.editor { margin: 20px 0px; border: 1px solid #888; padding: 5px; display: none; }
.item { background: #ccc; margin: 5px; padding: 5px; }
.options textarea { width: 80%; height: 100px; }
.options { display: none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="editor"></div>
add an item
<div class="options">
<br><b>Item Text</b> <br>
<textarea class="itemtext"></textarea>
</div>

show image on link click and hide it when clicked outside

I am trying to show images on a link click and hiding that image if clicked outside. After trying so many solutions for this I have came up with like below code.
<script>
function setImageVisible(id, visible) {
var img = document.getElementById(id);
img.style.visibility = (visible ? 'visible' : 'hidden');
}
</script>
<div id="wrapper" style="margin-top: -5px; text-align:center" align="center" onclick="javascript:setImageVisible('popup1', false)">
<div id="Btn7"></div>
<img id="popup1" class="img_popup1" src="../screenshots/pop-up.png" style="visibility:hidden" />
</div>
The above code is working fine. But when I add other image like below, its not working. When I clicked outside then images are not hiding.
<script>
function setImageVisible(id, visible) {
var img = document.getElementById(id);
img.style.visibility = (visible ? 'visible' : 'hidden');
}
$(document).click(function() {
var img1 = document.getElementById('popup1');
var img2 = document.getElementById('popup2');
img1.style.visibility = 'hidden';
img2.style.visibility = 'hidden';
});
</script>
<div id="wrapper" style="margin-top: -5px; text-align:center" align="center">
<div id="Btn7"></div>
<img id="popup1" class="img_popup1" src="../screenshots/pop-up.png" style="visibility:hidden" />
<div id="Btn8"></div>
<img id="popup2" class="img_popup2" src="../screenshots/pop-up2.png" style="visibility:hidden" />
</div>
Can anyone please suggest what should I do ?
You don't need jQuery to do this.
function setImageVisible(id, visible) {
var img = document.getElementById(id);
img.style.visibility = (visible ? 'visible' : 'hidden');
}
function hideAll() {
var img1 = document.getElementById('popup1');
var img2 = document.getElementById('popup2');
img1.style.visibility = 'hidden';
img2.style.visibility = 'hidden';
}
function click(e) {
e.stopImmediatePropagation();
var id, el = this;
while (el) {
el = el.nextSibling;
if (el.nodeName === 'IMG') { // finds the next sibling img element
id = el.id;
el = null;
}
}
hideAll(); // hide all images
setImageVisible(id, true); // show the right one
};
document.addEventListener('click', hideAll);
var btns = document.querySelectorAll('.btn'),
i = 0,
len = btns.length;
for (; i < len; i++) {
btns[i].addEventListener('click', click);
}
img {
width: 100px;
height: 100px;
border: 1px solid black;
}
<div id="wrapper" style="margin-top: -5px; text-align:center" align="center">
<div class="btn" id="Btn7">Image 1</div>
<img id="popup1" class="img_popup1" src="../screenshots/pop-up.png" style="visibility:hidden" />
<div class="btn" id="Btn8">Image 2</div>
<img id="popup2" class="img_popup2" src="../screenshots/pop-up2.png" style="visibility:hidden" />
</div>
Sure, as you have added a tag jquery, I am asking you to do it in a simple way like this:
Snippet:
$(function () {
$(".imgPreview").hide();
$(".unstyled li a").click(function () {
$(".imgPreview").show().find("img").attr("src", $(this).attr("href"));
return false;
});
$("body").click(function () {
$(".imgPreview").hide();
});
});
* {font-family: 'Segoe UI'; margin: 0; padding: 0; list-style: none;}
body {margin: 10px;}
li {margin: 5px;}
.unstyled, .imgPreview {float: left; width: 50%;}
.unstyled, .imgPreview img {max-width: 100%;}
p {margin: 5px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<p>Click on a link to show the respective image. Click outside to hide it!</p>
<p>Also you can right click and open it to open the image in a new tab!</p>
<ul class="unstyled">
<li>350x150</li>
<li>750x150</li>
<li>350x150</li>
<li>100x100</li>
<li>350x150</li>
</ul>
<div class="imgPreview">
<img src="" alt="" />
</div>
Try this simple demo
<!DOCTYPE html>
<html>
<head>
<script src = "jquery-1.10.2.min.js"></script>
</head>
<body>
Click to show image
<img id="image" style="display:none;height:500px; width:500px;">
<script type="text/javascript">
$('#imageLink').click(function (e){
e.stopPropagation();
$('#image').show();
});
$('body').click(function () {
$('#image').hide();
})
</script>
</body>
</html>
Remove inline event handler and write for common click event ,
1) bind the click event for all a tag inside wrapper id and then show the images when link is clicked
2) bind the click event for document and hide the all images when clicking outside of link
$("#popup1,#popup2").hide();
$("#Btn7,#Btn8").click(function (e) {
e.stopPropagation();
$(this).next().show();
})
$(document).click(function () {
$("#popup1,#popup2").hide();
})
DEMO
$(document).ready(function () {
$("#linkbutton_id").click(function () {
alert("The paragraph was clicked.");
if($("#image").hide())
{
$("#image").show();
return false;
}
});
});
$(document).ready(function () {
$("#div_id").click(function(){
$("#image").hide();
});
});
Code plus output link
https://jsfiddle.net/umxrn0Lg/2/
fullscreen output link
https://jsfiddle.net/umxrn0Lg/3/embedded/result/

create an array with values of selected images

Im trying to gather the images selected, take their values, put them into an array, and then push them to a mysql database.
Here is my current code
$(document).ready(function() {
var startfind = $("body").find('.on').val();
var awnsers = $('.on').map(function() {
return $(startfind).text();
}).get().join(',');
$("img").click(function() {
$(this).toggleClass("on");
});
$('button').click(function() {
alert(awnsers);
});
});
#seasoning {
margin: 8px;
font-size: 16px;
height: 100px;
width: 100px;
}
.on {
padding: 10px;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img src="https://i.imgur.com/7HyU4yh.jpg" id="seasoning" value="0">
<br>
<img src="https://i.imgur.com/OEHCjCK.jpg" id="seasoning" value="1">
<br>
<button>Submit</button>
I can't get the alert to show the values of the items selected.
You can trigger an event when you click on an image
Then listen on that event, an update the answer
use answer when you need it
an I change a little in your html code, that change img's value attr to data-value
============Here is the code and jsFiddle=======================
$(function(){
//catch this values, because you will use these for more than one time
var answers = [];
function getAnswers(){
answers = []; //empty old answers so you can update it
$.map($('.on'), function(item){
answers.push($(item).data('value'));
});
}
//init the answers in case you use it before click
getAnswers();
$(document).on('click', 'img', function(e){
e.preventDefault();
$(this).toggleClass('on');
//trigger the state change when you click on an image
$(document).trigger('state-change');
});
//get answers when event was triggered
$(document).on('state-change', function(e){
getAnswers();
});
$('#btn-show').click(function(){
alert(answers.join(',') || 'nothing was selected');
});
});
#seasoning {
margin: 8px;
font-size: 16px;
height: 100px;
width: 100px;
}
.on {
padding: 10px;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img src="https://i.imgur.com/7HyU4yh.jpg" id="seasoning" data-value="0">
<br>
<img src="https://i.imgur.com/OEHCjCK.jpg" id="seasoning" data-value="1">
<br>
<button id="btn-show">Submit</button>
Please check this code.
$("img").on('click',function() {
$(this).toggleClass("on");
});
$(document).on('click', 'button', function() {
var awnsers = $('.on').map(function() {
return $(this).attr('value');
}).get().join(',');
alert(awnsers);
});
Working fiddle - http://jsfiddle.net/Ashish_developer/6ezf363a/

Categories

Resources