jQuery.off() is not removing binding - javascript

For some reason jQuery.off('click') doesn't seem to be working here. When the 'Yes' button is clicked in the model another model just pops up. What am I doing wrong?
code:
$(function(){
//If there are warnings on the page bind alert
if ($('.renewal-warning').length > 0){
(function (){
$('#signRentalContainer').on('click', '.renewal-warning', function(e){
var buttonHandle = this;
//Prevent submission
e.preventDefault();
//Show warning model
$.modal({
content: $('#renewalWarning').html(),
title: "Order Renewal Warning",
buttons: {
'Yes': function(win) { $(buttonHandle).off('click').click(); },
'No': function(win) { win.closeModal(); }
},
maxWidth: 250,
closeButton: false
});
});
})();
}
});

Pretty sure you're going to need to provide it the same element, as well as the same selector.
$('#signRentalContainer').off('click', '.renewal-warning');
In the .on() handler, this is the '.renewal-warning' element that was clicked, not the #signRentalContainer element.
If there are several of these '.renewal-warning' elements, and you only want to disable one at a time, the simplest way is to change its class so that it no longer matches the selector.
$(this).removeClass('renewal-warning')
.addClass('renewal-warning-disabled');

Because the this refer to the context of the handle function, not the function itself.
Try making it a named function, then refer to it when you call off:
$("body").off("click", '#signRentalContainer', buttonHandle);
BTW, any reason we can't use unbind directly here?
$("#signRentalContainer").unbind("click");

Related

Adding an on event to an e.currentTarget?

A variety of elements on my page have the content editable tag.
When they are clicked I do this:
$('[contenteditable]').on('click', this.edit);
p.edit = function(e) {
console.log(e.currentTarget);
e.currentTarget.on('keydown', function() {
alert("keydown...");
});
};
I get the current target ok, but when I try to add keydown to it, I get the err:
Uncaught TypeError: undefined is not a function
It's a native DOM element, you'll have to wrap it in jQuery
$(e.currentTarget).on('keydown', function() {
alert("keydown...");
});
e.currentTarget should equal this inside the event handler, which is more commonly used ?
It's a little hard to tell how this works, but I think I would do something like
$('[contenteditable]').on({
click : function() {
$(this).data('clicked', true);
},
keydown: function() {
if ($(this).data('clicked'))
alert("keydown...");
}
});
Demo
First issue is you are trying to use jQuery methods on a DOM element. Second issue is I do not think you want to bind what is clicked on, but the content editable element itself.
It also seems weird to be adding the event on click instead of a global listener. But this is the basic idea
$(this) //current content editable element
.off("keydown.cust") //remove any events that may have been added before
.on('keydown.cust', function(e) { //add new event listener [namespaced]
console.log("keydown"); //log it was pressed
});
Edited: I had a fail in code. It works fine now.
Getting your code, I improved to this one:
$(function(){
$('[contenteditable]').on('click', function(){
p.edit($(this));
});
});
var p = {
edit: function($e) {
console.log($e);
$e.on('keydown', function() {
console.log($(this));
alert("keydown...");
});
}
}
You can check it at jsFiddle
You need to wrap the e.currentTarget(which is a native DOM element) in jQuery since "on" event is a jQuery event:
$(e.currentTarget).on('keydown', function() {
alert("keydown...");
});
EDIT:
$('[contenteditable]').on('click', p.edit);
p.edit = function(e) {
$(e.currentTarget).on('keydown', function() {
alert("keydown...");
});
};
You're defining p.edit AFTER $('[contenteditable]').on('click', p.edit); resulting in an error since p.edit doesn't exist when declaring the on.
In case you don't know, you are defining p.edit as a function expression, meaning that you have to define it BEFORE calling it.

Add onRightClick to JavaScript lib Hypertree

