How do I stop .click()? - javascript

I create a button 2 button. "square" and "circle"
When I click square and click circle. Square could not stop working.
<button id="square">square</button>
<button id="circle">circle</button>
Do I need to do?
$('#square').on('click', function () { $("canvas").on({
mousedown: function (e) {
...
},
mousemove: function (e) {
..
},
mouseup: function () {
..
}
}); });
$('#circle').on('click', function () { $("canvas").on({
mousedown: function (e) {
...
},
mousemove: function (e) {
..
},
mouseup: function () {
..
}
}); });

If you add an event listener with jQuery method .on() you can remove this event listener with jQuery method .off() like this:
$('#square').on('click', fnEventHandler); // add ONE on click event listener to #square DOM element
$('#square').off('click'); // remove ALL on click event listeners from #square DOM element
For your specific mockup it could look somehow like this:
$('#square').on('click', function() {
console.log('button#square on click handler'); // just for debug purpose
$('#circle').off('click'); // remove button#circle event listener
// do what ever you want to do after click on #square eg: $("canvas").on(...)
});
$('#circle').on('click', function() {
console.log('button#circle on click handler'); // just for debug purpose
$('#square').off('click'); // remove button#square event listener
// do what ever you want to do after click on #circle eg: $("canvas").on(...)
});
Please click both buttons:
<button id="square">square</button>
<button id="circle">circle</button>
<br>
To reset the behavior click "Run code snippet" again.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Or you make use of the disabled-attribute:
$('#square').on('click', function() {
console.log('button#square on click handler'); // just for debug purpose
$('#circle').prop('disabled', true); // disable button#circle event listener
// do what ever you want to do after click on #square eg: $("canvas").on(...)
});
$('#circle').on('click', function() {
console.log('button#circle on click handler'); // just for debug purpose
$('#square').prop('disabled', true); // disable button#circle event listener
// do what ever you want to do after click on #circle eg: $("canvas").on(...)
});
Please click both buttons:
<button id="square">square</button>
<button id="circle">circle</button>
<br>
To reset the behavior click "Run code snippet" again.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
The snippets above should illustrate whats going on in essence.
The snippet below shows an advanced way to add, remove and re-add event listeners in a somehow more generic way.
(function( $ ) {
var oHasEventListener = {},
removeEventListener = function( sKey ) {
// sanitize sKey first
if ( !oOnClickHandler[ sKey ] ) {
return console.log('sKey: "' + sKey + '" is not available'); // just for debug purpose
}
if ( oHasEventListener[ sKey ] ) {
$('#' + sKey).off('click').prop('disabled', true);
oHasEventListener[ sKey ] = false;
console.log('button#' + sKey + ' on click listener removed'); // just for debug purpose
}
},
addEventListeners = function() {
for ( sKey in oOnClickHandler ) {
if ( !oHasEventListener[ sKey ] ) {
$('#' + sKey).on('click', oOnClickHandler[ sKey ]).prop('disabled', false);
oHasEventListener[ sKey ] = true;
console.log('button#' + sKey + ' on click listener added'); // just for debug purpose
}
}
},
oOnClickHandler = {
square: function() {
console.log('button#square on click event catched'); // just for debug purpose
removeEventListener('circle');
// do what ever you want to do after click on #square eg: $("canvas").on(...)
},
circle: function() {
console.log('button#circle on click event catched'); // just for debug purpose
removeEventListener('square');
// do what ever you want to do after click on #circle eg: $("canvas").on(...)
},
reset: addEventListeners
};
addEventListeners(); // add event listeners on startup
})( jQuery )
<button id="square">square</button>
<button id="circle">circle</button>
<button id="reset">reset</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
If you need some further explanations please feel free to leave a comment.

Related

How to stop propagating from event handler in JavaScript?

