Preventing event bubbling (for javascript onclick events) - javascript

I am using javascript to interact with a CMS which provides a button for users to add things to their basket.
However, I am using the javascript to try and prevent the customer from doing so unless they have made a selection from a drop-down menu elsewhere on the page.
As there are many different buttons that could potentially get them to the basket (including the example below) and all of which have different methods for doing so, rather than write many lines of code to prevent each method and then re-enable that method when a selection is made I am trying to do a kind of 'catch-all' fix where I just cover any such buttons / links with another div so as to effectively 'mask' the button below it until they make a decision.
I first tried to use absolute positioned divs to do this which works beautifully until the user does something like re-size a textbox on the page and then suddenly my absolutely positioned div is in the wrong place!!
So I'm now using JQuery's .wrap() which solves this problem nicely.. BUT.. Now I can't use z-index to position the div above the required buttons as those buttons are within the mask not below it!
I have done a lot of reading about event bubbling but I am not sure whether I've not found the right information yet, or maybe I understand it correctly or possibly that event bubbling is leading me down the wrong path all together as I can't seem to take those concepts and apply them to this scenario.
so.....
given the following HTML structure:
<div class="btnMask">
<div class="button">
<a onclick="pageSubmit();return false;" href="#" id="addToBasket">
<span>Add to Basket</span>
</a>
</div>
</div>
where the div with class="btnMask" is added by my javascript.
Plus the following JQuery:
$('.btnMask').click(function() {
// prevent default actions and alert the customer to select something;
});
How do I go about stopping the tag firing when clicking the .btnMask div?
and (in case the answer to that does not make the answer to my other question obvious...)
How would I switch that on and off ? (I have a function that checks the drop-down onchange and sets the z-index to 99 / -99 so I would want to change this to incorporate this new method.)
Thank you in advance for your help.
<< EDIT >>
Using the initial answers to this I managed to solve the problems for links that take you away from the page using a regular href.
So I have now fixed the links where the HTML is like the following:
<div class="btnMask">
<div class="button">
<a id="nextPage" href="/link/toanotherpage.asp?id=667868465726122926234">
<span>Click to go to Page 2</span>
</a>
</div>
</div>
However, like I said there are many methods being used to take people away from the page and and e.preventDefault(); and e.stopPropagation(); don't work for my original example (presumably because they use an onclick rather than a href ?).
Is there a way to do the same thing as e.preventDefault(); and e.stopPropagation(); are doing on my .btnMask div but will also deal with contained links that are being trigged by an onclick?
thanks
<< EDIT >>
Updated the question title to reflect the exact issue rather than just event bubbling on regular links.

If you want to prevent event bubbling and cancel default action then you can return false from the event handler.
$('.btnMask').click(function() {
return false;
});
Or use preventDefault and stopPropagation
$('.btnMask').click(function(e) {
e.preventDefault();
e.stopPropagation();
});

$('.btnMask').click(function(e) {
e.stopPropagation();
});

Your onclick handler is fired before your jquery click handler. You can do something like this
function pageSubmit() {
alert('pageSubmit');
}
var link = document.getElementById('addToBasket');
var linkClickHandler = link.onclick;
link.onclick = null;
$('.button').data('linkClickHandler', linkClickHandler);
$('.button').on('click', function(e){
var clickHandler = $(this).data('linkClickHandler');
var link = $(this).find('a').get(0);
clickHandler.apply(link, [e]);
});
$('.btnMask').on('click', function(e){
if (!$(this).hasClass('test')) {
e.preventDefault();
e.stopPropagation();
}
});
and the html as
<div class="button">
<a onclick="pageSubmit();return false;" href="#" id="addToBasket">
<div class="btnMask test">
<span>Add to Basket</span>
</div>
</a>
</div>
If you remove the class test from btnMask div the pageSubmit handler will not be called,
and when it is present the handler is called.

Related

continue click action after preventDefault [duplicate]

How could one trigger the default action/event of a HTML link (anchor element)? That is to use JavaScript/jQuery to "click" an existing HTML link, as if the user has clicked it.
Just using .click() does not seem to work.
$('#alink').click();
// the nothing happening
For this HTML:
<a id="alink" href="http://google.com" target="_blank">a link</a>
Example fiddle: http://jsfiddle.net/dCfD8/
I'd rather not create a new window in JavaScript (and take care of whatever else needs to be handled when a link is clicked).
You can trigger the click event using a simple trigger method in jQuery.
$('#alink').trigger('click');
Beware though, that even in the event gets fired, the browser will not follow the link href. The only way to follow the href is to actually click it with the mouse yourself.
As far as I know, there is no way to force a link to behave as if it were clicked. You have to change the document location or something like that to actually navigate between pages.
Expanding on Fabio Cicerchia's comment to his own post: You can use window.open:
var link = $('#alink');
var target = link.attr("target");
window.open(link.attr("href"), target ? target : "_self");
<script src='jquery lib source' ></script>
<script>
function force()
{ ...do something...to fill page2
$('#gopage2').trigger('submit');
}
</script>
<form action='#page2' id='gopage2'>
</form>
...
<span name='#page2'>This is page2</span>
try this:
$('#alink').trigger('click');

