wierd error : code get executed more than once per click - javascript

i have a like comments system
when i click on the like link sometimes it works fine but some times it sends up to 8-9 request per click ! i have the same problem on another jquery code which works with keydown event
<a href="javascript:void(0);" class="like_comment" ><?php echo $likeLable; ?></a>
$('.like_comment').live('click', function () {
var parent = $(this).parent();
var comment_id = parent.parent().find('.comment_id').val();
parent.fadeOut(200);
$.post("<?php echo base_url(); ?>album/like", {
comment_id: comment_id
},
function (data) {
if ($.trim(data) == 'ok') {
var like_span = parent.parent().find('.like_counter');
var like = parseInt(like_span.text()) + 1;
like_span.text(like);
parent.html('<a href="javascript:void(0);" class="unlike_comment" ><?php echo $unlikeLable; ?></a>');
parent.fadeIn(200);
return false;
} else {
parent.fadeIn(200);
alert(data);
}
})
})
is there anything wrong with this code ?

Try returning true from the event handler to signify that you handled the event. That way noone else will pick it up...
If that doesn't work, then you are probably registering multiple event listeners for the same event. Use your favorite debugger to pause javascript execution, then use the console to inspect all the event listeners on the relevant dom elements.

Its hard to know without seeing the rest of your code and know what element the click is applied to, so one of the following 3 solutions could work:
$('.like_comment').on('click',function(e) {
//do something
e.preventDefault(); // stops default button action, e.g. submitting a form
e.stopPropagation(); // stops event bubbling back to parent element
}
return false; /// stops default link action
});
Also as a by-the-way, live is now deprecated and has been replaced by "on" instead.

Related

Intercept clicks, make some calls then resume what the click should have done before