I have a button that triggers an event on a click. Then I have a subscriber to that event. Inside the subscriber's event handler if certain condition is true then I want to stop processing everything inside button's click event.
I tried calling e.preventDefault(), e.stopPropagation() and e.stopImmediatePropagation() but nothing works.
$("#btn").click(function() {
// trigger event
console.log("triggering event");
$(document).trigger("response.beforeSave");
//I want to stop processing after this when subscriber invokes preventDefault() or
//stopPropagation()
console.log("after trigger. This should not get invoked.");
})
$(document).off("response.beforeSave").on("response.beforeSave", function(e) {
console.log("start subscriber");
if (true) // if condition is true
{
//e.preventDefault();
//e.stopPropagation();
e.stopImmediatePropagation();
return;
}
console.log("exit subscriber. This should not get invoked.");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn" type="button">Click Me</button>
You should create your own Event Object and pass that to the .trigger rather than a string with the event name.
This will allow you to check what happened to the event.
An example exists on the jQuery trigger page
var event = jQuery.Event( "submit" );
$( "form" ).first().trigger( event );
if ( event.isDefaultPrevented() ) {
// Perform an action...
}
Here's your code updated to match:
$("#btn").click(function(e) {
// trigger event
console.log("triggering event");
// create a new event object
var beforeSaveEvent = jQuery.Event("response.beforeSave");
$(document).trigger(beforeSaveEvent);
if (beforeSaveEvent.isImmediatePropagationStopped()) {
console.log("event stopped");
// can also check beforeSaveEvent.isDefaultPrevented
// can also check beforeSaveEvent.isPropagationStopped
// e is the click event - function(e) above
// could also use `event` here
// "cancel" the click event
e.stopPropagation();
return;
}
console.log("after trigger. This should not get invoked.");
})
$(document).off("response.beforeSave").on("response.beforeSave", function(e) {
console.log("start subscriber");
if (true) // if condition is true
{
// whichever is used, check the equivalent event.isXXX
//e.preventDefault();
//e.stopPropagation();
e.stopImmediatePropagation();
return;
}
console.log("exit subscriber. This should not get invoked.");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn" type="button">Click Me</button>
To put it simple, here's a suggestion by passing arbitrary data (a boolean in your case) via the second parameter of .trigger("EventNamespace", [])
$("#btn").on("click", function(evt) {
const canSave = document.querySelector("[name=canSave]").checked;
$(document).trigger("response.beforeSave", [{canSave}]);
console.log(`Handler before: canSave is ${canSave}`);
if (!canSave) return;
console.log(`Handler after`);
});
$(document).on("response.beforeSave", function(evt, data) {
if (!data.canSave) return;
console.log(`Subscriber: canSave is ${data.canSave}`);
});
<label><input type="checkbox" name="canSave"> toggle "canSave"</label><br>
<button id="btn" type="button">Click Me</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
PS: place $(document).trigger before (like in the example) or after the if(canSave) statement - depending on what you need.

Add onblur attribute back after removing it

I have a textbox that uses onblur and ondblclick - when they double click it opens a pop screen but I don't want the onblur to be triggered.
When the double click function is called I removed the onblur attribute to stop it getting triggered. This works but now I'm trying to add the onblur back after the pop up opens but it's not working
function OpenCust(v) {
$('#<%= txtDebtor.ClientID %>').removeAttr('onblur');
shadowboxopen = true;
if (!v || 0 === v.length) {
}
else {
Shadowbox.open({
content: "lookups/Customer.aspx?NODEBT=true&CustomerAC=" + v,
player: "iframe",
onClose: function () { shadowboxopen = false; },
title: "Edit Customer"
});
}
$('#<%= txtDebtor.ClientID %>').attr('onblur');
}
edit:
Changed code to use on and off for the blur function but the onblur is still getting triggered when the double click OpenCust is being called.
textbox: <asp:TextBox runat="server" ID="txtDebtor" onblur="CheckIfAccountCodeDebtValid(this.value)" ondblclick="OpenCust(this.value)"></asp:TextBox>
function OpenCust(v) {
$('#<%= txtDebtor.ClientID %>').off('blur', CheckIfAccountCodeDebtValid(v));
shadowboxopen = true;
if (!v || 0 === v.length) {
}
else {
Shadowbox.open({
content: "lookups/Customer.aspx?NODEBT=true&CustomerAC=" + v,
player: "iframe",
onClose: function () { shadowboxopen = false; },
title: "Edit Customer"
});
}
setTimeout(function() {
$('#<%= txtDebtor.ClientID %>').on('blur', CheckIfAccountCodeDebtValid(v));
}, 2000);
}
You will have to specify the value of the onblur when re-adding it. The correct functions in jQuery to do this are on() and off(). In the example below you can see how I remove the blur event handler after clicking on the button but after 2 seconds ill add it again. If the button loses focus within these 2 seconds there won't be a blur console message. If it loses focus after it does.
//Add blur event handler to the button
$('#button').on('blur', blurFunction);
//Add click event handler to the button
$('#button').on('click', function() {
//Remove blur event handler
$('#button').off('blur', blurFunction);
console.log('click');
setTimeout(function() {
//reattach blur event handler after 2 seconds
$('#button').on('blur', blurFunction);
}, 2000);
});
//The actual blur event handler function
function blurFunction() {
console.log(this.value);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="button" type="button" value="test-value">
With the function that uses a parameter you can wrap it in an anonymous function like in below snippet.
//Add blur event handler to the button
$('#button').on('blur', function() {
CheckIfAccountCodeDebtValid(this.value);
});
//Add click event handler to the button
$('#button').on('click', function() {
//Remove all blur event handlers
$('#button').off('blur');
console.log('click');
setTimeout(function() {
//reattach blur event handler after 2 seconds
$('#button').on('blur', function() {
CheckIfAccountCodeDebtValid(this.value);
});
}, 2000);
});
//The actual blur event handler function
function CheckIfAccountCodeDebtValid(value) {
console.log(value);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="button" type="button" value="test-value">

Override jQuery on click handler function

I'm a newbie when it comes to jQuery and I'm hoping if there's a way to override an existing on click function.
The code is as follows:
$('.woo-star-rating').on('click', function() {
$('.woo-star-rating-filled').width( $(this).attr('data-rating') * 25 )
});
and I'd like to change the number 25 to 21 inside my own .js file.
$('.woo-star-rating').on('click', function() {
$('.woo-star-rating-filled').width( $(this).attr('data-rating') * 21 )
});
You can remove the existing click event handler using the .off() method add your new click event.
var $rating = $('.woo-star-rating');
$rating.off('click');
$rating.on('click', function() {
$('.woo-star-rating-filled').width( $(this).attr('data-rating') * 21 )
});
This can be chained into:
$('.woo-star-rating').off('click').on('click', function() {
$('.woo-star-rating-filled').width( $(this).attr('data-rating') * 21 )
});
Here's a working example:
// add junk event
$('#test-button').on('click', function() {
console.log('first button click');
});
// remove first event
$('#test-button').off('click');
// add new event, only this will fire on click
$('#test-button').on('click', function() {
console.log('second button click');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="test-button">Test Button</button>

How to "Hijack" jQuery events and then trigger the default handler on some condition

I am trying to do something like Hijack the jQuery events of some elements, do a judgement, and then trigger the default handler if necessary.
Say I have a page with some inputs and buttons, and each of them are already bind with event handlers(click, focu key events, etc.) to do their jobs.
What I want to achieve is: whenever these elements' events are fired, I'd like to trigger my function first, this function will gather some data, and judge whether the execution should continue.
If no the corresponding handler should not be called like nothing happened.
If yes the original handler should be triggered with the original event data.
I don't want to change the default handlers to achieve this, so, is there a good way to do something like this?
Thanks
You could use the internal method _data()
/* add some event handlers */
$("button").on("click", function() {
console.log("Button clicked");
});
$("button").on("click", function() {
console.log("Button clicked 2");
});
/* hijack them */
var button = $("button"),
boundEvents = $._data(button.get(0)).events;
$.each(boundEvents, function(key, eventHandlers) {
// save the handlers from being "destroyed" by .off()
eventHandlers = eventHandlers.map(function(eh) {
return eh.handler;
});
// remove the event handlers
button.off(key);
// add the hijacked version
$.each(eventHandlers, function(idx, handler) {
button.on(key, function(e) {
if ($("#cb").prop("checked")) {
handler(e);
} else {
console.log("nothing to do...");
}
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type="checkbox" id="cb" />
<br />
<button>Click me</button>
Try defining function at .data() of each that has events attached which is called at if condition within handler. If function returns true , do stuff , if function returns false do not do stuff
$("div").on("click", function() {
// if `check` returns `true`, do stuff
if ($(this).data().check()) {
console.log(this.tagName)
}
});
$("input").on("focus", function() {
// if `check` returns `true`, do stuff
if ($(this).data().check()) {
console.log(this.tagName)
}
});
var elems = $("*").filter(function(i,el) {
return $._data(el).events !== undefined
})
elems.each(function(i, el) {
$(el).data().check = function() {
// define condition here
// if element has `css` `color` property set to `"blue"`
// return `true`, else return `false`
if ($(el).css("color") === "rgb(0, 0, 255)") return true
else return false
}
});
div {
color:blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div>click</div>
<input type="text" />
<span>text</span>

jQuery how to bind event to element which is deleted and added again

I am using jQuery and a modal library named jQuery.Modal. I have a customize function to show this modal in order to fit the UI design:
show: function (option) {
var view = new Modal.View();
sdhapp.modalRegion.show(view);
$(".sdh-ui.modal-header").html(option.title);
$(".sdh-ui.modal-body").empty();
if (option.image) {
if (option.image === 'error') {
$(".sdh-ui.modal-body").append(
'<div class="image-box" style="background-image: url(images/error-icon.png)"></div>');
}
}
if (option.confirmButton === true) {
$(".sdh-ui.modal-footer").html(
'<button type="button" id="modal-confirm-button">Confirm</button><button type="button" id="modal-cancel-button">Cancel</button>');
}
$(".sdh-ui.modal-body").append(option.body);
$('#error-modal-form').modal({
showClose: false
});
bindModalEvents(option);
}
Where view is Marionette view that renders the modal body.
I am binding the click events:
$('#modal-cancel-button').on('click', function () {
unbindModalEvents();
$.modal.close();
if (option.cancel)
option.cancel.call();
});
$('#modal-confirm-button').on('click', function () {
unbindModalEvents();
$.modal.close();
if (option.confirm)
option.confirm.call();
});
$('#modal-ok-button').on('click', function () {
unbindModalEvents();
$.modal.close();
if (option.ok)
option.ok.call();
});
and unbind it:
var unbindModalEvents = function(){
console.log('called');
$('#modal-cancel-button').unbind('click');
$('#modal-confirm-button').unbind('click');
$('#modal-ok-button').unbind('click');
};
the problem is that the click event ( the close function ) is only triggered once. If I the modal is shown for a second time, the click events is not triggered
I tried to remove the element, using "bind" instead of "on" but nothing works
Any advice?
When you close the modal, it's deleted from the DOM. That means that any event handlers bound to will also disappear. Try this:
$('body').on('click', '#modal-cancel-button', function () {
unbindModalEvents();
$.modal.close();
if (option.cancel)
option.cancel.call();
});
$('body').on('click', '#modal-confirm-button', function () {
unbindModalEvents();
$.modal.close();
if (option.confirm)
option.confirm.call();
});
$('body').on('click', '#modal-ok-button', function () {
unbindModalEvents();
$.modal.close();
if (option.ok)
option.ok.call();
});
This binds the handler to the body, which then watches for events that originate from modals. You can add and create as many as you'd like and the handler won't get deleted.

Categories