Normally you write a handler for a button click like this:
$(document).ready(function()
{
$("button").click(function()
{
doSomething();
});
});
But in the case of an event delegator, to respond to an event with a function such as this:
function doSomething(event)
{
if (ev.target.id == 'button1' )
{
//do your stuff
console.log('#button1 click');
}
else
{
console.log('not a #button1 click');
}
}
What I'm confused about is the correct syntax for defining the event that calls this delegator function - this? (A):
$(document).ready(function()
{
$(function()
{
$('button').click(doSomething);
});
});
or this? (B):
$(document).ready(function()
{
$("button").click(doSomething);
});
Which is correct and why?
In choice A you are just repeating the document.ready syntax twice.
// These two lines are equal
$(document).ready(fn);
$(fn);
All you need to do is choice B
While choice B would certainly be the way to do this if you needed to use a separate function, i.e., in the case where you needed to invoke the function from somewhere other than a button click, my preference is usually to put the code in line. The only other times I don't do this is when it would improve readability.
$(function() {
$("button").click( function(e) {
if (e.target.id == 'button1') {
alert('button1 clicked');
}
...
});
});
Related
I have a button with class name test-button test-button--check. After clicking test-button--check it should do something and be replaced by class test-button--reset
For test-button--reset I want to write another function, but It doesn't work. Because, the previous function executes again.
$(".test-button--check").on("click", function() {
alert("Check is clicked");
$(this).removeClass("test-button--check").addClass("test-button--reset");
});
$(".test-button--reset").on("click", function() {
alert("Reset is clicked");
$(this).removeClass("test-button--reset").addClass("test-button--check");
});
What can I do?
Thanks
You can write your code inside the document.ready in this way
$(".test-button--check .test-button--reset").on("click", function(e) {
e.preventDefault();
var obj=$(this);
if($(obj).hasClass('test-button--check')){
alert("Check is clicked");
$(this).removeClass("test-button--check").addClass("test-button--reset");
}
if($(obj).hasClass('test-button--reset')){
alert("Reset is clicked");
$(this).removeClass("test-button--reset").addClass("test-button--check");
}
});
Try using .off() to remove an event handler, in this case, it is click.
Should be something like this:
$('.test-button.test-button--reset').off().click(function() {...});
I think this will work:
var check = function checkFunc() {
alert('Check is clicked!');
$(this).addClass('test-button--reset').removeClass('test-button--check');
$('.test-button--reset').unbind('click',check);
$('.test-button--reset').bind('click',reset);
}
var reset = function resetFunc() {
alert('Reset is clicked!');
$(this).addClass('test-button--check').removeClass('test-button--reset');
$('.test-button--check').unbind('click',reset);
$('.test-button--check').bind('click',check);
}
$('.test-button--check').bind('click',check);
Using bind and unbind
I currently have sections of a form which display based on the selection of a drop down list:
$('#Selection').on('change', function () {
if(this.value === "Section1"){
$("#Section1").show();
} else {
$("#Section1").hide();
}
if(this.value === "Section2"){
$("#Section2").show();
} else {
$("#Section2").hide();
}
if(this.value === "Section3"){
$("#Section3").show();
} else {
$("#Section3").hide();
}
if(this.value === "Section4"){
$("#Section4").show();
} else {
$("#Section4").hide();
}
if(this.value === "Section5"){
$("#Section5").show();
} else {
$("#Section5").hide();
}
});
This works well for my 'Add' function because the default drop down list selection is 'Please Select...' which means there is a 'change' which triggers my function.
For my 'Edit' function, a selection has already been made, and it's unlikely a change to this selection will be made. I've tried to change the .on('change') bit to .on('load') but that doesn't seem to work!
It feels like there is a simple change I need to make, but I'm rubbish at javaScript!
Thanks.
Try this one:
$( document ).ready(function() {
// Handler for .ready() called.
$("#Section1").show();
});
Try to trigger your code manually on document ready like so:
$(document).ready(function(){
$("#Selection").trigger("change");
});
If you are happy with the functionality inside your change handler;
I think Klikas solution is the correct one:
$(document).ready(function(){
if($('#Selection').value!=""){$('#Selection').trigger("change");}
});
You can simplify your long function with something like this:
$('#Selection').on('change', function(){
var p=["Section1", "Section2", "Section3", "Section4", "Section5"];
for(var i=0; i<p.length; i++){var n=p[i]; var t=$("#"+n); if(t){this.value===n?t.show():t.hide();}}
});
I have some dynamically generated elements with the class my-class on which I want to bind some events. I have the below code which works properly.
$(document).on("event1", ".my-class", function () {
alert("Event 1");
});
$(document).on("event2", ".my-class", function () {
alert("Event 2");
});
I want to refactor it so that there can be a single call to on for the category. Something like this
$(document).on(".my-class", {
"event1": function() {alert("Event1")},
"event2": function() {alert("Event2")}
});
Is this possible in jquery?
There might be a better way, but I've used this before and it worked for me:
Demo Fiddle
I wouldn't delegate off the document, instead I'd use the closest parent container.
JS:
$('body').on('click mouseenter', 'div', function(e) {
if (e.type === 'click') {
$('div').html('clicked');
}
else { //you'd need an else if here if you had more than two event types
$('div').html('mouse enter');
}
});
I'm wondering if I can fire off both of these events together :
$("input[type=checkbox]").click(function(){
if($(this).is(":checked"))
{
//Value of checkbox
alert(this.value);
}
});
and
$("input[type= 'text']").keyup(function(){
alert(this.value);
});
I looked into .bind, but that seems to only work for one selected elements (i.e. $(p).bind("mouseout mouseenter).doSomething()).
The situation I am running into is that I have a function that needs to fire anytime either one of these things occur.
Try
$("input[type=checkbox],input[type='text']").on('click keyup', function(){
// code
});
Two ways you can achieve this as shown below:
using "on" method:
$(document).on('keyup click',"input[type=checkbox],input[type='text']", function(){
// Do stuff here..
})
Call function after the event.
$("input[type=checkbox]").click(doSomething);
$("input[type= 'text']").keyup(doSomething);
function doSomething() {
}
If you still need the additional if, you can use:
$("input[type=checkbox]").click(function(){
if($(this).is(":checked"))
{
//Value of checkbox
alert(this.value);
somethingHappened();
}
});
$("input[type= 'text']").keyup(function(){
alert(this.value);
somethingHappened();
});
function somethingHappened() {
// Do stuff
}
Perhaps all you need is a common function?
$("input[type=checkbox]").click(function(){
if($(this).is(":checked")) {
special(this.value);
}
});
$("input[type= 'text']").keyup(function(){
special(this.value);
});
function special(val) {
alert(val);
}
If your intent really is to invoke a function when any checkboxes/text fields across the whole page changes, you probably want something like this:
$('body').on('change', ':checkbox,:text', function () {
});
Note that the :checkbox and :text selectors are much nicer than input[type=checkbox] etc.
I have a bunch of elements that get three different classes: neutral, markedV and markedX. When a user clicks one of these elements, the classes toggle once: neutral -> markedV -> markedX -> neutral. Every click will switch the class and execute a function.
$(document).ready(function(){
$(".neutral").click(function markV(event) {
alert("Good!");
$(this).addClass("markedV").removeClass("neutral");
$(this).unbind("click");
$(this).click(markX(event));
});
$(".markedV").click(function markX(event) {
alert("Bad!");
$(this).addClass("markedX").removeClass("markedV");
$(this).unbind("click");
$(this).click(neutral(event));
});
$(".markedX").click(function neutral(event) {
alert("Ok!");
$(this).addClass("neutral").removeClass("markedX");
$(this).unbind("click");
$(this).click(markV(event));
});
});
But obviously this doesn't work. I think I have three obstacles:
How to properly bind the changing element to the already defined function, sometimes before it's actually defined?
How to make sure to pass the event to the newly bound function [I guess it's NOT accomplished by sending 'event' to the function like in markX(event)]
The whole thing looks repetitive, the only thing that's changing is the alert action (Though each function will act differently, not necessarily alert). Is there a more elegant solution to this?
There's no need to constantly bind and unbind the event handler.
You should have one handler for all these options:
$(document).ready(function() {
var classes = ['neutral', 'markedV', 'markedX'],
methods = {
neutral: function (e) { alert('Good!') },
markedV: function (e) { alert('Bad!') },
markedX: function (e) { alert('Ok!') },
};
$( '.' + classes.join(',.') ).click(function (e) {
var $this = $(this);
$.each(classes, function (i, v) {
if ( $this.hasClass(v) ) {
methods[v].call(this, e);
$this.removeClass(v).addClass( classes[i + 1] || classes[0] );
return false;
}
});
});
});
Here's the fiddle: http://jsfiddle.net/m3CyX/
For such cases you need to attach the event to a higher parent and Delegate the event .
Remember that events are attached to the Elements and not to the classes.
Try this approach
$(document).ready(function () {
$(document).on('click', function (e) {
var $target = e.target;
if ($target.hasClass('markedV')) {
alert("Good!");
$target.addClass("markedV").removeClass("neutral");
} else if ($target.hasClass('markedV')) {
alert("Bad!");
$target.addClass("markedX").removeClass("markedV");
} else if ($target.hasClass('markedX')) {
alert("Ok!");
$target.addClass("neutral").removeClass("markedX");
}
});
});
OR as #Bergi Suggested
$(document).ready(function () {
$(document).on('click', 'markedV',function (e) {
alert("Good!");
$(this).addClass("markedV").removeClass("neutral");
});
$(document).on('click', 'markedX',function (e) {
alert("Bad!");
$(this).addClass("markedX").removeClass("markedV");
});
$(document).on('click', 'neutral',function (e) {
alert("Ok!");
$(this).addClass("neutral").removeClass("markedX");
});
});
Here document can be replaced with any static parent container..
How to properly bind the changing element to the already defined function, sometimes before it's actually defined?
You don't bind elements to functions, you bind handler functions to events on elements. You can't use a function before it is defined (yet you might use a function above the location in the code where it was declared - called "hoisting").
How to make sure to pass the event to the newly bound function [I guess it's NOT accomplished by sending 'event' to the function like in markX(event)]
That is what happens implicitly when the handler is called. You only need to pass the function - do not call it! Yet your problem is that you cannot access the named function expressions from outside.
The whole thing looks repetitive, the only thing that's changing is the alert action (Though each function will act differently, not necessarily alert). Is there a more elegant solution to this?
Yes. Use only one handler, and decide dynamically what to do in the current state. Do not steadily bind and unbind handlers. Or use event delegation.