JQuery: Disable click event - javascript

I want to disable all click events on my page but some of events are still getting called, suppose I have html as below
<div id='parent'>
<table>
<tr>
<td><input type = 'text'/></td>
<td><select><option>A</option><option>B</option></select></td>
<td>Click </td>
</tr>
<tr>
<td>dscsdcd</td>
<td>dscsdcd</td>
<td>dscdscdsc</td>
</tr>
<tr>
<td>sdcdsc</td>
<td>dssdcdsc</td>
<td><input type='submit' value='Button'/></td>
</tr>
</table>
</div>
And script as below
$('#parent').click( function(e)
{
e.stopPropagation();
e.preventDefault();
e.stopImmediatePropagation();
return false;
});
when I click anchor tag, it alerts Called which it shouldn't because I am disabling event for it's parent. Looks like anchor tag is overriding onclick, if it is then how to prevent it? if not, then what could be the solution?
JS Fiddle

Just remove the onclick attribute from elements that have it, and unbind the 'click' event using .off('click') method
$('#parent *[onclick]').removeAttr('onclick').off('click');

onclick attribute has a higher priority here. You can loop your <a> elements and unset this attribute:
$('#parent a').each(function () {
$(this).attr('onclick', '');
}).click(function () {
// ...
});

try this plugin to temporary disable onclick AND jQuery click events:-
$.fn.disableClick = function (disable){
this.each(function() {
if(disable){
if(this.onclick)
$(this).data('onclick', this.onclick).removeAttr('onclick');
if($._data(this, 'events') && $._data(this, 'events').click)
$(this).data('click', $.extend(true, {}, $._data(this, 'events').click)).off('click');
}
else{
if($(this).data('onclick'))
this.onclick = $(this).data('onclick');
if($(this).data('click'))
for(var i in $(this).data('click'))
$(this).on('click', $(this).data('click')[i].handler);
}
});
return this;
};
//disable clicks
$('#parent *').disableClick(true);
//enable clicks
$('#parent *').disableClick(false);
DEMO

There is an attribute you should use to make all things disabled.
var nodes = document.getElementById("parent").getElementsByTagName('*');
for(var i = 0; i < nodes.length; i++) {
nodes[i].disabled = true;
}
Unfortunately disable is not valid with anchor tags.
There you should use :
var nodes = document.getElementById("parent").getElementsByTagName('a');
for(var i = 0; i < nodes.length; i++) {
nodes[i].onclick = function(e){
e.preventDefault();
// YOUR CODES HERE
}
}
try to combine these two methods according to your needs

If you want to disable it for any element under that div you must type:
$('#parent *').click( function(e)
{
e.stopPropagation();
e.preventDefault();
e.stopImmediatePropagation();
return false;
});

Related

Bind event on element that's not in dom

