JavaScript event handling code get's called multiple times - javascript

I need your help. I'm currently working with a modal lib in JavaScript to display a modal for my customers:
https://github.com/vodkabears/Remodal/tree/1.1.1
Unfortunately my event handling in case the user clicks a button don't works like expected. When you take a look into the manual, you can see under the point Events the following event handler:
$(document).on('cancellation', '.remodal', function () {
console.log('Cancel button is clicked');
});
This one get's triggered for example when the cancel button get's pressed. Because I'm using one popup for multiple things, I need to attach the event handler to the call directly. So first I've wrote a function that opens the popup:
function openRemodal( remodalId ) {
let remodal = $( `[data-remodal-id=${remodalId}]` );
remodal.remodal().open();
return remodal; // <- added to handle events
}
I can call this function that way:
openRemodal( 'information-remodal' );
To get an event handling done, I've now returned the remodal in the function and re-wrote my call:
openRemodal( 'information-remodal' ).on( 'cancellation', function () {
alert( 'Test' );
} );
This seems to work but somehow when I repeat the opening of the popup and pressing the button, the alert get's shown multiple times increased by any new opening.
I'm not sure why this happens and why. Can you please help me get this working? I just want to call any function in there once - any time.

JQuery has a .one method ... try using that in place of .on. The callback should run only once. https://api.jquery.com/one/

On each time when you open model you attach function to cancelation event. so add new function and you never remove it. after first time you have one, then you have two... etc.
just attach it once, or remove it after handling event.
const modal = openRemodal( 'information-remodal' )
const handler = () => {
alert( 'Test' );
modal.off('cancellation', handler);
}
modal.on( 'cancellation', handler);

Related

Javascript function executing too many times

This is how i populate the table
I'm having some trouble with the datatables plugin for jquery. The table is populated dynamically, I have 3 columns with text and a fourth column which consists of a delete and an edit button. For the edit button I have a modal, and if I confirm the changes, it does indeed change the specific line in the table.
However, if I click on several edit buttons and cancel, when I actually want to change one it changes all the previously canceled lines.
Here is the relevant code:
$("#example").on("click", ".edit-button", function() {
$("#edit-modal").modal("show");
saveChanges(this);
});
function saveChanges(k) {
$("#edit-confirm").click(function() {
$(".itm-loader-modal").show();
setTimeout(function() {editJob(k);},1000);
});
}
function editJob(currentButton) {
$(".itm-loader-modal").fadeOut("slow");
var editedName = $("#job-name").val();
var editedDescription = $("#job-description").val();
var editedCompany = $("#job-company").val();
var data = {
"name":editedName,
"description": editedDescription,
"company": editedCompany
};
var currentLine = $(currentButton).parent().parent().children();
currentLine.eq(0).text(data.name);
currentLine.eq(1).text(data.description);
currentLine.eq(2).text(data.company);
$("#edit-modal").modal("hide");
}
Hard to say for sure, but one think that looks wrong is that each time saveChanges is called, you register new event listener on #edit-confirm button.
Once that #edit-confirm is clicked, it will execute all the registered event handlers – one for each .edit-button click.
Instead, you probably want to have a single #edit-confirm click handler and find a way to pass the info about the line that's currently being edited to it.
Cheers.
so when you call saveChanges it assign event handler to "#edit-confirm", all those event handlers are executed at once,
to avoid it you should attach event handler to it via delegation or i think this quick fix should work
$(this).find('#edit-confirm').click(function() {
/...
})

After second triggered function button inside execute code twice

