Accordion preventing click on link - javascript

I have an accordion with a link in it, but whenever I click on the link, the accordion thinks I'm trying to close it. It's set up so you can click anywhere on the accordion to open or close it which I would like to keep, but when I person clicks on the link, ignore the accordion behavior and follow the link instead.
<div class="wrap">
<div class="top"></div>
<div class="middle">
<h3>Always showing</h3>
<div class="hidden">
<p>I want to follow this link.</p>
</div>
</div>
<div class="bottom"></div>
</div>
$('.wrap').on(touchClick, function (e) {
if ($(this).hasClass('active')) {
$(this).removeClass('active');
$(this).find('.hidden').slideUp('fast');
return false;
}
$('.wrap').each(function (index, el) {
$(this).removeClass('active');
$(this).find('.hidden').slideUp('fast');
});
$(this).find('.hidden').slideDown('fast');
$(this).addClass('active');
});

Not tested but I believe this will work
$('.wrap').on(touchClick, function (e) {
//other code
});
$( "a" ).click(function( event ) {
event.stopPropagation();
});
It should stop the click from bubbling up and triggering the accordion events.
As an afterthought if you want use touchClick like youre accordion you could rewrite it as.
$( "a" ).on(touchClick, function (e) {
e.stopPropagation();
});

You will need to tell the browser to stop the event from bubbling up the event chain using event.stopPropagation() (see this so post for more details on this). This means that jQuery never gets to know about the click event, thus it won't close the accordion.
Add this in the specific link's click event listener and it should work as you want it to:
$('.wrap a').each(function(e){
e.stopPropagation(); // stop the event from bubbling up
});
However, don't confuse it with event.preventDefault(), which would not stop the event from bubbling up, but it would stop the browser from opening the link when it's clicked.

Related

Is there any way to make these link inside another link work

