Strange behavior using live event on IE10 with jQuery - events

I have the following code:
$('input.test2').live('keyup', function (e) {
});
$('input.test1').live('change', function (e) {
});
test1 and test2 are classes of the same input element.. but only the test1 is triggered.
Can somebody explain to me why this is happening? (It only happens on IE10).
I tried to return false or e.stopPropagation() but nothing changed.

Try using "on" instead of "live"
$('input.test1').on('change', function (e) {
});
$('input.test2').on('keyup', function (e) {
});
As per the jQuery docs:
http://api.jquery.com/live/
"As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers. Users of older versions of jQuery should use .delegate() in preference to .live()."

Related

bootstrap modal and datepicker show events

When click on datepicker (http://www.eyecon.ro/bootstrap-datepicker/), his SHOW event fires, but the modal's SHOW.BS.MODAL fires too. Whhere is a problem?
$(document).ready(function() {
$('#ArrDate')
.datepicker()
.on("show", function(event){
alert("Q");
});
$("#dlg3000to3100")
.on('show.bs.modal', function (event) {
alert("W");
});
$("#dlg3000to3100")
.modal("show");
});
exampleExample
Thanks
It seems to be a bug (or feature?) of the datepicker. What you can do is to prevent the show.bs.modal event reaching the dialog.
$('#ArrDate').on('show.bs.modal', function (event) {
event.stopPropagation();
});
This will detect the event at the datepicker level and stop the event propagation, so show.bs.modal will not 'bubble up' to the dialog.
Another work around is to swap the show.bs.modal with shown.bs.modal on modal event.
modal.on('shown.bs.modal', function (event) {
// Do something
});
however if it is not possible to swap show with shown or hide with hidden use the namespace check
modal.on('show.bs.modal', function(e) {
if (e.namespace === 'bs.modal') {
// Do something
}
});
Had a similar issue, caused by the datepicker watching for a show event.
One option is to use the shown event on the modal but this is not ideal in all cases
$('#dlg3000to3100').on('shown.bs.modal', function (event) {
// modal code in here
});
A more elegant solution is to check the namespace of the event
$('#dlg3000to3100').on('show.bs.modal', function (event) {
if(event.namespace !== 'bs.modal') return;
// modal code in here
});
https://jsfiddle.net/bzh75tww/

How to check if a button is clicked in JavaScript

How to check if a button is clicked or not in prototype JavaScript?
$('activateButton').observe('click', function(event) {
alert(hi);
});
The code above is not working.
With this button:
<button id="mybutton">Click Me</button>
Use this:
$('mybutton').observe('click', function () {
alert('Hi');
});
Tested and works, here.
You might want to encase it in a document.observe('dom:loaded', function () { }) thingy, to prevent it executing before your page loads.
Also, just an explanation:
The single dollar sign in Prototype selects an element by its id. The .observe function is very similar to jQuery's .on function, in that it is for binding an event handler to an element.
Also, if you need it to be a permanent 'button already clicked' thingy, try this:
$('mybutton').observe('click', function () {
var clicked = true;
window.clicked = clicked;
});
And then, if you want to test if the button has been clicked, then you can do this:
if (clicked) {
// Button clicked
} else {
// Button not clicked
}
This may help if you are trying to make a form, in which you don't want the user clicking multiple times.
How one may do it in jQuery, just for a reference:
$('#mybutton').on('click', function () {
alert('Hi');
});
Note that, the jQuery code mentioned above could also be shortened to:
$('#mybutton').click(function () {
alert('Hi');
});
jQuery is better in Prototype, in that it combines the usage of Prototype's $ and $$ functions into a single function, $. That is not just able to select elements via their id, but also by other possible css selection methods.
How one may do it with plain JavaScript:
document.getElementById('mybutton').onclick = function () {
alert('Hi');
}
Just for a complete reference, in case you need it.
$('body').delegate('.activateButton', 'click', function(e){
alert('HI');
});

How to use events and event handlers inside a jquery plugin?

I'm triyng to build a simple animation jQuery-plugin. The main idea is to take an element and manipulate it in some way repeatedly in a fixed intervall which would be the fps of the animation.
I wanted to accomplish this through events. Instead of using loops like for() or while() I want to repeat certain actions through triggering events. The idea behind this: I eventualy want to be able to call multiple actions on certain events, like starting a second animation when the first is done, or even starting it when one animation-sequence is on a certain frame.
Now I tried the following (very simplified version of the plugin):
(function($) {
$.fn.animation = function() {
obj = this;
pause = 1000 / 12; //-> 12fps
function setup(o) {
o.doSomething().trigger('allSetUp');
}
function doStep(o, dt) {
o.doSomething().delay(dt).trigger('stepDone');
}
function sequenceFinished(o) {
o.trigger('startOver');
}
function checkProgress(o) {
o.on({
'allSetup': function(event) {
console.log(event); //check event
doStep(o, pause);
},
'stepDone': function(event) {
console.log(event); //check event
doStep(o, pause);
},
'startOver': function(event) {
console.log(event); //check event
resetAll(o);
}
});
}
function resetAll(o) {
/*<-
reset stuff here
->*/
//then start over again
setup(o);
}
return this.each(function() {
setup(obj);
checkProgress(obj);
});
};
})(jQuery);
Then i call the animation like this:
$(document).ready(function() {
$('#object').animation();
});
And then – nothing happens. No events get fired. My question: why? Is it not possible to use events like this inside of a jQuery plugin? Do I have to trigger them 'manualy' in $(document).ready() (what I would not prefer, because it would be a completely different thing – controling the animation from outside the plugin. Instead I would like to use the events inside the plugin to have a certain level of 'self-control' inside the plugin).
I feel like I'm missing some fundamental thing about custom events (note: I'm still quite new to this) and how to use them...
Thx for any help.
SOLUTION:
The event handling and triggering actually works, I just had to call the checkProgress function first:
Instead of
return this.each(function() {
setup(obj);
checkProgress(obj);
});
I had to do this:
return this.each(function() {
checkProgress(obj);
setup(obj);
});
So the event listening function has to be called before any event gets triggered, what of course makes perfect sense...
You need set event on your DOM model for instance:
$('#foo').bind('custom', function(event, param1, param2) {
alert('My trigger')
});
$('#foo').on('click', function(){ $(this).trigger('custom');});​
You DOM element should know when he should fire your trigger.
Please note that in your plugin you don't call any internal function - ONLY DECLARATION

