I need to use the $().bind method. I do not wish to use another plugin. I simply want to add both a left click and a right click function. Here is my function handler. I also must disable the context menu. Here is my $().bind function (I am attempting to extend jQuery's full calendar to allow me to bind any jsEvent to its own events, as it only exposes 3 js events.)
if (has(eventBind)) {
$.each(eventBind, function (eventString, eventFunction) {
options.eventRender = function (calEvent, element) {
element.bind(eventString, { calEvent: calEvent }, eventFunction);
}
});
}
}
If i define eventBind like this, then what happens is that function A gets called if i right click and function B gets called if I left click
eventBind: {
mouseup: function eventClick(e) {
if (e.button === 2) {
//execute function A
} else {
//execute function B
}
}
I apologize if the order of my code does not really make sense, but I just want to know what to do. I tried to define the following
eventBind: {
mouseup: function eventClick(e) {
if (e.button === 2) {
//execute function A
} else {
//execute function B
}
},
contextmenu: function() { return false; }
}
}
But this also disabled the previously defined "mouseup" from executing correctly.
Your help is greatly appreciated.
Related
Javascript newbie here.
Is there a "best practice" for placement of "if" statements in event delegation?
Context
I'm setting up event listeners using vanilla Javascript (I know jQuery etc. would simplify things, but let's stick to vanilla JS): there's an event listener on the parent element that invokes a function when a child is clicked. In our example, that function to-be-invoked lives elsewhere in the code.
Let's say I only want to take action when element with id=child-element is clicked. To do this, I use an "if" statement.
There are two obvious places I can put the if statement:
Within the event listener
Within the function
Question
Is (1) or (2) preferred? If so, why? ("Better memory management", "code is easier to read", etc.)
Example 1
var foo = {
bindEvent: function () {
document.getElementById('clickableElement').addEventListener('click', function (e) {
const clickTarget = e.target.id
if (clickTarget === 'child-element') {
foo.takeAnAction.bind(foo);
foo.takeAnAction();
};
});
},
takeAnAction: function () {
console.log('Click');
},
};
Example 2
var foo = {
bindEvent: function () {
document.getElementById("clickableElement").addEventListener("click",
foo.takeAnAction.bind(foo));
},
takeAnAction: function(e) {
if (e.target.id === "child-element") {
console.log('click');
};
},
};
Thanks!
I would go with option 1. The reason is that you can easily generalise it to handle any event delegation, so it's reusable. Sample:
var foo = {
bindEvent: function (selector, callback) { //accept a selector to filter with
document.getElementById('clickableElement').addEventListener('click', function (e) {
const clickTarget = e.target; //take the element
// check if the original target matches the selector
if (target.matches(selector)) {
takeAnAction.call(foo);
};
});
},
takeAnAction: function () {
console.log('Click');
},
};
foo.bindEvent("#child-element", foo.takeAction);
Now you can produce any amount of delegated event bindings. Adding another delegated binding is as simple as:
foo.bindEvent("#parent-element", foo.takeAction);
foo.bindEvent(".table-of-content", foo.takeAction);
With option 2, you will not need to change the implementation or produce new functions for each case:
/*... */
takeAnAction: function(event) {
if (event.target.id === "child-element") {
console.log('click');
};
},
takeAnActionForParent: function(event) {
if (event.target.id === "parent-element") {
console.log('click');
};
},
takeAnActionOnTableOfContentItems: function(event) {
if (event.target.classList.contains("table-of-content") {
console.log('click');
};
},
If you need to execute the same logic in each case, there is really no need to add a new function for every single case. So, for maintainability point of view, adding the logic in the event listener that would call another function is simpler to manage than producing different functions to be called.
Please check out my diagram, and the pseudo-code below. I'm trying to figure out how to pass a function between two event listeners.
Basically, I want to execute some code if "Availability" is less than 0, OR when a user clicks "confirm" in a bootstrap dialog. If the Availability is greater than 0, you'll get the special bootstrap dialog.
I'm trying to avoid writing the same code twice. I'm also trying to avoid using trigger $("#btnConfirm").trigger("click", fn1); --- my assumption is that there is a sexier way, like a callback, or something...
So.... how do I get the code I want to execute into the other 'button click' event listener --OR-- how do I return "btnConfirm" back to the event listener that called the dialog?
$("#Select").on("change", function(e) {
fn1 = function() {
//stuff I want to do
};
//a check that must be passed
currAvail = $("#Availability").val();
if (currAvail > 0) {
//show a message, "Are you sure you want to make the thing?"
//if YES, execute fn1()
//fn1() needs to be available to btnConfirm click listener
// use trigger("click", fn1) ????
} else {
//execute the code
fn1();
};
});
$("#btnConfirm").on("click", function(e, param1) {
//Ok, well, they said YES...
//so I need to execute fn1();
});
Since the requirement is to call fn1() in both cases, you can separate the logic out into a method and call when it is needed
function fn1() {
//code to execute on no goes here
}
$("#Select").on("change", function(e) {
let currAvail = $("#Availability").val();
if (currAvail > 0) {
//show modal window
} else {
//execute the code
fn1();
};
});
$("#btnConfirm").on("click", function(e, param1) {
fn1()
});
Why not just move the function definition to outside the change callback?
$("#Select").on("change", function(e) {
//a check that must be passed
currAvail = $("#Availability").val();
if (currAvail > 0) {
//show a message, "Are you sure you want to make the thing?"
//if YES, execute fn1()
//fn1() needs to be available to btnConfirm click listener
// use trigger("click", fn1) ????
} else {
//execute the code
fn1();
};
});
$("#btnConfirm").on("click", function(e, param1) {
//Ok, well, they said YES...
//so I need to execute fn1();
});
// Function move to here.
function fn1() {
//stuff I want to do
};
I want the events click and touchstart to trigger a function.
Of course this is simple with JQuery. $('#id').on('click touchstart', function{...});
But then once that event is triggered, I want that same handler to do something else when the events are triggered,
and then later, I want to go back to the original handling function.
It seems like there must be a cleaner way to do this than using $('#id').off('click touchstart'); and then re-applying the handler.
How should I be doing this?
You can create a counter variable in some construct in your javascript code that allows you to decide how you want to handle your event.
$(function() {
var trackClicks = (function() {
var clicks = true;
var getClicks = function() {
return clicks;
};
var eventClick = function() {
clicks = !clicks;
};
return {
getClicks: getClicks,
eventClicks: eventClicks
}
})();
$('#id').on('click touchstart', function {
if (trackClicks.getClicks()) {
handler1();
} else {
handler2();
}
trackClicks.eventClick();
});
function handler1() { //firsthandler};
function handler2() { //secondhandler};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
The way I would do this is by creating a couple of functions for the handler function to call based on certain flags. Sudo code would be something like this:
function beginning_action() {
...
}
function middle() {
...
}
var beginning_state = true;
$('#id').on('click touchstart', function{
if(beginning_state) {
beginning_action();
} else {
middle();
}
});
Then all you need to do is change the variable beginning_state to change which function is called. Of course you would give them better names that describe what they do and not when they do it.
Additionally, if you want the handler to call more than two functions you can change the beginning_state variable from a boolean to an int and check it's value to determine which function to call.
Good luck!
I have a simple function that shows a div when the user clicks on a given checkbox. I'd like to have the same behaviour on another checkbox, so that's why I'd like to generalize it as a function passing the element to be shown.
But I'm not aware of the syntax on Jquery to do so. And it's triggering automatically when the page loads. Does anybody has an idea?
Code:
$(document).ready(function() {
$("#transcricao").change(
function(){
if ($('.form_transcr').css('display') === 'none') {
$('.form_transcr').fadeIn();
} else {
$('.form_transcr').fadeOut();
}
}
); //This is working fine!
$("#traducao").change( show_hide($('.form_trad')) );
//This is auto-trigerring without user action...
});
Here's my function:
function show_hide($elm){
//This is the "generalized" function that I'd like to use on both
//checkboxes, just passing the element.
if ($($elm).css('display') === 'none') {
$($elm).fadeIn();
} else {
$($elm).fadeOut();
}
}
Its auto-triggering without user action because you are invoking it.
Use
$("#traducao").change(function () {
show_hide($('.form_trad'));
});
As you are passing jQuery object so use it directly
function show_hide($elm) {
//This is the "generalized" function that I'd like to use on both
//checkboxes, just passing the element.
if ($elm.css('display') === 'none') {
$elm.fadeIn();
} else {
$elm.fadeOut();
}
}
The argument to .change() should be a function. You're not passing a function, you're calling the function.
$("#traducao").change(function() {
show_hide($('.form_trad'));
} );
BTW, your show_hide function seems to be equivalent to jQuery's fadeToggle method, so it can be:
$("#traducao").change(function() {
$(".form_trad").fadeToggle();
});
We have multiple animations against the same object. We need to take different actions when each of these animations end.
Right now, we bind to the webkitAnimationEnd event, and use a gnarly if/then statement to handle each animation differently.
Is there a way to essentially create custom webkitAnimationEnd events, allowing us to fire a specific event handler when a specific animation ends? For instance, fire handler1 when animation1 ends and fire handler2 when animation2 ends.
We're building for Webkit browsers, specifically Mobile Safari.
Thanks!
For a simple event-trigger, you can pass a function to jQuery's trigger() method and use the returned value of that function to call a trigger a specific event (which can then be listened-for:
function animEndTrigger(e) {
if (!e) {
return false;
}
else {
var animName = e.originalEvent.animationName;
return animName + 'FunctionTrigger';
}
}
$('body').on('bgAnimFunctionTrigger fontSizeFunctionTrigger', function(e){
console.log(e);
});
$('div').on('webkitAnimationEnd', function(e) {
$(this).trigger(animEndTrigger(e));
});
JS Fiddle demo.
You can, of course, also use the called function to either trigger the event itself or assess the passed parameters to determine whether or not to return an event at all:
One method to assess for a particular event to trigger is to use an object:
var animations = {
'bgAnim': 'aParticularEvent'
};
function animEndTrigger(e) {
if (!e) {
return false;
}
else {
var animName = e.originalEvent.animationName;
return animations[animName] ? animations[animName] : false;
}
}
$('body').on('aParticularEvent', function(e) {
console.log(e);
});
$('div').on('webkitAnimationEnd', function(e) {
$(this).trigger(animEndTrigger(e));
});
JS Fiddle demo.
Though, in this case, the return false should be altered so as not to provide the error Uncaught TypeError: Object false has no method 'indexOf' (which I've not bothered, as yet, to account for).
The following causes the called-function (animEndTrigger()) to directly trigger() the custom event (which requires an element on which to bind the trigger() method) and also avoids the Uncaught TypeError above:
var animations = {
'bgAnim': 'aParticularEvent'
};
function animEndTrigger(e, el) {
if (!e || !el) {
return false;
}
else {
var animName = e.originalEvent.animationName;
if (animations[animName]) {
$(el).trigger(animations[animName]);
}
}
}
$('body').on('aParticularEvent', function(e) {
console.log(e);
});
$('div').on('webkitAnimationEnd', function(e) {
animEndTrigger(e, this);
});
JS Fiddle demo.
Of course you're still, effectively, using an if to perform an assessment, so I can't be particularly sure that this is any tidier than your own already-implemented solution.