I have the following markup:
<a class="list-group-item hola" id="competition-card-<%= competition.id %>" href="a_url_to_a_site">
<div class='row'>
<div class='col-xs-11'>
Some text
</div>
<div class='col-xs-1 shows-submenu'>
Some text
</div>
</div>
</a>
I'm trying to achieve:
If user clicks the 'a' tag he is directed to a site, except when...
user clicks the '.shows-submenu' div a hidden div is displayed.
My jQuery is as follows:
$('body').on('click', '.shows-submenu', function(e) {
event.stopImmediatePropagation();
if ($(this).closest('a.list-group-item').next('.hidden-group-item').hasClass('hide')) {
$('.hidden-group-item').addClass('hide');
$(this).closest('a.list-group-item').next('.hidden-group-item').toggleClass('hide');
}
else {
$(this).closest('a.list-group-item').next('.hidden-group-item').toggleClass('hide');
}
});
Currently, if I click '.shows-submenu' div the 'a' tag is still called and I'm directed to the site.
As I'm using bootcards plugin I can't change the 'a' tag to a div, for example.
Is there any way to stop 'a' only when clicking the '.shows-submenu' div. I've tried using stopPropagation in both 'a' and the 'div' without success.
What you are looking for is event.stopPropagation() that will prevent bubbling and event.preventDefault that will avoid the default behavior for links onClick.
Fortunately, in jQuery returning false inside the click handler function will fire both. More on the subject here: https://stackoverflow.com/a/1357151/670377
So you just need to modify your function as:
$('document').on('click', '.shows-submenu', function(e) {
if ($(this).closest('a.list-group-item').next('.hidden-group-item').hasClass('hide')) {
$('.hidden-group-item').addClass('hide');
$(this).closest('a.list-group-item').next('.hidden-group-item').toggleClass('hide');
}
else {
$(this).closest('a.list-group-item').next('.hidden-group-item').toggleClass('hide');
}
// This will be equivalent to
// e.preventDefault; e.stopPropagation;
return false;
});
event.stopImmediatePropagation has another purpose than just stopping the default functionality, it will also prevent all the remaining listeners of the element from being called.
I think what you want is event.preventDefault(). Both event.stopPropagation() and event.stopImmediatePropagation() will affect other event handlers but not the default behavior of an anchor. Also you should declare the argument as event if that's how you're referring to it inside the function:
$('.show-submenu').on('click', function(event) {
event.preventDefault();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="http://example.com">this follows link
<div class="show-submenu">this does not</div>
</a>

Event propagation issue

I have a series of click events which are causing me some propagation issues. The data for this container is loaded in via ajax hence the body on click method. Here's the code I have:
$(function () {
$("body").on("click","#top-div",function(){
console.log("top event");
});
$("body").on("click","#middle-div",function(e){
e.stopPropagation();
});
$("body").on("click","#bottom-div",function(){
console.log("bottom event");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="top-div">
top
<div id="middle-div">
middle
<div id="bottom-div">
bottom
</div>
</div>
</div>
The top div has an event which the middle one needs to not inherit hence the stopPropagation(). However the bottom one needs to have an event of its own but the stopPropagation() from the middle one is stopping it from executing the event (if I remove the stop propagation the bottom event triggers but coincidentally so does the top)
How can I get around this bubbling issue?
I think what you want to happen is that the propagation is only stopped if it originated from the middle div; if it originated from the bottom div you want the event to bubble all the way to the top.
You need to call stopPropagation conditionally. If the event did not originate on or inside #bottom-div, you want to call it. You can test for this using closest:
if (!$(e.target).closest('#bottom-div').length) {
e.stopPropagation();
}
It is better to use closest for this, rather than testing the element's id directly, because with closest it will continue to work as expected even if there are other elements (a or em, for example) within the various divs.
$(function () {
$("body").on("click","#top-div",function(){
console.log("top event");
});
$("body").on("click","#middle-div",function(e){
if (!$(e.target).closest('#bottom-div').length) {
e.stopPropagation();
}
});
$("body").on("click","#bottom-div",function(){
console.log("bottom event");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="top-div">
top
<div id="middle-div">
middle
<div id="bottom-div">
bottom
</div>
</div>
</div>
Bubbling works from most nested element to tree root, I think You misunderstanding it in some way. So for example click in bottom-div will:
call event on bottom-div --> call event on middle-div --> call event on top-div.
As I understand the need You want to some how check what div was clicked, so to have control on it just create single event and check clicked target like that:
$("body").on("click","#top-div",function(e){
if ( e.target.id ==='top-div'){
//click in top div
}
if ( e.target.id ==='middle-div'){
//click in middle div
}
if ( e.target.id ==='bottom-div'){
//click in bottom div
}
});
In this proposition You know exactly which div was clicked, but it will always be the most nested one, so target will be middle-div only when will be clicked part of middle-div which is not bottom-div, it will be for example padding space, the same is with top-div it will be target only if click will be in space without child elements.
More about event bubbling You can find in http://maciejsikora.com/standard-events-vs-event-delegation/.
Instead of attaching event to every div. You can consider doing it as follows
check this snippet
$(document).ready(function() {
$("body").on("click", "div", function(event) {
console.log(event.currentTarget.id + "event");
if (event.target.id === "middle-div") {
event.stopPropagation()
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="top-div">
hello
<div id="middle-div">
hi
<div id="bottom-div">
bott-mid-v
</div>
</div>
</div>
Hope it helps

Element on element gets clicked both by Javascript

I've got a div which has multiple elements nested. If I press on the div, the buttons appear in the same DIV. If I press on the button however, the buttons dissapear as well (this is because of a toggleClass on the div)
I've tried returning but that isn't working as well. See below for a JSFiddle
http://jsfiddle.net/p168uLv2/
$(document).on('click', "[data-link=level1]", function() {
console.log("li clicked");
$(this).find(".knoppenbalk").toggleClass("displaynone");
});
$(document).on('click', "[data-link=solo]", function() {
console.log("solo BUTTON clicked");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-link="level1" class="limodeknop">
<div class="overlay"></div>
<div class="modeknop">
<div class="titel">
<lrmodenaam>Level 1</lrmodenaam>
<lrsubmode>Tutorial</lrsubmode>
</div>
<div class="knoppenbalk displaynone">
<div data-link="solo" class="solo btn">Solo</div>
</div>
</div>
</div>
This is made with jQuery, and I'm working with Framework7, but I don't think thats an issue.
You should stop the propagation of the events (calling bubbling). You can search tons of articles about it.
http://jsfiddle.net/p168uLv2/1/
$(document).on('click',"[data-link=solo]", function(e){
console.log("solo BUTTON clicked");
e.stopPropagation();
});
This only apply to the child element, to avoid the parent click propagation.
You can stop an event propagating to parent elements with use of:
event.stopPropagation();
You will want to accept event as an argument to your inline functions.
$(document).on('click',"[data-link=solo]", function(e){
e.stopImmediatePropagation();
console.log("solo BUTTON clicked");
})
;

Close Toggle on outside click

I'm still quite new to javascript and JQuery...How do I get this div to close by clicking outside the toggle area (I don't want the user to have to use a close button)
the code looks like this:
function toggleDiv(divId) {
$("#"+divId).toggle();
}
function showonlyone(thechosenone) {
$('.newnote').each(function(index) {
if ($(this).attr("id") == thechosenone) {
$(this).show(0);
}
else {
$(this).hide(0);
}
});
}
and the html looks like this
<div class="note">
<a id="myHeader1" href="javascript:showonlyone('newnote1');" >
<img src="images/SN_NotesPage_14.png">
</a>
<div class="newnote" id="newnote1">
<a>
<img src="images/SN_NotesPage_16.png">
</a>
</div>
</div>
thank you
What I usually do is adding a click event listener to the document body which closes the overlay. To prevent closing the overlay by clicking on it I add a second click event listener to the overlay which contains ev.stopPropagation();
So with jQuery it would look like:
$(document.body).bind('click.closeNote', function() {
$('.newnote').hide();
});
$('.newnote').bind('click.closeNote', function(ev) {
ev.stopPropagation();
});
Another way is to add a transparent div (with a lower zIndex than the note) which covers the whole page. You could then add a click event listener to this div which closes the note.
Edit:
Please note, that the example above is not very performant as it executes a selector on every click. Just bind this event when a note is shown and unbind it when they get closed.

Jquery - hide on click anywhere on document

I have a div that hides whenever you click outside of it but I'm having some trouble getting certain links inside the div to work (and not hide the div).
$(document).click(function() {
fav.hide();
});
theDiv.click(function(e) {
e.stopPropagation();
});
That is what I have for the whole clicking outside and closing event. Heres the thing: I have two types of links in my div, one regular link and another which is a javascript one. The regular one redirects OK but the javascript one doesn't do anything.
Could somebody help me out? Thanks.
EDIT:
Here are the bits of my code that might help out
var fav = $('#favorites');
// Open & close button
$('#favorites_a').click(function(e) {
e.stopPropagation();
e.preventDefault();
fav.toggle();
});
$('a.c',fav).live('click', function(e) {
alert('hey');
});
$(document).click(function() {
fav.hide();
});
fav.click(function(e) {
e.stopPropagation();
});
HTML (built after page load):
<div id="favorites">
<div class="wrap">
<ul><li>AB</li></ul>
</div>
</div>
This could be a problem with the live() click event handler. When you use live the event handler is actually attached to the document. So the event needs to bubble up to the document, but your click event handler on fav prevents bubbling up.
It works with delegate though:
fav.delegate('a.c', 'click', function(e) {
alert('hey');
});
Here, the event handler is added to fav.
DEMO
I think your code for fav is preventing the 'B' link from working. Instead of .live(), try:
$('a.c').click(function() { ... });
instead.

Categories