Lets say there is a textbox and a button. On the click of button a function is executed, and on the focusout of textbox, the button is clicked. What I wanna know is, is there a way, I can determine that weather the user clicked the button, or it was triggered by focusout event of textbox, so that I may do some custom work in the click event, if it was triggered by focusout of textbox?
I could write some code, but I don't even have any idea where to begin with, I know the jQuery event and event.which property, but I wonder if it/they could be useful in this situation?
you can use event.target to determine which DOM element has initiated the event, then you can check if this is the button or the textbox.
check this out for more information: http://api.jquery.com/event.target/
from the documetation:
event.target
The target property can be the element that registered for the event
or a descendant of it. It is often useful to compare event.target to
this in order to determine if the event is being handled due to event
bubbling. This property is very useful in event delegation, when
events bubble.
This depends on how you're triggering the function from the textarea blur event, if you're simply triggering the click event using the following approach:
$('#btn').click(
function(e){
buttonActivation(e);
});
$('#txt').blur(
function(e){
$('#btn').click();
});
Then I'd suggest evaluating the originalEvent object to see what the original event was (if there was no originalEvent then the function was called by a programmatic click event, with jQuery; whereas if the originalEvent.type evaluates to click then the button must have been clicked.
function buttonActivation(e) {
if (!e) {
return false;
}
else {
var oEvent = e.originalEvent;
if (oEvent === undefined) {
console.log('Programmatic event');
}
else if (oEvent.type == 'click') {
console.log('User-initiated event');
}
}
}
JS Fiddle demo.
If, however, you're using something like the following (simply calling the same function from a different place):
$('#btn').click(
function(e){
buttonActivation(e);
});
$('#txt').blur(
function(e){
buttonActivation(e);
});
Then I'd recommend either directly assessing e.target or e.type:
function buttonActivation(e) {
if (!e) {
return false;
}
else {
var oEvent = e.type;
if (oEvent === 'blur') {
console.log('Programmatically-triggered event, on ' + oEvent);
}
else if (oEvent == 'click') {
console.log('User-initiated ' + oEvent + ' event');
}
}
}
JS Fiddle demo.
You can use the event.target. By default, jquery provides the event to the handler function.
Here's an example : jsfiddle
You can pass an additional parameters when triggering the event and check them in event handler.
So if you wrote
button$.trigger('click', 'hello');
then you can write the handler like
button$.on('click', function(e, someStr) {
console.log(someStr || 'Nothing passed');
// Obviously if someStr is undefined, the user clicked the button,
// otherwise the $.trigger() method has been called.
});
Related
I'm new to JQuery, so I don't know much of the logic. I'm using it to find out which index of textarea I clicked while holding the CtrlKey.
However how do I assign a function on a combination of onclick and a keyboard event.
//What I have tried:
//textarea is the object where I want to detect both ctrlKey and mouse click
$(textarea).keydown(function(event){
if(event.ctrlKey){
$(textarea).click(function(event){
console.log("catched")
})
}
})
The above method does work, however It does so thrice, i.e.the console.log occurs thrice, so is there a way to make this catch it once.
also it somehow also occurs when not pressing the ctrl key.
You can simply check the ctrlKey property of the mouse event:
$(function() {
$('textarea').on('click', function (e) {
if (e.ctrlKey) {
console.log('clicked with ctrl');
} else {
console.log('clicked without ctrl');
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea>click me</textarea>
A couple of small mistakes here, but you had the right idea :)
First off, it doesn't really make sense to stack the event handlers the way you have done - I get what you're thinking logically but in reality JS doesn't work that way. What you've actually said is this:
"If the user presses a key down in this textarea, and if their control key is down, add an event listener to this textarea that detects for clicks, and logs catched to the console".
What you really want is this:
$("#txtarea").click((e)=>{
if (e.ctrlKey) {
console.log("Control + Click!");
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea id="txtarea"></textarea>
The ctrlKey property is exposed to all events, not just the keypresses.
If it were not though, (say you wanted A + Click), you would have a keydown event which sets global variable aDown to true, a keyup event which sets the aDown variable to false, and a click event which has an if statement in it which only works if aDown is true. This is shown below:
let aDown = false;
$("#txtarea").keydown((e)=>{
aDown = e.originalEvent.code == "KeyA";
});
$("#txtarea").keyup((e)=>{
aDown = false;
});
$("#txtarea").click((e)=>{
if (aDown) {
console.log("A + Click!");
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Focus the textbox, hold down "A", and then click.<br>
<textarea id="txtarea"></textarea>
Note: On macOS, control + click is a shortcut for right-clicking, so your code won't fire. Consider listening to the oncontextmenu event and dealing with it if you care about macOS support - or perhaps changing your shortcut scheme.
I'd recommend setting up a global variable which holds the status of your ctrl key.
var ctrlDown=false;
Instead of simply listening for a keydown event, listen for a keyup event as well and update ctrldown accordingly.
$(textarea).keydown(function(event) {
if (event.ctrlKey) {
ctrlDown = true;
}
});
$(textarea).keyup(function(event) {
if (event.ctrlKey) {
ctrlDown = false;
}
});
Now that you know that the ctrl key is actually pressed you can do a simple check like:
$(textarea).click(function(event) {
if (ctrlDown) {
console.log("catched")
}
});
On a click function I have the option of playing audio.
The click is only fired once (after I added .off(), which I seem to have to do for every click event because I think there's something I fundamentally don't get about how javascript works) but the function added to the "ended" listener shows it is firing the number of times the button has been clicked. I presume .play() is also being fired multiple times.
These need to be inside the click event to get the id so how do I stop these kinds of things from happening, here and elsewhere when using js? Adding event.stopPropagation(), event.bubbles = false and .off() everywhere seems unnecessary (and in this case doesn't make a difference anyway).
$('.button').off().on('click', function(event){
event.stopPropagation();
event.bubbles = false;
var id = $(this).attr('id')
if ($(this).hasClass('hasAudio')) {
document.getElementById('audio_'+id).play();
document.getElementById('audio_'+id).addEventListener("ended", function(){
console.log("ended");
});
}
});
Move the ended event outside the click event,you are registering the event each time you click on the button
$('.button').on('click', function(event){
var id = $(this).attr('id')
if ($(this).hasClass('hasAudio')) {
document.getElementById('audio_'+id).play();
}
});
$('[id^="audio_"]').on("ended", function(){
console.log("ended");
});
Each time you click on the button a new event listener will be added to the ended event. To prevent that you can try defining the callback function before hand. That will prevent your event listener to be added in the event loop over and over.
An anonymous function has no signature, hence when you define the event with it, it will think that this is supposed to be a new event listener and invokes it multiple times. Check the working snippets to see the difference. Type something in the input box to see what is happening.
If this is confusing then removeEventListener can be the next option.
function ended(event){
console.log("ended");
}
$('.button').off().on('click', function(event){
event.stopPropagation();
event.bubbles = false;
var id = $(this).attr('id')
if ($(this).hasClass('hasAudio')) {
document.getElementById('audio_'+id).play();
document.getElementById('audio_'+id).addEventListener("ended", ended);
}
});
var input = document.getElementById('some');
function callback(event) {
console.log("PRINT");
}
input.addEventListener("keyup", callback)
// input.removeEventListener("keyup", callback)
input.addEventListener("keyup", callback)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="some" value="" >
Anonymous function as callback
var input = document.getElementById('some');
input.addEventListener("keyup", function(event) {
console.log("PRINT");
})
// input.removeEventListener("keyup", callback)
input.addEventListener("keyup", function(event) {
console.log("PRINT");
})
<input id="some" value="">
This fails because, every time you click the function, you add a new event listener to the button.
document.getElementById('audio_'+id).addEventListener("ended", function(){
console.log("ended");
This is repeatedly adding the event listener to the button.If you need this inside the click event, check to see whether it exists already. If it does, don't add it again.
Use global flag which defines if you want to pause or play. and also use preventDefault (in case of any inline click event used).
You have to remove the registered event listener after your task is completed.
document.getElementById('audio_'+id).removeEventListener("ended", function(){
console.log("ended");
});
Or what you can do is that move the logic for registering event listener outside the click event listener. Like this the event will be registered only once.
document.getElementById('audio_'+id).addEventListener("ended", function(){
console.log("ended");
});
}
$('.button').off().on('click', function(event){
event.stopPropagation();
event.bubbles = false;
var id = $(this).attr('id')
if ($(this).hasClass('hasAudio')) {
document.getElementById('audio_'+id).play();
});
I have a jQuery change event for when a user changes a given SELECT element. However the event may also be triggered by a third party script. What I want to do is detect whether the event was triggered programmatically or by the user.
I have tried the accepted solution in this question Check if event is triggered by a human
But note the JSFiddle in this answer is for a click event rather than a change event.
To demonstrate I amended the fiddle and created this one: http://jsfiddle.net/Uf8Wv/231/
If you try this in latest Firefox or Chrome, you will see that the alert human is being shown even when the event was triggered programmatically.
I have tried event.originalEvent.isTrusted but that doesn't work in all browsers. Can anyone help?
I have added mouseenter and mouseleave events. The idea is that it's a human if the click coincided with a mousepointer being over the element. See:
http://jsfiddle.net/Uf8Wv/232/
$("#try").mouseenter(function(event) {
mouseover = true;
});
// ... etc.
I can't think of any other way.
You can find some vague difference between click and emulated click using this code:
$(document).on('change', "#try", function (event) {
//some difference appear in the next line
console.log(event.delegateTarget.activeElement);
//no difference
if (event.originalEvent === undefined) {
alert('not human')
} else {
alert(' human');
}
event.delegateTarget = null;//doesn't help
});
$('#click').click(function (event) {
$("#try").click();
});
Click on the checkbox logs <input id="try" type="checkbox">.
Click on the button logs <button id="click">.
But...
Run $("#try").click(); from console before any clicks logs <body> and after the click result of the last click.
Generally JS can always fake any client event. So isTrusted is never trusted.
You can listen to the click event as well, and modify a variable. The change event seems indeed to be quite similar wheter it's a real click or a script triggered click, but the click on #try event won't be the same. And since click is triggered before change, you have time to set a switch.
Like this for example:
var realClick;
$("#try").change(function(event) {
console.log('change')
if (!realClick) {
alert('not human')
} else {
alert(' human');
}
});
$("#try").click(function(event) {
console.log('click')
// originalEvent is one way, but there will be many differences
if (event.originalEvent) {
realClick = true;
} else {
realClick = false;
}
});
// Since this is called from outside, better not put
// any controls here.
$('#click').click(function(event) {
$("#try").click();
});
http://jsfiddle.net/2xjjmo09/3/
What really worked for me is:
if ((event.originalEvent.isTrusted === true && event.originalEvent.isPrimary === undefined) || event.originalEvent.isPrimary === true) {
//Hey hooman it is you
//Real CLick
}
Tested with jQuery version 3.5
You can easily detect whether the click event on the button is actually triggered by mouse click or not. By doing,
$('#click').click(function(ev) {
if (ev.which !== undefined && ev.button !== undefined) {
$("#try").click();
}
});
Here's the Fiddle
Note: Beware of either ev.which or ev.button could result in 0 on some browser for left-click.
You can check for if event.srcElement (which is source element on which event is triggered) is equal to event.currentTarget something like:
$("#try").change(function(event) {console.log(event,event.target,event.currentTarget,event.srcElement)
if (event.currentTarget=== event.srcElement) {
alert(' human')
} else {
alert(' not human');
}
});
Fiddle: http://jsfiddle.net/Uf8Wv/234/
I need to pass somehow the information about pressed Ctrl key on invoking the event by jQuery click function. I want invoke this with Ctrl key pressed.
$(selector).click();
This is simplified example:
https://jsfiddle.net/62mdur6o/
When you click on the first cell of table ("One") you do not get information about present Ctrl key in the event.
Is it possible to invoke click listener differently or to attach somehow this information to the event which will be passed to other listeners?
You can trigger event using:
$('#cell').click(function (event) {
event.stopPropagation();
var e = jQuery.Event( event, {ctrlKey: event.ctrlKey} );
$(this).next().trigger(e);
});
-demo-
Target each cells
$('.cells').click(function (event) {
if (event.ctrlKey) {
alert('ctrl pressed');
} else {
alert('just clicked');
}
});
updated fiddle
I have the following html code:
<input type="text" id="theInput" value=""/>
Click me
I want to detect when the input changes and perform an operation in this case, but ONLY when the user has not clicked in the link. I have tried this:
$('#theLink').live('click', function(){
alert('click');
});
$('#theInput').live('change', function(){
alert('change');
});
However change is always executed before click when the value in the input changed, due to Javascript event precedence rules, and therefore only "change" message is displayed.
I would like it to display change only if the input value changed and the user exited the input clicking in any other place instead of the link. In that last case I would like to display click.
The example is here.
I use jQuery 1.6.4.
As far as I know, the click event fires after the blur and change events in every browser (have a look at this JSFiddle). The order of blur and change is different across browsers (source: Nicholas Zakas).
To solve your problem, you could listen to click events on the document and compare the event's target with #theLink. Any click event will bubble up to the document (unless it is prevented).
Try this:
var lastValue = '';
$(document).click(function(event) {
var newValue = $('#theInput').val();
if ($(event.target).is('#theLink')) {
// The link was clicked
} else if (newValue !== lastValue) {
// Something else was clicked & input has changed
} else {
// Something else was clicked but input didn't change
}
lastValue = newValue;
});
JSFiddle: http://jsfiddle.net/PPvG/TTwEG/
Both events will fire but in your example the alert in the onchange event handler fired when the onmousedown event occurs will stop the onmouseup event required for the onclick event to fire. Using console.log will show both events firing.
http://jsfiddle.net/hTqNr/4/
Ok, now i got it, you could do
$('#theLink').live('click', function(e){
alert('click');
});
$('#theInput').live('change', function(e){
//Check if the change events is triggerede by the link
if(e.originalEvent.explicitOriginalTarget.data === "Click me"){
//if this is the case trigger the click event of the link
$('#theLink').trigger("click");
}else{
//otherwise do what you would do in the change handler
alert('change');
}
});
Fiddle here http://jsfiddle.net/hTqNr/19/
why you dont pick the value of input box. you have to store initial value of input box on ready function
initialvalue= $('#theInput').val();
then compare the value
$('#theLink').live('click', function(){
var newvalue =$('#theInput').val();
if(newvalue!=initialvalue) {
//do something
}
});