Good day all, I have this task to do:
there are many, many many webpages, with any kind of element inside, should be inputs, buttons, links, checkboxes and so on, some time there should be a javascript that could handle the element behaviour, sometimes it is a simple ... link.
i have made a little javascript that intercepts all the clicks on clickable elements:
$( document ).ready(function() {
$('input[type=button], input[type=submit], input[type=checkbox], button, a').bind('click', function(evt, check) {
if (typeof check == 'undefined'){
evt.preventDefault();
console.log("id:"+ evt.target.id+", class:"+evt.target.class+", name:"+evt.target.name);
console.log (check);
$(evt.target).trigger('click', 'check');
}
});
});
the logic is: when something is cllicked, I intercept it, preventDefault it, make my track calls and then resme the click by trigger an event with an additional parameter that will not trigger the track call again.
but this is not working so good. submit clicks seams to work, but for example clicking on a checkbox will check it, but then it cannot be unchecked, links are simply ignored, I track them (in console.log() ) but then the page stay there, nothing happens.
maybe I have guessed it in the wrong way... maybe i should make my track calls and then bind a return true with something like (//...track call...//).done(return true); or something...
anyone has some suggestions?
If you really wanted to wait with the click event until you finished with your tracking call, you could probably do something like this. Here's an example for a link, but should be the same for other elements. The click event in this example fires after 2seconds, but in your case link.click() would be in the done() method of the ajax object.
google
var handled = {};
$("#myl").on('click', function(e) {
var link = $(this)[0];
if(!handled[link['id']]) {
handled[link['id']] = true;
e.preventDefault();
e.stopPropagation();
//simulate async ajax call
window.setTimeout(function() {link.click();}, 2000);
} else {
//reset
handled[link['id']] = false;
}
});
EDIT
So, for your example, this would look something like this
var handled = {};
$( document ).ready(function() {
$('input[type=button], input[type=submit], input[type=checkbox], button, a').bind('click', function(evt) {
if(!handled[evt.target.id]) {
handled[evt.target.id] = true;
evt.preventDefault();
evt.stopPropagation();
$.ajax({
url: 'your URL',
data: {"id" : evt.target.id, "class": evt.target.class, "name": evt.target.name},
done: function() {
evt.target.click();
}
});
} else {
handled[evt.target.id] = false;
}
});

Hiding Bootstrap Popover on Click Outside Popover

I'm trying to hide the Bootstrap Popover when the user clicks anywhere outside the popover. (I'm really not sure why the creators of Bootstrap decided not to provide this functionality.)
I found the following code on the web but I really don't understand it.
// Hide popover on click anywhere on the document except itself
$(document).click(function(e) {
// Check for click on the popup itself
$('.popover').click(function() {
return false; // Do nothing
});
// Clicking on document other than popup then hide the popup
$('.pop').popover('hide');
});
The main thing I find confusing is the line $('.popover').click(function() { return false; });. Doesn't this line add an event handler for the click event? How does that prevent the call to popover('hide') that follows from hiding the popover?
And has anyone seen a better technique?
Note: I know variations of this question has been asked here before, but the answers to those questions involve code more complex than the code above. So my question is really about the code above
I made http://jsfiddle.net/BcczZ/2/, which hopefully answers your question
Example HTML
<div class="well>
<a class="btn" data-toggle="popover" data-content="content.">Popover</a>
<a class="btn btn-danger bad">Bad button</a>
</div>
JS
var $popover = $('[data-toggle=popover]').popover();
//first event handler for bad button
$('.bad').click(function () {
alert("clicked");
});
$(document).on("click", function (e) {
var $target = $(e.target),
var isPopover = $target.is('[data-toggle=popover]'),
inPopover = $target.closest('.popover').length > 0
//Does nothing, only prints on console and wastes memory. BAD CODE, REMOVE IT
$('.bad').click(function () {
console.log('clicked');
return false;
});
//hide only if clicked on button or inside popover
if (!isPopover && !inPopover) $popover.popover('hide');
});
As I mentioned in my comment, event handlers don't get overwritten, they just stack. Since there is already an event handler on the .bad button, it will be fired, along with any other event handler
Open your console in the jsfiddle, press 5 times somewhere on the page (not the popover button) and then click bad button you should see clicked printed the same amount of times you pressed
Hope it helps
P.S:
If you think about it, you already saw this happening, especially in jQuery.
Think of all the $(document).ready(...) that exist in a page using multiple jquery plugins. That line just registers an event handler on the document's ready event
I just did a more event based solution.
var $toggle = $('.your-popover-button');
$toggle.popover();
var hidePopover = function() {
$toggle.popover('hide');
};
$toggle.on('shown', function () {
var $popover = $toggle.next();
$popover.on('mousedown', function(e) {
e.stopPropagation();
});
$toggle.on('mousedown', function(e) {
e.stopPropagation();
});
$(document).on('mousedown',hidePopover);
});
$toggle.on('hidden', function () {
$(document).off('mousedown', hidePopover);
});
short answer
insert this to bootstrap min.js
when popout onblur will hide popover
when popout more than one, older popover will be hide
$count=0;$(document).click(function(evt){if($count==0){$count++;}else{$('[data-toggle="popover"]').popover('hide');$count=0;}});$('[data-toggle="popover"]').popover();$('[data-toggle="popover"]').on('click', function(e){$('[data-toggle="popover"]').not(this).popover('hide');$count=0;});
None of the above solutions worked 100% for me because I had to click twice on another, or the same, popover to open it again. I have written the solution from scratch to be simple and effective.
$('[data-toggle="popover"]').popover({
html:true,
trigger: "manual",
animation: false
});
$(document).on('click','body',function(e){
$('[data-toggle="popover"]').each(function () {
$(this).popover('hide');
});
if (e.target.hasAttribute('data-toggle') && e.target.getAttribute('data-toggle') === 'popover') {
e.preventDefault();
$(e.target).popover('show');
}
else if (e.target.parentElement.hasAttribute('data-toggle') && e.target.parentElement.getAttribute('data-toggle') === 'popover') {
e.preventDefault();
$(e.target.parentElement).popover('show');
}
});
My solution, works 100%, for Bootstrap v3
$('html').on('click', function(e) {
if(typeof $(e.target).data('original-title') !== 'undefined'){
$('[data-original-title]').not(e.target).popover('hide');
}
if($(e.target).parents().is('[data-original-title]')){
$('[data-original-title]').not($(e.target).closest('[data-original-title]')).popover('hide');
}
if (typeof $(e.target).data('original-title') == 'undefined' &&
!$(e.target).parents().is('.popover.in') && !$(e.target).parents().is('[data-original-title]')) {
$('[data-original-title]').popover('hide');
}
});

How to capture clicked button in js functions?

I have to buttons like this:
<input type='submit' id='submit' class='processAnimation'>
<input type='reset' id='reset' class='processAnimation'>
Now I have two js function. First function is called when ajax request is started and seconf function is called when ajax request is completed.
this.showLoading = function () {
backupsource = $('.processAnimation').attr('class');
$('.processAnimation').removeAttr('class').addClass('disabled-btn processAnimation');
$('.processAnimation').attr( 'backupsource', backupsource );
}
this.hideLoading = function () {
backupsource = $('.processAnimation').attr('backupsource');
if( backupsource != undefined ) {
$('.processAnimation').removeAttr('class').addClass( backupsource );
$('.processAnimation').removeAttr('backupsource');
}
}
EDIT: Above two functions are working and moving flower replaced clicked button. When request is complete then button is back. Problem is that when I click one button it replace all buttons(class=procesAnimation) with moving flower.
Thanks
Since you haven't posted your click event binding I am going to take a quick guess and say that your selector is not set right or conflicts with another element. try something like this:
$('input').click(function(){
switch( $(this).attr('id') ){
case 'submit' :
ShowLoading();
break;
case 'reset' :
HideLoading();
break;
}
});
and change the syntax of how you initialize the two functions to the following:
function ShowLoading(){
//do your show loading procedure here
};
function HideLoading(){
//do your hide loading procedure here
};
This is using the code u have currently
$('.processAnimation').click(function (){
if($(this).attr('type')=='submit'){
//submit has been clicked
}else{
//reset has been clicked
}
});
but it looks like you should really be using ID's rather than class's
if you have jQuery it is simple
$('#submit').click(showLoading)
$('#reset').click(hideLoading)
Just two different binding of events.
or did I miss something? :)

Why alert popup a few times after a click event?

On a page there are couple of Add buttons (li .plus).
When you click on a Add button and assume json.success is false, it will then popup via $.colorbox plugin
The popup pull the data from href:"/Handle/Postcode/?val" + Val
There is a submit button (#submitButton) from the popup, when I click on the submit button, it keep popup alert box a few times, I dont understand why that happen? how to fix it?
$("li .plus").click(function(event) {
event.preventDefault();
var Val;
Val = $('#id').val()
$.getJSON(Address +"/Handle/Add", {
Val:Val
}, function(json) {
if (json.success == "false" && json.error == "NoArea") {
$.colorbox({
width:"450px",
transition:"none",
opacity:"0.4",
href:"/Handle/Postcode/?val" + Val
});
$("#submitButton").live('click', function() {
var PostCodeArea = $("#deliveryAreaPostcode").val();
alert(PostCodeArea);
//Why does it popup a few times?
});
}
if (json.success == "true") {
Backet();
}
});
});
Thats an easy one, because you are using the .live() function to bind your click handler. If that code gets executed more than one time your binding happens more than one time.
You can either try to track the state of the binding and only apply it if it doesn't exist, or you can call your click function in the html with the onClick attr.
Edit: Just to clarify I meant something along the lines of -
HTML
<button id='submitButton' onclick="displayAreaCode();">Submit</button>
JS
function displayAreaCode(){
var PostCodeArea = $("#deliveryAreaPostcode").val();
alert(PostCodeArea);
}

What is the opposite of evt.preventDefault();

Once I've fired an evt.preventDefault(), how can I resume default actions again?
As per commented by #Prescott, the opposite of:
evt.preventDefault();
Could be:
Essentially equating to 'do default', since we're no longer preventing it.
Otherwise I'm inclined to point you to the answers provided by another comments and answers:
How to unbind a listener that is calling event.preventDefault() (using jQuery)?
How to reenable event.preventDefault?
Note that the second one has been accepted with an example solution, given by redsquare (posted here for a direct solution in case this isn't closed as duplicate):
$('form').submit( function(ev) {
ev.preventDefault();
//later you decide you want to submit
$(this).unbind('submit').submit()
});
function(evt) {evt.preventDefault();}
and its opposite
function(evt) {return true;}
cheers!
To process a command before continue a link from a click event in jQuery:
Eg: Click me
Prevent and follow through with jQuery:
$('a.myevent').click(function(event) {
event.preventDefault();
// Do my commands
if( myEventThingFirst() )
{
// then redirect to original location
window.location = this.href;
}
else
{
alert("Couldn't do my thing first");
}
});
Or simply run window.location = this.href; after the preventDefault();
OK ! it works for the click event :
$("#submit").click(function(event){
event.preventDefault();
// -> block the click of the sumbit ... do what you want
// the html click submit work now !
$("#submit").unbind('click').click();
});
event.preventDefault(); //or event.returnValue = false;
and its opposite(standard) :
event.returnValue = true;
source:
https://developer.mozilla.org/en-US/docs/Web/API/Event/returnValue
I had to delay a form submission in jQuery in order to execute an asynchronous call. Here's the simplified code...
$("$theform").submit(function(e) {
e.preventDefault();
var $this = $(this);
$.ajax('/path/to/script.php',
{
type: "POST",
data: { value: $("#input_control").val() }
}).done(function(response) {
$this.unbind('submit').submit();
});
});
I would suggest the following pattern:
document.getElementById("foo").onsubmit = function(e) {
if (document.getElementById("test").value == "test") {
return true;
} else {
e.preventDefault();
}
}
<form id="foo">
<input id="test"/>
<input type="submit"/>
</form>
...unless I'm missing something.
http://jsfiddle.net/DdvcX/
This is what I used to set it:
$("body").on('touchmove', function(e){
e.preventDefault();
});
And to undo it:
$("body").unbind("touchmove");
There is no opposite method of event.preventDefault() to understand why you first have to look into what event.preventDefault() does when you call it.
Underneath the hood, the functionality for preventDefault is essentially calling a return false which halts any further execution. If you’re familiar with the old ways of Javascript, it was once in fashion to use return false for canceling events on things like form submits and buttons using return true (before jQuery was even around).
As you probably might have already worked out based on the simple explanation above: the opposite of event.preventDefault() is nothing. You just don’t prevent the event, by default the browser will allow the event if you are not preventing it.
See below for an explanation:
;(function($, window, document, undefined)) {
$(function() {
// By default deny the submit
var allowSubmit = false;
$("#someform").on("submit", function(event) {
if (!allowSubmit) {
event.preventDefault();
// Your code logic in here (maybe form validation or something)
// Then you set allowSubmit to true so this code is bypassed
allowSubmit = true;
}
});
});
})(jQuery, window, document);
In the code above you will notice we are checking if allowSubmit is false. This means we will prevent our form from submitting using event.preventDefault and then we will do some validation logic and if we are happy, set allowSubmit to true.
This is really the only effective method of doing the opposite of event.preventDefault() – you can also try removing events as well which essentially would achieve the same thing.
Here's something useful...
First of all we'll click on the link , run some code, and than we'll perform default action. This will be possible using event.currentTarget Take a look. Here we'll gonna try to access Google on a new tab, but before we need to run some code.
Google
<script type="text/javascript">
$(document).ready(function() {
$("#link").click(function(e) {
// Prevent default action
e.preventDefault();
// Here you'll put your code, what you want to execute before default action
alert(123);
// Prevent infinite loop
$(this).unbind('click');
// Execute default action
e.currentTarget.click();
});
});
</script>
None of the solutions helped me here and I did this to solve my situation.
<a onclick="return clickEvent(event);" href="/contact-us">
And the function clickEvent(),
function clickEvent(event) {
event.preventDefault();
// do your thing here
// remove the onclick event trigger and continue with the event
event.target.parentElement.onclick = null;
event.target.parentElement.click();
}
I supose the "opposite" would be to simulate an event. You could use .createEvent()
Following Mozilla's example:
function simulateClick() {
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("click", true, true, window,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
var cb = document.getElementById("checkbox");
var cancelled = !cb.dispatchEvent(evt);
if(cancelled) {
// A handler called preventDefault
alert("cancelled");
} else {
// None of the handlers called preventDefault
alert("not cancelled");
}
}
Ref: document.createEvent
jQuery has .trigger() so you can trigger events on elements -- sometimes useful.
$('#foo').bind('click', function() {
alert($(this).text());
});
$('#foo').trigger('click');
This is not a direct answer for the question but it may help someone. My point is you only call preventDefault() based on some conditions as there is no point of having an event if you call preventDefault() for all the cases. So having if conditions and calling preventDefault() only when the condition/s satisfied will work the function in usual way for the other cases.
$('.btnEdit').click(function(e) {
var status = $(this).closest('tr').find('td').eq(3).html().trim();
var tripId = $(this).attr('tripId');
if (status == 'Completed') {
e.preventDefault();
alert("You can't edit completed reservations");
} else if (tripId != '') {
e.preventDefault();
alert("You can't edit a reservation which is already attached to a trip");
}
//else it will continue as usual
});
jquery on() could be another solution to this. escpacially when it comes to the use of namespaces.
jquery on() is just the current way of binding events ( instead of bind() ). off() is to unbind these. and when you use a namespace, you can add and remove multiple different events.
$( selector ).on("submit.my-namespace", function( event ) {
//prevent the event
event.preventDefault();
//cache the selector
var $this = $(this);
if ( my_condition_is_true ) {
//when 'my_condition_is_true' is met, the binding is removed and the event is triggered again.
$this.off("submit.my-namespace").trigger("submit");
}
});
now with the use of namespace, you could add multiple of these events and are able to remove those, depending on your needs.. while submit might not be the best example, this might come in handy on a click or keypress or whatever..
you can use this after "preventDefault" method
//Here evt.target return default event (eg : defult url etc)
var defaultEvent=evt.target;
//Here we save default event ..
if("true")
{
//activate default event..
location.href(defaultEvent);
}
You can always use this attached to some click event in your script:
location.href = this.href;
example of usage is:
jQuery('a').click(function(e) {
location.href = this.href;
});
In a Synchronous flow, you call e.preventDefault() only when you need to:
a_link.addEventListener('click', (e) => {
if( conditionFailed ) {
e.preventDefault();
// return;
}
// continue with default behaviour i.e redirect to href
});
In an Asynchronous flow, you have many ways but one that is quite common is using window.location:
a_link.addEventListener('click', (e) => {
e.preventDefault(); // prevent default any way
const self = this;
call_returning_promise()
.then(res => {
if(res) {
window.location.replace( self.href );
}
});
});
You can for sure make the above flow synchronous by using async-await
this code worked for me to re-instantiate the event after i had used :
event.preventDefault(); to disable the event.
event.preventDefault = false;
I have used the following code. It works fine for me.
$('a').bind('click', function(e) {
e.stopPropagation();
});

Categories

Resources