jquery .submit live click runs more than once

I use the following code to run my form ajax requests but when i use the live selector on a button i can see the ajax response fire 1 time, then if i re-try it 2 times, 3 times, 4 times and so on...
I use .live because i also have a feature to add a post and that appears instantly so the user can remove it without refreshing the page...
Then this leads to the above problem... using .click could solve this but it's not the ideal solution i'm looking for...
jQuery.fn.postAjax = function(success_callback, show_confirm) {
this.submit(function(e) {
e.preventDefault();
if (show_confirm == true) {
if (confirm('Are you sure you want to delete this item? You can\'t undo this.')) {
$.post(this.action, $(this).serialize(), $.proxy(success_callback, this));
}
} else {
$.post(this.action, $(this).serialize(), $.proxy(success_callback, this));
}
return false;
})
return this;
};
$(document).ready(function() {
$(".delete_button").live('click', function() {
$(this).parent().postAjax(function(data) {
if (data.error == true) {
} else {
}
}, true);
});
});​
EDIT: temporary solution is to change
this.submit(function(e) {
to
this.unbind('submit').bind('submit',function(e) {
the problem is how can i protect it for real because people who know how to use Firebug or the same tool on other browsers can easily alter my Javascript code and re-create the problem
If you don't want a new click event bound every time you click the button you need to unbind the event before re-binding it or you end up with multiple bindings.
To unbind events bound with live() you can use die(). I think the syntax using die() with live() is similar to this (untested):
$(document).ready(function(){
$('.delete_button').die('click').live('click', function(){
$(this).parent().postAjax(function(data){
if (data.error == true){
}else{
}
}, true);
});
});
However, if you are using jQuery 1.7 or later use on() instead of live() as live() has been deprecated since 1.7 and has many drawbacks.
See documentation for all the details.
To use on() you can bind like this (I'm assuming the delete_button is a dynamically added element) :
$(document).ready(function(){
$(document).off('click', '.delete_button').on('click', '.delete_button', function(){
$(this).parent().postAjax(function(data){
if (data.error == true){
}else{
}
}, true);
});
});
If you are using an earlier version of jQuery you can use undelegate() or unbind() and delegate() instead. I believe the syntax would be similar to on() above.
Edit (29-Aug-2012)
the problem is how can i protect it for real because people who know
how to use Firebug or the same tool on other browsers can easily alter
my Javascript code and re-create the problem
You can some-what protect your scripts but you cannot prevent anyone from executing their own custom scripts against your site.
To at least protect your own scripts to some degree you can:
Write any script in an external js file and include a reference to that in your site
Minify your files for release
Write any script in an external js file and include a reference to that in your site
That will make your html clean and leave no trace of the scripts. A user can off course see the script reference and follow that for that you can minify the files for release.
To include a reference to a script file:
<script type="text/javascript" src="/scripts/myscript.js"></script>
<script type="text/javascript" src="/scripts/myscript.min.js"></script>
Minify your files for release
Minifying your script files will remove any redundant spacing and shorten function names to letters and so no. Similar to the minified version of JQuery. The code still works but it is meaningless. Off course, the hard-core user could follow meaningless named code and eventually figure out what you are doing. However, unless you are worth hacking into I doubt anyone would bother on the average site.
Personally I have not gone through the minification process but here are some resources:
Wikipedia - Minification (programming)
Combine, minify and compress JavaScript files to load ASP.NET pages faster
How to minify (not obfuscate) your JavaScript using PHP
Edit (01-Sep-2012)
In response to adeneo's comment regarding the use of one().
I know you already found a solution to your problem by unbinding and rebinding to the submit event.
I believe though it is worth to include a mentioning of one() in this answer for completeness as binding an event with one() only executes the event ones and then unbinds itself again.
As your click event, when triggered, re-loads and rebinds itself anyway one() as an alternative to unbinding and re-binding would make sense too.
The syntax for that would be similar to on(), keeping the dynamic element in mind.
// Syntax should be right but not tested.
$(document).ready(function() {
$(document).one('click', '.delete_button', function() {
$(this).parent().postAjax(function(data) {
if (data.error == true) {} else {}
}, true);
});
});​
Related Resources
live()
die()
on()
off()
unbind()
delegate()
undelegate()
one()
EDIT AGAIN !!!! :
jQuery.fn.postAjax = function(show_confirm, success_callback) {
this.off('submit').on('submit', function(e) { //this is the problem, binding the submit function multiple times
e.preventDefault();
if (show_confirm) {
if (confirm('Are you sure you want to delete this item? You can\'t undo this.')) {
$.post(this.action, $(this).serialize(), $.proxy(success_callback, this));
}
} else {
$.post(this.action, $(this).serialize(), $.proxy(success_callback, this));
}
});
return this;
};
$(document).ready(function() {
$(this).on('click', '.delete_button', function(e) {
$(e.target.form).postAjax(true, function(data) {
if (data.error) {
} else {
}
});
});
});​
jQuery.fn.postAjax = function(success_callback, show_confirm) {
this.bind( 'submit.confirmCallback', //give your function a namespace to avoid removing other callbacks
function(e) {
$(this).unbind('submit.confirmCallback');
e.preventDefault();
if (show_confirm === true) {
if (confirm('Are you sure you want to delete this item? You can\'t undo this.')) {
$.post(this.action, $(this).serialize(), $.proxy(success_callback, this));
}
} else {
$.post(this.action, $(this).serialize(), $.proxy(success_callback, this));
}
return false;
})
return this;
};
$(document).ready(function() {
$(".delete_button").live('click', function() {
$(this).parent().postAjax(function(data) {
if (data.error == true) {
} else {
}
}, true);
});
});​
As for the "people could use Firebug to alter my javascript" argument, it does not hold : people can also see the request that is sent by your $.post(...), and send it twice.
You do not have control over what happens in the browser, and should protect your server side treatment, rather than hoping that "it won't show twice in the browser, so it will prevent my database from being corrupt".

How to handle custom jQuery events in Meteor?

In Metor 0.3.5, when all events were jQuery events, I was able to use use jQuery UI Draggable and then handle the drag & dragstop events using a Metor event map:
Template.game.events['dragstop .card'] = function (e) {
//stuff
};
But I just read this in the Meteor mailing list:
In 0.3.6, event maps no longer depend on jQuery
And sure enough, the above technique no longer seems to work – my dragstop handler isn't called at all now.
I'd greatly appreciate any advice as to how to achieve the same effect in 0.3.6.
Nowadays, you can simply use body events to accomplish this the "Meteor" way:
Template.body.events({
'dragstop #somedivid': function(e) {
// Do stuff
}
});
Custom jQuery events can be bound with plain old jQuery, bypassing event maps altogether:
$(function () {
$('body').on('dragstop', '.card', function (e) {
//stuff
});
});
Remember to use jQuery's on function to bind the handlers, since template elements are not necessarily included in the DOM at all times.

Resources