I'm currently working (a repo is here) on a Hypertree graph, which I want to use from the JavaScript InfoVis Toolkit. The issue is as follows: I added the specific events to the Hypertree, which are onClick and onRightClick.
Events: {
enable: true,
onClick: function(node, eventInfo, e) {
ht.controller.onComplete();
},
onRightClick: function(node, eventInfo, e) {
ht.controller.onComplete();
},
},
Then I simply attached the veent handlers to the Hypertree labels, just modifying demo-code a little:
//Attach event handlers and add text to the
//labels. This method is only triggered on label
//creation
onCreateLabel: function(domElement, node){
domElement.innerHTML = node.name;
$jit.util.addEvent(domElement, 'click', function () {
ht.onRightClick(node.id, {
onComplete: function() {
ht.controller.onComplete();
}
});
});
$jit.util.addEvent(domElement, 'rclick', function () {
ht.onClick(node.id, {
onComplete: function() {
ht.controller.onComplete();
}
});
});
},
That's pretty straight forward. The documentation for Hypertree events is in Options.Events.js. Now I load the page... and I have the left.clicks. But no right clicks... I want the RightClicks to move the graph and the onClicks to open a link from the DOM Element node. Can someone please give me a pointer here?
Best,
Marius
$jit.util.addEvent(obj, type, fn) is a shortcut for obj.addEventListener(type, fn, false). So you are trying to bind to 'onrclick' event. But there is no such event in javascript. For detecting right click you just need to replace your 'rclick' to 'mouseup', and in callback you should check for button to be the right one. Here is the code:
$jit.util.addEvent(domElement, 'mouseup', function (event) {
// detecting right button
if (event.button != 2) {
return;
}
ht.onClick(node.id, {
onComplete: function() {
ht.controller.onComplete();
}
});
});
Also you don't need to use Options.Events.js for this purpose, so you can remove that code
The only fault I can see in the "Events"-section, is a trailing comma behind onRightClick. It really shouldn't affect the code if you use IE>8, but it's worth a try.
Ok, this is an answer on why I think your solution is not working.
$jit.util.addEvent(domElement, 'rclick', function ()
There is no such jquery event as 'rclick'.
Typically using jquery you would detect a right-click using the following:
$('#element').mousedown(function(event) {
if (event.which === 3) {
alert('Right mouse button pressed');
}
});
Hence in your example you would use 'mousedown' instead of 'rclick'. However, looking at the documentation for addEvent:
$jit.util.addEvent(elem, 'click', function(){ alert('hello'); });
The example seems to suggest that the event object can not be passed in to addEvent's function parameter, meaning that it won't be possible to detect that the right mouse button has been clicked.
Might be worth posting your question directly to InfoVis' author, as I too will be interested to see whether it is possible to hook-up the right mouse button.

On() and off() - Jquery

Trying to understand Jquery's On() and off() a little better. Not understanding why this is not working. I want to activate and inactivate id TurnON and TurnOff Js.
Javascript
$(document).ready(function(){
$(document).on("click.turnon","#TurnOn",function() {
$(document).off('click.turnon');
alert("Turn Off is now turned off");
});
$(document).on("click.turnoff","#TurnOff",function() {
$(document).on('click.turnon');
alert("Turn Off is now turned back on");
});
});
HTML
<div id="TurnOn">Turn Off</div>
<div id="TurnOff">Turn On</div>
If you want an event handler to only fire once then take a look at .one(): http://api.jquery.com/one
As of jQuery 1.7 it does event delegation.
$(function(){
$(document).one("click.turnon","#TurnOn",function() {
alert("Turn Off is now turned off");
});
$(document).one("click.turnoff","#TurnOff",function() {
alert("Turn Off is now turned back on");
});
});
Here is a demo using .one(): http://jsfiddle.net/9qxfT/1/
Also, your code was just about right but you have a couple typos here:
$(document).on("click.turnoff","#TurnOff",function() {
$(document).on('click.turnon');
alert("Turn Off is now turned back on");
});
$(document).on('click.turnon'); should be: $(document).off('click.turnoff');
Here is a demo of these small changes: http://jsfiddle.net/9qxfT/
Update
You can save the state with a variable:
$(function(){
//declare a variable to save whether or not the `#TurnOn` element is 'on' (true) or 'off' (false)
var isOn = true;
$(document).on("click.turnon","#TurnOn",function() {
//check to see if the flag is set to true, which means the `#TurnOn` element is 'on' already
if (isOn) {
alert("#TurnOn is already turned on");
//otherwise set the `#TurnOn` element to 'on'
} else {
alert("#TurnOn is now turned back on");
isOn = true;
}
});
//set the `#TurnOn` element to `off` when the `#TurnOff` element is clicked
$(document).on("click.turnoff","#TurnOff",function() {
isOn = false;
alert("#TurnOn is now turned off");
});
});​
Here is a demo: http://jsfiddle.net/9qxfT/4/
Your logic is right, but may I suggest better implementation?
Please read this page as well: http://api.jquery.com/off/
Here is what I suggest:
// first put a .click event with a separate "ID" to enable another div "ID".
$('#ButtonForTurnOn').click(function () {
//while body is .on(), the ID, when clicked applies whatever effects
$("body").on("click", "#TurnOn", onlight).find("#TurnOn").addClass("clickable").text("ON switch on");
});
// enable OFF switch
$('#ButtonForTurnOff').click(function () {
$("body").on("click", "#TurnOff", offlight).find("#TurnOff").addClass("clickable").text("OFF switch on");
});
Now, for you to have an effective .off function, YOU MUST have the
"selector string match the one passed to .on() when the event handler
was attached."
For example:
If your $("body").on() is this,
$("body").on("click", "#TurnOff", function({
// stuff here
});
Your $("body").off() should be this,
$("body").off("click", "#TurnOff", function({
// stuff here
});
Try out this jsfiddle
Hope this helps explain things!
Just think of it as disabling something, until its turned back on.

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();
});

How can I pass an element to a jQuery UI dialog box?

Goal
I've got a web page with a table of items. Each item has a delete button beside it. When that button is clicked, I want to
Ask the user to confirm
Delete the corresponding item from the database
Remove that item's row from the list
Current solution
Right now, I'm doing something like this:
$('button.delete').click(function(){
thisRow = $(this).parent();
itemID = $(this).parent().attr('id');
if (confirm('Are you sure?')){
$.post('/manage_items.php', {"action":"delete", "itemid":itemID}, function(){
thisRow.hide("slow").remove();
});
}
}
This solution works because each button.delete can determine which row and item it belongs to, and act accordingly.
Desired solution
Instead of the clunky "OK or Cancel" alert box, I'd like to use a jQuery UI dialog box. But I'm not sure how to let the dialog know which row and item it should handle on any given click.
Here's how you set it up:
1) Define a dialog box div
<div class="dialogbox" id="confirmdeleteitem" title="Really DELETE this item?">
<p>Gee golly, are you s-s-s-sure you want to do that?!</p>
</div>
2) Set up the dialog box behavior
$('#cofirmdeleteitem').dialog({
//other options - not relevant here
buttons: {
"Nevermind": function() {
//do nothing
},
"Alright! Woo!": function(){
//do something
}
}
});
3) Set the click event that will open the dialog
$('button.delete').click(function(){
$('#confirmdeleteitem').dialog('open');
});
In this last step, I'd like to be able to pass some information to the dialog - which delete button was clicked, for example. But I don't see a way to do that.
I could insert a hidden dialog div.dialog into each item row up front, or insert one into a particular row after its button is clicked. Then the $(this).parent() references would grab the correct row...
Is there an easier way to do this?
i do something like this:
function ConfirmationDialog(title, question, options) {
var d = $('<div title="' + title + '"><p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>' + question + '</p></div>');
d.dialog({
bgiframe: true,
resizable: false,
height: 190,
width: 350,
modal: true,
overlay: {
backgroundColor: '#000',
opacity: 0.5
},
buttons: options
});
}
and then call my function from the click event.
It ended up being most straightforward to set up the dialog behavior inside the click function itself. Actually, it's not much different than my original example.
$('button.delete').click(function(){
thisRow = $(this).parent().parent();
thisRow.css("background-color","red");
skuid = $(this).parent().parent('tr').attr('id').substr(5);
$('#dialogbox').dialog({
autoOpen: false,
modal: true,
draggable: true,
width: 600,
buttons: {
"Actually, I can just mark it inactive": function() {
thisRow.css("background-color","inherit");
$(this).dialog("close");
},
"This SKU needs to be deleted": function() {
$.post('/intranet/backstage/modify_sku_info.php', {"action":"delete", "skuid":skuid}, function(result){
thisRow.hide("slow").remove();
});
$(this).dialog("close");
}
}
});
$('#dialogbox').dialog('open');
return false;
});
Since div#dialogbox doesn't get hidden until $('#dialogbox').dialog() is called, I just gave it an inline style of display:none.
If I end up needing something that can be generalized, as hyun suggested, I'll revisit the issue.
You could store the row in a global variable, like this:
var deletingId;
$('button.delete').click(function() {
deletingId = $(this).parent().attr('id');
$('#confirmdeleteitem').dialog('open');
});
$('#confirmdeleteitem').dialog({
//other options - not relevant here
buttons: {
"Never mind": function() { },
"Alright! Woo!": function(){
$.post(
'/manage_items.php',
{ action: "delete", itemid: deletingId },
function() {
$('#' + deletingId).hide("slow").remove();
}
);
}
}
});
This will only work if the dialog is modal; otherwise, the user could click two different delete links, and you'd need multiple dialogs.
Why can't you just call a setup method to build the dialog as you see fit?
setupMyDialog( '#confirmdeleteitem', info1, info2 );
$('#confirmdeleteitem').dialog...
Alternatively, just store the information in global space before you show the dialog. Remember that your javascript variables can have global scope, or you can store information arbitrarily on objects/functions (which are just objects).
myDataStore = {};
myDataStore.row = foo;
myDataStore.col = bar;
You could add the "rel" attribute to the dialog and store it there, instead. That way you don't need to worry about global variables, and it's semantically not-too-bad, since you are defining a relationship between the dialog and a row. So it'd just be $('#confirmdeleteitem').attr('rel', $(this).parent().attr('id').dialog('open');

Categories

Resources