I have a script that adds a <tr> dynamically, outside it seems that the elements contained in it are not recognized by jQuery because it is not yet loaded into the DOM.
I try to use .on function , but it is not working.
Have you an idea ?
$(document).ready(function(){
$("#add_item").click(function(e){
e.preventDefault();
var nbeTr = $(".tablerow").length;
if (nbeTr < 10){
$(".tablerow:last").after("<tr class='filleul'><td></td><td></td><td></td><td><button class='newtr'>X</button></td></tr>");
}
});
$(document).on("click", ".newtr", function(event) {
event.preventDefault();
alert("Yo");
});
});
You'll need to register the event listener when creating the button element. Right now you're trying to register click events to undefined elements.
// create button
$ele = $("<button class='newtr'>X</button>");
// bind event listener to button
$ele.on("click", function() { alert("hello"); });
// insert $ele into DOM
$target.append($ele);
Hey Buck your code is working, I think problem is some where else.
See this working example:
$(document).ready(function() {
$("#add_item").click(function(e) {
e.preventDefault();
var nbeTr = $(".tablerow").length;
if (nbeTr < 10) {
$(".tablerow:last").after("<tr class='tablerow filleul'><td>1</td><td>2</td><td>3</td><td><button class='newtr'>X</button></td></tr>");
}
});
$(document).on("click", ".newtr", function(event) {
event.preventDefault();
alert("Yo");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button id='add_item'>Add item</button>
<table>
<tr class='tablerow'>
<td>c1</td>
<td>c2</td>
<td>c3</td>
<td>
<button class='newtr'>X</button>
</td>
</tr>
<table>
Ok, the problem was a bad version of jQuery was using.
I just use CDN of last jQuery version and refresh cache and it's working.

Apply A Function to All Links on Page

i have my all links on page like this :
Example
But Now I Want All Links With Following OnClick Function like this:
<a onclick="show();" href="http://example.com">Example</a>
can any one tell me jquery or javascript code to add above function to all links on body, thanks
Some answers have suggested to use jQuery's click() function. That's alright as long as you don't expect to add new links dynamically using javascript.
This click handler will bind on the <body> element, and fire whenever a <a> element inside it is clicked. The advantage with this over $('a').click(...) is that all <a> tags don't need to be present on page load:
$(function () {
$('body').on('click', 'a', function (event) {
event.preventDefault();
show();
});
});
Fiddle: http://jsfiddle.net/Lubf6gjw/2/
EDIT: Here's how to do it with pure javascript:
document.querySelector('body')
.addEventListener('click', function (event) {
if(event.target.tagName === 'A') {
event.preventDefault();
show();
}
});
http://jsfiddle.net/pymwsgke/1/
$(function(){
$("a").click(function(){
show();
}
});
If you want to prevent the browser from following the href, you can just add a preventDefault call
$(function(){
$("a").click(function(e){
e.preventDefault();
show();
}
});
Note that this will not actually append the onclick= to the <a> tags. If you want to do that, you can do it this way:
$("a").each(function(){
$(this).attr("onclick", $(this).attr("onclick")+";show();");
});
Using pure Js
function show (event) {
event.preventDefault();
// do somethink
}
var anchors = document.querySelectorAll("a");
for(var a = 0; a < anchors.length; a++) {
anchors[a].addEventListener("click",show,false)
}

JavaScript/Jquery - Copy table row inside a handler

I got a function like this:
function isRowEmpty(){
var emptyRow = true;
var tableRow;
$('#ProblemsGrid').delegate('td a', 'click', function() {
tableRow = $(this).closest ('tr');
});
tableRow.find('textarea').each(function(index, element){
var value = $(element).val();
if(value != "") {emptyRow = false;}
});
return emptyRow;
}
What I'm trying to do is to get the table row that has the that was clicked and check the of that row to see if it's empty, then return true/false. I think the problem I got here has something to do with javascript closure. The var tableRow is not being changed in the outer function. I've been trying to figure out a workaround but no luck. I'm relatively new to JavaScript and Jquery.
Update: Here's how isRowEmpty() is used.
function deleteRow(){
if (isRowEmpty()===true){
$('#ProblemsGrid').delegate('td a', 'click', function() {
$(this).closest ('tr').remove();
});
}
}
Here's part of my HTML:
<tr>
<td><textarea name='text' style='width: 98%; height:40px'>....</textarea></td>
<td><a href='#anchor' name='DeleteButton' onclick='deleteRow();'>
<img src='../images/delete.gif'></img> </a>
</td>
</tr>
You should utilize the power of jQuery when you are using it. I tried to simplify your code:
$('.deleteRow').on('click', function() {
var tr = $(this).closest('tr');
var remove = true;
tr.find('textarea').each(function() {
if ($(this).val() != '') {
remove = false;
}
});
if (remove) {
tr.remove();
}
});
Just add a class deleteRow to your remove button/image and lose your inline event handler (onclick='functionCall())
Example jsFiddle
It seems you're appending your rows dynamically, then your selector should look like this:
$(document).on('click', '.deleteRow', function() {
// ...
});
By the way. From the .delegate docs:
As of jQuery 1.7, .delegate() has been superseded by the .on() method. For earlier versions, however, it remains the most effective means to use event delegation. More information on event binding and delegation is in the .on() method. In general, these are the equivalent templates for the two methods:
Try this:
function deleteRow(){
if (emptyRow){// isRowEmpty returning emptyRow
$('#ProblemsGrid').delegate('td a', 'click', function() {
$(this).closest ('tr').remove();
});
}
}
Try this.
function isRowEmpty(el){
var emptyRow = true;
if(el.val() != "" && el.val() != "....")
emptyRow = false;
return emptyRow;
}
$(document).delegate('#ProblemsGrid td a', 'click', function() {
if (isRowEmpty($(this).closest('tr').find('textarea'))){
$(this).closest('tr').remove();
}
});
Fiddle

Javascript .on event handler

I have the following scenario; in my js I have a dynamic hyperlink that I need to capture the clicked link id.
for (var i = 0; i < neighbor.data[3].length; i++){
<a class="Chris" name="a" id="+i+" href="Chris">Hi</a>
}
Now I can get this with;
parseInt($(this).attr("ID"));
I am using this to capture the it;
$(document).on("click", "a.a", function(event) {
event.stopPropagation();
alert(clickedID);
clickedID = parseInt($(this).attr("ID"));
});
Now, my problem is that everytime I click on the hyperlink instead of only one clickedID I have one for every hyperlink clicked. Is there a way to prevent this?
I believe you are getting every anchor tag because you are setting the event on the document, rather than the anchor tag. Try this instead:
$('a').on('click',function(event) {
event.stopPropagation();
clickedID = parseInt($(this).attr('id'));
alert(clickedID);
});
You have an error in your for loop. Your id="+i+" will just set all anchor tags' IDs to +i+ because you are not escaping the plus sign and the variable i
You may try this, "a.a" should be "a.Chris" because Chris is the class name you have used not a andid should start with a non-numeric character.
for (var i = 0; i < neighbor.data[3].length; i++){
var a='<a class="Chris" name="a" id="id_'+i+'" href="Chris">Hi</a>';
$('#links').append(a);
}
$("#links").on("click", "a.Chris", function(event) { // You can use $(document).on(...) instead of $("#links").on(...)
event.preventDefault();
event.stopPropagation();
clickedID = parseInt($(this).attr("id").split('_')[1]);
alert(clickedID);
});
DEMO.

Trigger a click event on an inner element

A row in a table where each first cell contains a link needs to be clicked and open a url.
<table>
<tr>
<td><a class="fancybox" href="detail.aspx?CID=67525">LT5C260A436C41</a></td>
<td>more data</td>
</tr>
<tr>
<td><a class="fancybox" href="detail.aspx?CID=17522">LA5C260D436C41</a></td>
<td>more data</td>
</tr>
...
</table>
The complete row should be clickable instead of only the link top open the detail page in a fancybox, ie in the page itself.
So I tried to do something like this:
$("table tr").bind('click',function(e) {
e.stopPropagation();
$(this).find("a").trigger('click');
});
But it seems that the event is bubbling recursivly resulting in a:
Uncaught RangeError: Maximum call stack size exceeded
How can I trigger the click on the full row instead of only the link in a proper way avoiding the stackoverflow?
UPDATE: I really appreciate the answers below, but my question is about triggering the event, NOT executing the behaviour inside that event. Workarounds could be nice, but not in this case.
This worked well:
$("table tr").click(function(e) {
var $link = $(this).find("a");
if (e.target === $link[0]) return false;
$link.trigger('click');
return false;
});
EDIT:
Why most solutions don't work — they fail, because when the link was clicked, the immediate handler attached runs. The event then bubbles to see if a handler was attached to a table cell, row, etc.
When you suggest triggering a click you cause the recursion: the link was clicked → fancybox → bubbles → aha! table row → trigger the link click → the link was clicked…
When you suggest to stop propagation, please note that event stops bubbling to parent elements, so a click handler attached to body will not be executed.
Why the code above works — we check if the event bubbled from a link. If true, we simply return and stop further propagation.
See the updated fiddle: http://jsfiddle.net/F5aMb/28/
try
$('table tr').click(function() {
var href = $(this).find("a").attr("href");
if(href) {
window.location = href;
}
});
Try this:
$("table tr a").bind('click', function(e) {
e.preventDefault();
window.open($(this).attr('href'));
return false;
});
$("table tr").bind('click', function(e) {
$(this).find("a").trigger('click');
});
I found what went wrong.
In your code,
$("table tr").bind('click',function(e) {
e.stopPropagation();
$(this).find("a").trigger('click');//This line again triggers a click event binded on the tr ELEMENT which contains the 'a' ELEMENT. So it goes into a infinite loop.
});
Update:
This will do.
$("table tr").bind('click', function(e) {
window.location.href = $(this).find("a.fancybox").attr('href');
});
$(this).find("a").trigger('click'); is actually not triggering the default
anchor tag behavior. It just tries to trigger a click event if a click event
is already bound to that element explicitly.
It may be that I misunderstood your question, but doesn't this do what you need:
$("table tr").click(function(e) {
e.stopImmediatePropagation();
if (! $(e.target).is('a')) {
$(this).find("a").trigger('click');
}
});
For the funny purpose of this exercise, here is a pure js solution, i.e., w/o using jQ lib).
Available here for testing: http://jsfiddle.net/Sr5Vy/3/
<table>
<tr id="node_1">
<td><a class="fancybox" href="detail.aspx?CID=67525">LT5C260A436C41</a></td>
<td>more data</td>
</tr>
<tr id="node_2">
<td><a class="fancybox" href="detail.aspx?CID=17522">LA5C260D436C41</a></td>
<td>more data</td>
</tr>
</table>
function AddEvent(id, evt_type, ma_fonction, phase) {
var oElt = document.getElementById(id);
if( oElt.addEventListener ) {
oElt.addEventListener(evt_type, ma_fonction, phase);
} else if( oElt.attachEvent ) {
oElt.attachEvent('on'+evt_type, ma_fonction);
}
// Debug
// alert('a \'' + evt_type + '\' event has been attached on ' + id );
return false;
}
function getElementsByRegExpOnId(search_reg, search_element, search_tagName) {
search_element = (search_element === undefined) ? document : search_element;
search_tagName= (search_tagName === undefined) ? '*' : search_tagName;
var id_return = new Array;
for(var i = 0, i_length = search_element.getElementsByTagName(search_tagName).length; i < i_length; i++) {
if (search_element.getElementsByTagName(search_tagName).item(i).id &&
search_element.getElementsByTagName(search_tagName).item(i).id.match(search_reg)) {
id_return.push(search_element.getElementsByTagName(search_tagName).item(i).id) ;
}
}
return id_return; // array
}
function FollowSpecialLinks(event) {
// Debug
// alert('event was successfully attached');
// Prevent propagation
event.preventDefault();
// Identify targetted node (eg one of the children of <tr>)
var targetted_elt = ShowEventSource(event);
//alert('Event\'s target : ' + targetted_elt);
// Extract the targetted url
if (targetted_elt == "A") {
var current_link = GetEventSource(event).href;
} else {
var current_tr = GetEventSource(event).parentNode;
var child_links = current_tr.getElementsByTagName('a');
var current_link = child_links[0].href;
}
// Now open the link
if(current_link) {
// Debug
alert('will now open href : ' + current_link);
window.location = current_link;
}
}
function GetEventSource(event) {
var e = event || window.event;
var myelt = e.target || e.srcElement;
return myelt;
}
function ShowEventSource(event) {
var elmt;
var event = event || window.event; // W3C ou MS
var la_cible = event.target || event.srcElement;
if (la_cible.nodeType == 3) // Vs bug Safari
elmt = la_cible.parentNode;
else
elmt = la_cible.tagName;
return elmt;
}
// Get all document <tr> id's and attach the "click" events to them
my_rows = new Array();
my_rows = getElementsByRegExpOnId(/^node_.+/, document , 'tr') ;
if (my_rows) {
for (i=0; i< my_rows.length; i++ ) {
var every_row = document.getElementById( my_rows[i] ) ;
AddEvent(every_row.id, 'click', FollowSpecialLinks, false);
}
}
Try
$(".fancybox").parent('td').parent('tr').bind('click',function(e) {
e.stopPropagation();
$(this).find("a").trigger('click');
});
Have you tried stopping immediate propagation when you click the link?This way you should stop the recursion
$('a').click(function(e){
e.stopImmediatePropagation();
alert('hi');
});
fiddle here: http://jsfiddle.net/3VMGn/2/
In order to compensate for the bubbling, you need to detect the target of the event and not click on the link more than once.
Also, jQuery's "trigger" function won't work for plain links, so you need a specialized click function.
you can try it out at: http://jsfiddle.net/F5aMb/27/
$("table tr").each(function(i, tr){
$(tr).bind('click',function(e) {
var target = $(e.target);
if( !target.is("a") ) {
clickLink($(this).find("a")[0]);
}
})
});
function clickLink(element) {
if (document.createEvent) {
// dispatch for firefox + others
var evt = document.createEvent("MouseEvents");
evt.initEvent("click", true, true ); // event type,bubbling,cancelable
return !element.dispatchEvent(evt);
} else {
//IE
element.click()
}
}
I was able to do it by giving each link a unique ID and then using jQuery to set the click event of that unique ID to redirect the window to the appropriate page.
Here is my working example: http://jsfiddle.net/MarkKramer/F5aMb/2/
And here is the code:
$('#link1').click(function(){
// do whatever I want here, then redirect
window.location.href = "detail.aspx?CID=67525";
});
$('#link2').click(function(){
// do whatever I want here, then redirect
window.location.href = "detail.aspx?CID=17522";
});
$("table tr").click(function(e) {
e.stopImmediatePropagation();
$(this).find("a").trigger('click');
});
You can do what you want with following code. I tested it on you jsfilddle seems working.
$("table tr").click(function(e) {
// check if click event is on link or not.
// if it's link, don't stop further propagation
// so, link href will be followed.
if($(e.target).attr('class')=='fancybox'){
alert('you clicked link, so what next ?.');
// else if click is happened somewhere else than link,
// stop the propagation, so that it won't go in recursion.
}else{
alert('no link clicked, :( ');
alert('now clicking link prgrammatically');
$(this).find('a').click();
e.preventDefault();
}
});
Let me know, if you want to achieve something else than this.
I think .click() or .trigger("click") only fires the event handlers for onclick.
See a sample here http://jsfiddle.net/sethi/bEDPp/4/
. Manually clicking on the link shows 2 alerts while firing the event through jQuery shows only 1 alert.
You can also refer to this link : re-firing a click event on a link with jQuery
Solution
If you are just looking to open a fancybox try this:
$("table tr").bind('click',function(e) {
var elem = $(e.target);
if(elem.is('a')){
return;
}
e.stopImmediatePropagation();
var parent= elem.is('tr') ? elem:elem.parents("tr").eq(0);
parent.find("a").trigger('click.fb');
});
where click.fb is the event that fancybox binds with the anchor element.
$('a.fancybox').click(function(evt){evt.stopPropagation())});
$('table tr:has[.fancybox]').click(function(evt){
$(this).find('.fancybox').trigger('click')
})
I think I have what you're looking for. What you need to do is to call click() on the anchor tag in the handler, and make sure you ignore events from the anchor itself. Also, WebKit doesn't support click(), so you have to implement it yourself.
Notice from the fiddle below that it properly follows the link target, that is, opens a new window, or loads into the same window. http://jsfiddle.net/mendesjuan/5pv5A/3/
// Some browsers (WebKit) don't support the click method on links
if (!HTMLAnchorElement.prototype.click) {
HTMLAnchorElement.prototype.click = function() {
var target = this.getAttribute('target');
var href = this.getAttribute('href');
if (!target) {
window.location = href;
} else {
window.open(href, target);
}
}
}
$("table tr").bind('click',function(e) {
// This prevents the stack overflow
if (e.target.tagName == 'A') {
return;
}
// This triggers the default behavior of the anchor
// unlike calling jQuery trigger('click')
$(this).find("a").get(0).click();
});
My usecase was to trigger a click when a -element was clicked. Checking the type of the target element solves the recursive call problem.
$('#table tbody td').click(function(e){
if ($(e.target).is('td')) {
$(this).find('input').trigger('click');
}
});

Categories

Resources