Differentiate change event incurred by user or script - javascript

I've encountered a situation where some script changes a select/radio/checkbox. That fires the change event. However I need, separately, an event to tell me the user changed the element, and obviously when change fires from the script it registers as a user change.
Is there a way to prevent a script from firing the change event when you alter the value of a select/radio/checkbox?

Use jQuery.trigger() and pass an additional parameter when triggering the event from code.
For example:
$('select').bind('change', function(e, isScriptInvoked) {
if (isScriptInvoked === true) {
// some code for when artificial
} else {
// some code for when organic
}
});
// Trigger the event.
$('select').trigger('change', [true]);

Try:
function changeEvent(){
if(this.type.toLowerCase()=='select' || this.type.toLowerCase()=='radio' || this.type.toLowerCase()=='checkbox')
return false;
else{
//Your code here
}
}

Related

jQuery - detect change event triggered programmatically

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/

Stop onclick method running with jQuery

I have a button similar to below
<button id="uniqueId" onclick="runMethod(this)">Submit</button>
What I'm trying to do is stop the runMethod from running, until after I've done a check of my own. I've tried using the stopImmediatePropagation function, but this doesn't seem to have worked. Here's my jQuery:
$j(document).on('click', '#uniqueId', function(event) {
event.stopImmediatePropagation();
if(condition == true) {
// continue...
} else {
return false;
}
return false;
});
Note: runMethod basically validates the form, then triggers a submit.
What you want to do, especially in the way that you want to do it, requires a some sort of workaround that will always be a bit fiddly. It is a better idea to change the way the button behaves (e.g. handle the whole of the click event on the inside of the jQuery click() function or something along those lines). However I have found sort of a solution for your problem, based on the assumption that your user will first hover over the button. I am sure you can extend that functionality to the keyboard's Tab event, but maybe it will not work perfectly for mobile devices' touch input. So, bear in mind the following solution is a semi-complete workaround for your problem:
$(document).ready(function(){
var methodToRun = "runMethod(this)"; // Store the value of the onclick attribute of your button.
var condition = false; // Suppose it is enabled at first.
$('#uniqueId').attr('onclick',null);
$('#uniqueId').hover(function(){
// Check your stuff here
condition = !condition; // This will change to both true and false as your hover in and out of the button.
console.log(condition); // Log the condition's value.
if(condition == true){
$('#uniqueId').attr('onclick',methodToRun); // Enable the button's event before the click.
}
},
function(){
console.log('inactive'); // When you stop hovering over the button, it will log this.
$('#uniqueId').attr('onclick',null); // Disable the on click event.
});
});
What this does is it uses the hover event to trigger your checking logic and when the user finally clicks on the button, the button is enabled if the logic was correct, otherwise it does not do anything. Try it live on this fiddle.
P.S.: Convert $ to $j as necessary to adapt this.
P.S.2: Use the Javascript console to check how the fiddle works as it will not change anything on the page by itself.
Your problem is the submit event, just make :
$('form').on('submit', function(e) {
e.preventDefault();
});
and it works. Don't bind the button click, only the submit form. By this way, you prevent to submit the form and the button needs to be type button:
<button type="button" .....>Submit</button>
Assuming there's a form that is submitted when button is clicked.
Try adding
event.cancelBubble();
Hence your code becomes:
$j(document).on('click', '#uniqueId', function(event) {
// Don't propogate the event to the document
if (event.stopPropagation) {
event.stopPropagation(); // W3C model
} else {
event.cancelBubble = true; // IE model
}
if(condition == true) {
// continue...
} else {
return false;
}
return false;
});
Your code is mostly correct but you need to remove J:
$(document).on('click', '#uniqueId', function(event) {...
You also need to remove the onClick event from the inline code - there's no need to have it there when you're assigning it via jQuery.
<button id="uniqueId">Submit</button>

html element got focused by mouse or keyboard

How can I find out a HTML-Element (lets say a select-tag) got focus by mouse-click, keyboard or JavaScript function?
<select onfocus="foo(event)"></select>
<script>
function foo(e) {
if (e.??? == 'mouse') {
//do something
}
else if (e.??? == 'keyboard') {
//do something different
}
}
</script>
I also tried to add an onclick event to the element but the onfocus event fires first.
I don't believe there is any native way to see how the element received its focus (correct my if I'm wrong!).
However, you may be able to do something like store when the mouse is clicked, store when the keyboard is used and then react based on the last active state.
var inputState = null;
document.addEventListener("click", handleClick);
document.addEventListener("keyup", handleKey);
function handleClick () {
inputState = "mouse";
}
function handleKey () {
inputState = "keyboard";
}
function foo() {
if ( inputState === "mouse" ) {
// mouse code
} else if ( inputState === "keyboard" ) {
// keyboard code
} else {
// Function was called directly
}
// Reset input State after processing
inputState = null
}
This will likely need some adjustments but I hope you can use this to find the correct answer.
Edit:
My answer is a vanilla JS solution, if you have access to jQuery you may want to investigate the click and keyup event handlers.
Use document.activeElement, it is supported in all major browsers. It can give you the current active element.
EDIT
Oops I think I misunderstood your question. you want to identify the mouse or keyboard or programmatic
For programmatic
if(e.hasOwnProperty('originalEvent')) {
// Focus event was manually triggered.
}
To differentiate between keyboard and mouse based focus events
You have to hack it by adding an extra keydown event and understand. You can not differentiate it like you want.
If you want to check wheather < select > is clicked by keyboard or mouse,
you can use mousedown() and keypress() event
$('select').mousedown(function(e){
//your code on mouse select
});
and
$('select').keypress(function(e){
//your code on key select
});

Change event precedence with JQuery

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
}
});

Click source in JavaScript and jQuery, human or automated?

We all know that you can simulate click or any other event on an element using one of these ways:
$('#targetElement').trigger('eventName');
$('#targetElement').click();
I have encountered a situation in which, I should know how an element is clicked. I should know if it's been clicked automatically via code, or by pressing mouse button. Is there anyway I can do it without hacks or workarounds? I mean, is there anything built into browsers' event object, JavaScript, or jQuery that can tell us whether click has been initiated by a human action or by code?
Try this:
$('#targetElement').click(function(event, generated) {
if (generated) {
// Event was generated by code, not a user click.
} else {
// Event was generated by a user click.
}
});
Then, to make this work, you have to trigger them like this:
$('#targetElement').trigger('click', [true]);
See this jsfiddle.
Check out event.which, it'll be undefined if triggered with code.
$(document).click(function(event) {
if (event.which) {
// Triggered by the event.
} else {
// Triggered with code.
}
});
jsFiddle.
Here's one way I have found (tested in Chrome)
$('#foo').click(function(e) {
if (e.originalEvent)
alert('Has e (manual click)');
else
alert('No e (triggered)');
});
See here for testing: http://jsfiddle.net/ZPD8w/2/
In your immediate event handler, provide an e parameter. If the click is automated (via code), this e would be undefined (no need to check e.target as #alex has said):
$('#targetElement').click(function(e){
if(e)
{
// Click is triggered by a human action
}
else
{
// Click is triggered via code
}
});

Categories