I make a game and I have problem that I cant solve.
I have function and inside I have buttons with .click(). After I execute function for second time buttons clicks execute code twice for example I post here some simple code with same problem.
When I click 1st button alert is triggered once. When I click 2nd and then 1st button alert is triggered twice. I want trigger alert just once. Buttons must stay in function. Sorry for bad English.
Also jsfiddle here https://jsfiddle.net/o2gxgz9r/25237/
function testf() {
$("#1").click(function() {
alert("test");
});
$("#2").click(function() {
testf();
});
}
testf();
You need to unbind the click event before bind,
function testf() {
$("#1").unbind('click');
$("#1").click(function() {
alert("test");
});
$("#2").unbind('click');
$("#2").click(function() {
testf();
});
}
testf();
Somehow this function is binding your event twice. changing anything here removes the issue
$(".address_field").each(function(index){
var widget = new AddressFinder.Widget(this, "WR3NUKVGC4Q97FPHBJXL");

Removing/hiding a select option in javascript without making it look awkward (need to delay the native onclick event of the select element)

code:
https://dl.dropboxusercontent.com/u/16952797/webdev/uppg1/kontakt.html
http://jsfiddle.net/v8uMJ/ (the result box does not succesfully render the page or reproduce the bug)
relevant code:
function addEvent(element, eventType, theFunction, capture)
{
if(element.addEventListener)
{
element.addEventListener(eventType, theFunction, capture);
}
else if(element.attachEvent)
{
element.attachEvent( "on" + eventType, theFunction);
}
}
function removeDefaultOption(event)
{
document.getElementById("selectSuggestion").options[0].style.display = "none"; // <-- looks awkward
//document.getElementById("selectSuggestion").remove(0); // <-- also looks awkward and needs boundaries so that all options don't get removed after each click
//delay(1000); // <-- tried delaying the thread but it didn't work..
//setInterval(function(){},1000); // <-- tried delaying the thread but it didn't work..
}
function addEventListeners()
{
...
addEvent(document.getElementById("selectSuggestion"), "click", removeDefaultOption, false);
}
context: So what I'm trying to do is whenever you click on the select element in the suggestion form (swe: Förslag) I want the first option (value: --Välj Förslag--) to disappear from the list. The problem is that the options are displayed "too fast" so I either need to a) delay the displaying of the options after setting the style.display of the first option or b) I need to prevent the default event of clicking on select and then override it with my own function so I can control when it should be run (I don't know the name of the native function that is run when you click on the select element).
Use the "focus" event instead of the "click" event. This fires the function direclty when it's in focus instead of "waiting" for the click to be completed.
Cleaned JS-fiddle: http://jsfiddle.net/vhS3p/1/
document.getElementById("selectSuggestion").addEventListener("focus", removeDefaultOption, false);
Try removing the option you want like so:
var index = 0;
var select = document.getElementById("selectSuggestion");
select.removeChild(select[index]);

The mouseEvent in a function fires twice if call again?

The problem is I would like to fire only once when the mouseevent function is triggered, e.g.
$(document).ready(function() {
$("#menu").click(function(){
$('#menu_div').show();
menu_function();
});
$("#menu_close").click(function(){
$('#menu_div').hide();
});
});
function menu_function(){
$(".select_li").live(
"click",
function() {
alert("test");
}
);
}
The example has two objects, menu and menu close; when the menu press, the ui box is shown, and run the menu_function , which fires an alert test message. The problem is when the menu_close is clicked and box closed, and open it again, the alert test will fire twice. I observe that the times of div box close and open again is the same as the fire times of the function, how can I fix it?
If I would like not using unbind, are there any better solution?
Your menu_function() is NOT just firing an alert test message - it is adding a live click listener to everything in the DOM that has a class of "select_li" that fires a test alert. This means that every time you click on #menu you are adding ANOTHER listener to .select_li - so if you click #menu 10x, you should have 10 listeners for each click of .select_li.
If you are truly trying to JUST show an alert when you click on #menu, your menu_function() should only look like this:
function menu_function() {
alert("test");
}

jQuery preventDefault() doesn't work like I expect - is this a jQuery Bug?

This is simplified code to exactly reproduce a problem I'm having with jQuery.
I would expect it to cancel the original click, then trigger the click event again which in turn would cause the browser to load the href of the url.
<script type="text/javascript">
$( function()
{
var confirmed = false;
$('a').click( function( event )
{
if ( confirmed == false )
{
event.preventDefault();
confirmed = true;
$(event.target).trigger( 'click' );
}
});
});
</script>
Original Question Here
I do not want to change window.location. I want to trigger so that any event handlers that have been bound to the click event will fire too. It just so happens that I also want the browser to follow the link.
.trigger('click') won’t trigger the browser’s default action — it will just trigger jQuery event handlers bound to that event on that element.
Take a look at this answer — you need to create and fire a click event yourself. Here’s the code from that answer:
function fireEvent(obj,evt){
var fireOnThis = obj;
if( document.createEvent ) {
var evObj = document.createEvent('MouseEvents');
evObj.initEvent( evt, true, false );
fireOnThis.dispatchEvent( evObj );
} else if( document.createEventObject ) {
var evObj = document.createEventObject();
fireOnThis.fireEvent( 'on' + evt, evObj );
}
}
Your event handler will always be run when you trigger a "click" event, and before the default behavior happens. So no, it's not a bug.
edit — If you want the default action to happen when the element is clicked and your various conditions are satisfied, just return from your handler.
$('a').click( function( event )
{
if ( confirmed == false )
{
event.preventDefault();
confirmed = true;
}
else
return;
});
When your handler returns, the browser will carry on with the default behavior.
edit again — and of course if you want to simply carry out programmatically the default action of an <a> tag with an "href" attribute, it's just:
window.location = $(element).attr('href');
No need for a "click" event at all.
preventDefault() doesn't cancel the jquery bound click action; it cancels the 'default' click action that is inherent to an anchor tag. unbind() is the proper function for canceling any action/function that is bound to an object.
It looks like you have one state where you want to inhibit the default action (and update a flag), and another state where you simply want the default action to apply. Wouldn't removing the else case entirely do the trick? With no preventDefault() the default click action will still run.
Edit: Pointy's answer now shows your code updated similarly.
Edit: I'm still not entirely sure what you're going for, but if for some reason you must trigger manually, one way to prevent a stack overflow due to recursion would be to assign a custom event (i.e., not click), and then always suppress the default action. Then in your conditional, either do or don't fire the custom event.
So, something like this (untested):
$('a')
.bind('fancyclick', function () { // Your special click logic
changeStatusOf( confirmed );
doCrazyStuff();
location.replace( $(this).attr('href') ); // or whatever
})
.click( function (e) {
e.preventDefault(); // Always suppress natural click
if ( confirmed ){
$(this).trigger('fancyclick'); // Fire the special click
}
});
I'll simply write while I analyse, hoping it'll be easy to follow and easy to compare to your code. Kick me when I can optimize/enhance my replies in any way.
checking - part 1
Move the "preventDefault" outside of the "if" statement! If you don't move it outside of the "if", the code will skip the "preventDefault" if confirmed == true.
<script type="text/javascript">
$( function()
{
var confirmed = false;
$('a').click( function( event )
{
event.preventDefault();
if ( confirmed == false )
{
confirmed = true;
$(event.target).trigger( 'click' );
}
});
});
</script>
checking - part 2
Besides that, I'm wondering about the existence of "var confirmed" in general. The code would also work flawless without it since you're not using the confirmed variable in the function anywhere else...
<script type="text/javascript">
$( function()
{
$('a').click( function( event )
{
event.preventDefault();
$(event.target).trigger( 'click' );
});
});
</script>
checking - part 3
Knowing you can replace the trigger with a simple click, did you try that?
<script type="text/javascript">
$( function()
{
$('a').click( function( event )
{
event.preventDefault();
$(event.target).click();
});
});
</script>
checking - part 4
If the click still fails on the target element, it's definitely time to inspect (using "FireBug on Firefox" or alike) if "event.target" holds an object at all. You never know...
checking - part 5
One more thing: I don't see any Document Ready checking, so I hope you've put that script at the end of your file, right before the "</body>" tag. If you load it in the "<head>" without checking Document Ready, it might happen that javascript tries to bind the event to an element that is yet to be loaded into the dom... which would be like throwing feathers against a 9 Inch steel plate... nothing will happen. ;)
that's all
That's all that comes to mind as an answer to your question. One of them could fix the issue you're having. At least, that's what I hope. These little snippets here at stackoverflow leave massive probabilities related to what we don't see. It's hard to be sure what might be missing when you don't have the "complete view". ;)
How about doing something like creating a link offscreen that would handle the final click? That way, you can prevent the click of the original link, handle the code, then proceed to trigger the click of the hidden copy.

Categories