Bootstrap onClick button event

This seems a silly question but just got bootstrap and it doesn't gives any examples on the website about adding a Javascript callback to a button...
Tried setting my button an id flag and then
<div class="btn-group">
<button id="rectButton" class="btn">Rectangle</button>
<button class="btn">Circle</button>
<button class="btn">Triangle</button>
<button class="btn">Line</button>
<button class="btn">Curve</button>
<button class="btn">Pic</button>
<button class="btn">Text</button>
<button class="btn">Gradient</button>
</div>
I want to add a callback to Rectangle button...
$('#rectButton').on('show', function (e) {
//ACTION
})
cant get the point of bootstrap callbacks.
All I could found on the web is oriented to Rails + Bootstrap... no bootstrap and JS only.
There is no show event in js - you need to bind your button either to the click event:
$('#id').on('click', function (e) {
//your awesome code here
})
Mind that if your button is inside a form, you may prefer to bind the whole form to the submit event.
If, like me, you had dynamically created buttons on your page, the
$("#your-bs-button's-id").on("click", function(event) {
or
$(".your-bs-button's-class").on("click", function(event) {
methods won't work because they only work on current elements (not future elements). Instead you need to reference a parent item that existed at the initial loading of the web page.
$(document).on("click", "#your-bs-button's-id", function(event) {
or more generally
$("#pre-existing-element-id").on("click", ".your-bs-button's-class", function(event) {
There are many other references to this issue on stack overflow here and here.

Click event listener for dynamic/moving anchors

I'm using a tutorial plugin - http://particlebits.com/code/jquery-tutorial/
which has this code attached to the number of tutorial steps you require.
<div for="tutstep4" data-target="#publishbutton" data-arrow="tc" data-location="tr" style="display: block; ">
<h1>Almost Done!</h1>
<p>
Now click "Publish" and you are done.
</p>
</div>
My question is how do I trigger a click event from the the tags that are attached to each tutorial step.
<a id="tutorial-done" class="tutorial-button" href="javascript:void(0);" style="display: block; ">Done!</a>
<a id="tutorial-cancel" class="tutorial-cancel" href="javascript:void(0);">X</a>
<a id="tutorial-next" class="tutorial-button" type="button" href="javascript:void(0);" style="display: none; ">Next</a>
<a id="tutorial-prev" class="tutorial-button" type="button" href="javascript:void(0);" style="display: block; ">Prev</a>
These tags are moved between steps with the same Id's so if I call
$('.tutorial-button').click(function(){
do something
})
the button has already been clicked and the function doesn't register.
I dont want to edit the tutorial.js file as it's used across different pages.
Is there something I can do to 'listen' to when '#tutorial-prev' is clicked and then call a function based on the div it' attached to?
i.e. if '#tutorial-prev' is clicked when the tutorial step is 3, do something ?
UPDATE:
After stepping away from it for a while I found an easier solution that simply use a monkey patch on the functions within the script and add my own personal code which consists of opening/closing the required div.
So it was like
$.fn.tutorialNext() {
// start of original next code.
//end of original code.
myfunc();
}
Not exactly pretty but a quick solution for the one page where I required something customised.
The issue I originally faced was that the anchor tags had already been removed when the Next() function was run so there was no element to perform the function on.
I'm not sure if I have clear what you are trying to achieve, but when you have the click handler:
$("'#tutorial-prev").on("click", dosomething);
In do something you can replicate the click event everywhere you want with:
$(selector).trigger("click");
with the js you posted, you bind the click event to every button with the tutorial-button class.
You could further specify a single button by using the element's id, for which you would need to bind one callback to each button.
$('#tutorial-prev').click(function(){ //go to previous step });
$('#tutorial-next').click(function(){ //go to next step });
$('#tutorial-cancel').click(function(){ //cancel actions });
...
UPDATE:
After stepping away from it for a while I found an easier solution that simply use a monkey patch on the functions within the script and add my own personal code which consists of opening/closing the required div.
So it was like
$.fn.tutorialNext() {
// start of original next code.
//end of original code.
myfunc();
}
Not exactly pretty but a quick solution for the one page where I required something customised.
The issue I originally faced was that the anchor tags had already been removed when the Next() function was run so there was no element to perform the function on.

Why does clicking a link go to the top of the page?

This may sound a weird question,
I have a page which has a link:
<a href="#" class="emails" > Email to Friends </a>
Now I have an event attach to the anchor tag so that on click the given div toggle it state.
The Javascript Code look like this:
$(document).ready(function() {
$(".emails").bind("click",function() {
$("div#container").toggle
})
})
Now the above code and all of it works fine,
but here the big deal,
when I click the given link the my focus of the page move to top of the page,
and I have to scroll all the way down to see the change.
Can anyone help me on this?
It does this because the href="#" is an empty anchor. Anchors are used for linking to specific spots within a page. An empty anchor results in the page going back to the top.
To fix this in your javascript, you need to prevent the click event from propagating or "bubbling" up the DOM. You can do this by returning false from your click event.
$(document).ready(function() {
$(".emails").bind("click",function() {
$("div#container").toggle();
return false; // prevent propagation
})
});
You can also make the event available in the bind's click handler function by using an argument, usually named e. Having access to the event allows you to call methods on it such as .preventDefault().
$(document).ready(function() {
$(".emails").bind("click", function(event) {
$("div#container").toggle();
event.preventDefault(); // this can also go at the start of the method if you prefer
})
});
This will solve all cases where anchor is empty.
$(document).ready(function () {
$('a').click(function () {
$('[href = #]');
return false;
});
});
This comes from the href='#' in the a. Just remove this tag. But then it's technically not a link any more, so the cursor will default to a text-selector when over it. You can override this using cursor:pointer in your CSS. See the left menu on this website for reference.
Use:
<a href="javascript:void(0)" class="emails" > Email to Friends </a>
Or, using jQuery,
$(document).ready(function() {
$(".emails").attr("href","javascript:void(0)");
})
Void(0) returns a.. well.. it doesn't return anything. The browser knows how to go to nothing (i.e., what would happen if you did href=""), and to # (# is the top of the page), but not how to go to a void "value".
Whenever you put a javascript: in an attribute, the attribute's value gets set to the return value of the code inside. The code is called the first time the attribute is accessed.
But, void(0) returns nothing. Not even "". The browser takes this to meant that the link is not a link at all.

How to use javascript onclick on a DIV tag to toggle visibility of a section that contains clickable links?

Hi I've got a DIV section that has only its title visible initially. What I would like to achieve is that when the visitor clicks anywhere on the area of toggle_section the toggle_stuff div toggles between visible/hidden.
<div id="toggle_section"
onclick="javascript: new Effect.toggle('toggle_stuff', 'slide');">
<div id="toggle_title">Some title</div>
<div id="toggle_stuff">
some content stuff
Some link
</div>
</div>
However, the way it is set-up right now, if I have any <a> link within the toggle_section, clicking that link will also execute the onclick event.
Then my question is what would be the best way to set this type of behavior?
The most simple solution is to add an extra onclick handler to the link within your DIV which stops event propagation:
<div id="toggle_section"
onclick="javascript: new Effect.toggle('toggle_stuff', 'slide');">
<div id="toggle_title">Some title</div>
<div id="toggle_stuff">
some content stuff
<a href="/foo.php"
onclick="Event.stop(event);"
>Some link</a>
</div>
</div>
The above example uses Prototype's Event.stop() function in order to facilitate a cross browser event propagation stop.
As you use the inline onclick() handler, most (if not all) browser will traverse the event in the bubbling phase first (which is what you want).
A good guide to understanding the actual reasons behind this behaviour and the differences between event capturing and event bubbling can be found at the excellent Quirksmode.
in script :
function overlayvis(blck) {
el = document.getElementById(blck.id);
el.style.visibility = (el.style.visibility == 'visible') ? 'hidden' : 'visible';
}
activator link, followed by content (no reason that couldn't be else on the page):
<div onclick='overlayvis(showhideme)">show/hide stuff</div>
<div id="showhideme">
... content to hide / unhide ...
</div>
I got this from Modal window javascript css overlay - had to search for the source and was pleased to find it was this site. :)
After I posted my first question I could not wait to try to think about it once more and it seems that I have found a quite simple way to achieve this.
I have moved the onlick Effect.toggle into a separate function like:
function someClick(event) {
if (event.target.nodeName == 'A') {
return;
} else {
new Effect.toggle('toggle_stuff', 'slide');
}
}
I suppose this would only work for A tags and not anything else that is clickable though.
I don't really know if this would work, but try giving the link element a bigger z-index value than the toggle_section div.
something like :
#toggle_section a { z-index: 10; }
Add an onclick handler to stop event propagation.
With JQuery use:
onclick="event.stopPropagation()"
With Prototype use:
onclick="Event.stop(event)"

Categories