Is it possible to "wait" for multiple events before executing a function? I know its possible with jQuery deferred obejcts to use $.when to wait for two promises to resolve but I wondered if its possible with just plain old events?
Lets say a click event and a custom event trigger an alert, for example:
$.when("click", "customEvent").then(function(){ alert("yay"); });
You could use deferred, you just have to create them yourself.
var clickDfd = $.Deferred();
var eventDfd = $.Deferred();
$("div").on("click", function(e) {
clickDfd.resolve();
});
$("div").on("some-event", function(e) {
eventDfd.resolve();
});
$.when(clickDfd, eventDfd).done(function(){
alert("yay");
});
var click = 0;
var hover = 0;
$("div").on("click mouseenter", function(e) {
if(e.type == 'click') {
click = 1;
bana();
}
else if(e.type == 'mouseenter') {
hover = 1;
bana();
}
});
function bana() {
if(click == 1 && hover == 1) {
alert(1);
click = 0;
hover = 0;
}
else {
return false;
}
}
Well, Checking event types and setting them in old way. Plain jQuery and JS.
Will alert 1 only when both events are done / fired.
Fiddle
Related
can we stop prevent blur or tabbing for 5 second in input field.then after 5 second user can tab from one field to another.I use off and on function but it is not working .here is my code
http://jsfiddle.net/GV3YY/99/
$("input").off("blur");
setTimeout(function(){
$("input").on("blur");
},5000)
You need to "lock" the inputs when they is focused and use setTimeout to "unlock" it after 5 seconds. A naive implementation could look something like this: https://jsfiddle.net/my7wk6gj/2/
Update: Now pseudo prevents bluring by click. The blur still happens, but focus is returned to the original input until the 5 seconds have passed. I couldn't get event.stopImmediatePropagation to work for blur, so this is the next best thing...
var lockInput = false;
var focusTarget = null;
var lockTimeout = null;
$('input').on('focus', function (e) {
if (lockTimeout) {
return;
}
lockInput = true;
lockTimeout = setTimeout(function () { lockInput = false; lockTimeout = null }, 5000)
}).on('keydown', function (e) {
if (e.keyCode === 9 && lockInput) {
e.preventDefault();
return false;
}
}).on('blur', function (e) {
console.log('blur')
if (lockInput && focusTarget === null) {
focusTarget = e.target;
setTimeout(function () {
focusTarget.focus();
focusTarget = null;
});
}
});
The global variables are used only for the example, i'd advice against that.
Also, if you have a large number of inputs, i'd suggest using event delegation, instead of adding a listener to every one of them.
if I'm fetching multiple events using jquery how can I determine which event is currently triggered so I can processed further, for example
$("#someId").on('paste blur', function (e) {
var data = '';
// if paste
data = e.originalEvent.clipboardData.getData('text')
// if blur
data = $("#someId").val();
});
You can use event.type to get the current event,
$("#someId").on('paste blur', function (e) {
if ('paste' == e.type) {
data = e.originalEvent.clipboardData.getData('text')
} else if ('blur' == e.type) {
data = $("#someId").val();
}
});
You can use Event.type.
$("#someId").on('paste blur', function (e) {
var data = '';
if(e.type == 'paste') {
data = e.originalEvent.clipboardData.getData('text')
}
if(e.type == 'blur') {
data = $("#someId").val();
}
});
You might wish to consider registering separate handlers depending on how different you're going to handle the events though.
To avoid unnecessary if conditions you can add only the events you actually needs:
// Bind up a couple of event handlers
$("#txt").on({
click: function() {
console.log("click")
},
mouseout: function() {
console.log("mouseout")
},
change: function() {
console.log("change")
}
});
//Lookup events for this particular Element
//prints out an object with all events on that element
console.log($._data($("#txt")[0], "events"));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="txt" />
I have two events one is a key press and the other is a click event. the events do similar thing but they are different(ex: they search for different elements and in my real code they call diff functions depending on which button and which input box was entered) . should i combine the events? if so how?
$(document).ready( function(){
function replaceQ(){
var num1 = Math.floor(Math.random() *10)
var num2 = Math.floor(Math.random() *10)
$(".container").children().remove()
$(".container").append("<div>" + num1 + " </div><div>" + num2 +"</div>")
.append("<input class='input'>").append("<button class = 'button'>Go</button>")
var result = num1 + num2;
return [result]
}
var outResult = replaceQ()[0]
$(".container").on("click", "button", function(){
var entry = $(this).siblings(".input").val()
if(outResult == entry){
outResult = replaceQ()[0]
}
})
$(".container").on("keypress", "input", function(e){
var entry = $(".input").val()
if(outResult == entry && e.which == 13){
outResult = replaceQ()[0]
}
})
var processAnswer = function processAnswer(e){
//if(e.target.className === "input")
}
$(".input, .button").on("click", processAnswer)
});
you can get Event.type in callback function, see below sample code
var processAnswer = function processAnswer(e){
if(e.type == 'click'){
//code here
}
else if(e.type == 'keypress'){
//code here
}
}
$(".input, .button").on("click keypress", processAnswer)
Yes - there is. You can use the bind method as follows:
$(".container button").bind("click keypress", function(){
....
});
edit
You can check wether the button or the container was triggered as follows
$(".container button, .container input").bind("click keypress", function(event){
var target = $(event.target);
if(target.is('button'))
{
alert("button");
}
else if(target.is('input'))
{
alert("input");
}
});
See this fiddle for example.
The event listeners themselves are separate enough that it would probably make more sense to just make a single function for the handler. So part of your code would look like this:
//New Event Handling function
function eventHandler(e) {
var entry = $(".input").val()
if(outResult == entry && (!e.which || e.which == 13)){
outResult = replaceQ()[0]
}
}
$(".container").on("click", "button", eventHandler);
$(".container").on("keypress", "input", eventHandler);
I don't think it makes sense to combine the event listeners as they are listening to specific elements and combining them (like $(".container").on("click keypress", eventHandler);) could get weird as it would trigger when you click on a text field. So for that reason, I'd focus on combining the handler like above.
i am trying to write a custom event which should get fire when user click three times on any html node.
i know that i can create even using
var evt = document.createEvent("Event");
evt.initEvent("myEvent",true,true);
but i am not getting how i will capture that three times click event.
I will be appreciated if some one can suggest me the write approach for this.
Thanks!!!
You can create a special event
Code and example - here is your problem solvation :)
Just create a variable that stores the number of clicks.
var clickTimes = 0;
element.addEventListener('click', function(event) {
clickTimes++;
if(clickTimes==3) {
clickTimes = 0;
/* do something like dispatch my custom event */
}
});
This will count the clicks for any specific element and trigger Event on every third click.
$('selector').on('click',function(e){
Event_threshold = 500;
var clicked_times = $(this).data('Event-clicked-times');
if(clicked_times == '')
clicked_times = 0;
if(clicked_times == 0)
$(this).data('Event-first-click-timestamp',e.timeStamp);
clicked_times++;
if(e.timeStamp-$(this).data('Event-first-click-timestamp')<Event_threshold)
{
if(clicked_times == 3)
{
$(this).data('Event-clicked-times',0);
$(this).trigger('Event');
}
else
$(this).data('Event-clicked-times',clicked_times);
}
else
$(this).data('Event-clicked-times',0);
});
EDIT:
Fixed and added threshold control.
You can create iteration variable and check if element was three times clicked.
For example:
var clickTimer = 0;
document.body.addEventListener('click', function() {
clickTimer++;
if(clickTimer == 3) {
clickTimer = 0;
// fire your event
}
}, true);
To make this behavior like dbclick you can compare timestamp with first click.
For example:
var clickTimes = 0;
var fisrtClickTime = 0;
element.addEventListener('click', function(event) {
clickTimes++;
if(clickTimes == 1) {
fisrtClickTime = +new Date();
}
if(clickTimes == 3) {
clickTimes = 0;
firstClickTime = 0;
if((+new Date() - fisrtClickTime) < 1000) {
/* do something like dispatch my custom event */
}
}
});
This works without using external variables, using the HTML5 "data-" attribute for storage, so you will work on multiple elements.
$('#yourLink').click(function() {
window.setTimeout(function() {$(this).data("count",1)},300)
if(typeof $(this).data("count")=='undefined') {
$(this).data("count",1)
}
else {
var myCount = parseInt($(this).data("count"))
myCount++
if(myCount==3) {
alert("3!")
$(this).data("count",0)
}
else {
$(this).data("count",myCount)
}
}
})
$(document).click(function(evt) {
var target = evt.currentTarget;
var inside = $(".menuWraper");
if (target != inside) {
alert("bleep");
}
});
I am trying to figure out how to make it so that if a user clicks outside of a certain div (menuWraper), it triggers an event.. I realized I can just make every click fire an event, then check if the clicked currentTarget is same as the object selected from $(".menuWraper"). However, this doesn't work, currentTarget is HTML object(?) and $(".menuWraper") is Object object? I am very confused.
Just have your menuWraper element call event.stopPropagation() so that its click event doesn't bubble up to the document.
Try it out: http://jsfiddle.net/Py7Mu/
$(document).click(function() {
alert('clicked outside');
});
$(".menuWraper").click(function(event) {
alert('clicked inside');
event.stopPropagation();
});
http://api.jquery.com/event.stopPropagation/
Alternatively, you could return false; instead of using event.stopPropagation();
if you have child elements like dropdown menus
$('html').click(function(e) {
//if clicked element is not your element and parents aren't your div
if (e.target.id != 'your-div-id' && $(e.target).parents('#your-div-id').length == 0) {
//do stuff
}
});
The most common application here is closing on clicking the document but not when it came from within that element, for this you want to stop the bubbling, like this:
$(".menuWrapper").click(function(e) {
e.stopPropagation(); //stops click event from reaching document
});
$(document).click(function() {
$(".menuWrapper").hide(); //click came from somewhere else
});
All were doing here is preventing the click from bubbling up (via event.stopPrpagation()) when it came from within a .menuWrapper element. If this didn't happen, the click came from somewhere else, and will by default make it's way up to document, if it gets there, we hide those .menuWrapper elements.
try these..
$(document).click(function(evt) {
var target = evt.target.className;
var inside = $(".menuWraper");
//alert($(target).html());
if ($.trim(target) != '') {
if ($("." + target) != inside) {
alert("bleep");
}
}
});
$(document).click((e) => {
if ($.contains($(".the-one-you-can-click-and-should-still-open").get(0), e.target)) {
} else {
this.onClose();
}
});
I know that the question has been answered, but I hope my solution helps other people.
stopPropagation caused problems in my case, because I needed the click event for something else. Moreover, not every element should cause the div to be closed when clicked.
My solution:
$(document).click(function(e) {
if (($(e.target).closest("#mydiv").attr("id") != "mydiv") &&
$(e.target).closest("#div-exception").attr("id") != "div-exception") {
alert("Clicked outside!");
}
});
http://jsfiddle.net/NLDu3/
I do not think document fires the click event. Try using the body element to capture the click event. Might need to check on that...
This code will open the menu in question, and will setup a click listener event. When triggered it will loop through the target id's parents until it finds the menu id. If it doesn't, it will hide the menu because the user has clicked outside the menu. I've tested it and it works.
function tog_alerts(){
if($('#Element').css('display') == 'none'){
$('#Element').show();
setTimeout(function () {
document.body.addEventListener('click', Close_Alerts, false);
}, 500);
}
}
function Close_Alerts(e){
var current = e.target;
var check = 0;
while (current.parentNode){
current = current.parentNode
if(current.id == 'Element'){
check = 1;
}
}
if(check == 0){
document.body.removeEventListener('click', Close_Alerts, false);
$('#Element').hide();
}
}
function handler(event) {
var target = $(event.target);
if (!target.is("div.menuWraper")) {
alert("outside");
}
}
$("#myPage").click(handler);
try this one
$(document).click(function(event) {
if(event.target.id === 'xxx' )
return false;
else {
// do some this here
}
});
var visibleNotification = false;
function open_notification() {
if (visibleNotification == false) {
$('.notification-panel').css('visibility', 'visible');
visibleNotification = true;
} else {
$('.notification-panel').css('visibility', 'hidden');
visibleNotification = false;
}
}
$(document).click(function (evt) {
var target = evt.target.className;
if(target!="fa fa-bell-o bell-notification")
{
var inside = $(".fa fa-bell-o bell-notification");
if ($.trim(target) != '') {
if ($("." + target) != inside) {
if (visibleNotification == true) {
$('.notification-panel').css('visibility', 'hidden');
visibleNotification = false;
}
}
}
}
});