Prevent function execution twice within two triggered events - javascript

I have the following code:
myInput.change(function (e) { // this triggers first
triggerProcess();
});
myButton.click(function (e) { // this triggers second
triggerProcess();
});
The problem with the above is when I click myButton both events are triggered and triggerProcess() is fired twice which is not desired.
I only need triggerProcess() to fire once. How can I do that?

Small demo
You can have a static flag that disables any more triggers once the first trigger has occurred. Might look something like this:
var hasTriggered = false;
myInput.change(function (e) { // this triggers first
triggerProcess();
});
myButton.click(function (e) { // this triggers second
triggerProcess();
});
function triggerProcess () {
// If this process has already been triggered,
// don't execute the function
if (hasTriggered) return;
// Set the flag to signal that we've already triggered
hasTriggered = true;
// ...
}
For resetting the hasTriggered flag, that's entirely up to you and how this program works. Maybe after a certain event occurring in the program you'd want to reenable the ability to trigger this event again — all you'd need to do it set the hasTriggered flag back to true.

You can use the mousedown event, which will fire before the input is blurred, and then check if the input has focus by checking if it's the activeElement, and if it does have focus, don't fire the mousedown event, as the change event will fire instead.
Additionally, if you want a mousedown event to occur when the value hasn't changed, and the change event doesn't fire, you'll need a check for that as well
var myInput = $('#test1'),
myButton = $('#test2'),
i = 0;
myInput.change(function(e) { // this triggers first
$(this).data('prev', this.value);
triggerProcess();
});
myButton.mousedown(function(e) { // this triggers second
var inp = myInput.get(0);
if (document.activeElement !== inp || inp.value === myInput.data('prev'))
triggerProcess();
});
function triggerProcess() {
console.log('triggered : ' + (++i))
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="test1">
<br />
<br />
<button id="test2">
Click
</button>

In a fairly typical scenario where you have an input with a button next to ie, eg quick search.
You want to fire when the input changes (ie onblur) but also if the user clicks the button.
In the case where the user changes the input then clicks the button without changing input focus (ie no blur), the change event fires because the text has changed and the click event fires because the button has been clicked.
One option is to debounce the desired event handler.
You can use a plugin or a simple setTimeout/clearTimeout, eg:
$('#inp').change(debounceProcess)
$('#btn').click(debounceProcess);
function debounceProcess() {
if (debounceProcess.timeout != null)
clearTimeout(debounceProcess.timeout);
debounceProcess.timeout = setTimeout(triggerProcess, 100)
}
function triggerProcess() {
console.log('process')
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input id="inp">
<button id="btn">Click</button>

Use a real <button>BUTTON</button>. If you click on input text, alert is triggered, then once you leave the input text to click anywhere else, that unfocuses the input text which triggers the change event, so now 2 events have been triggered from the text input.
This is an assumption since the code provided is far from sufficient to give a complete and accurate answer. The HTML is needed as well as more jQuery/JavaScript. What is myInput and myButton actually referring to, etc.?
So I bet if you change...
var myButton = $('{whatever this is}'); and <input type='button'>
...TO:
var myButton = $("button"); and <button></button>
...you should no longer have an event trigger twice for an element.
This is assuming that triggerProcess() is a function that does something that doesn't manipulate the event chain or anything else involving events. This is an entirely different ballgame if instead of click() and change() methods you are using .trigger() or triggerHandler(), but it isn't. I'm not certain why such complex answers are derived from a question with very little info...?
BTW, if myInput is a search box and myButton is the button for myInput, as freedomn-m has mentioned, simply remove:
myButton.click(...
Leave myButton as a dummy. The change event is sufficient in that circumstance.
SNIPPET
var xInput = $('input');
var xButton = $('button'); //«———Add
xInput.on('change', alarm);
xInput.on('click', alarm);
xButton.on('click', alarm);
function alarm() {
return alert('Activated')
}
/* For demo it's not required */
[type='text'] {
width: 5ex;
}
b {
font-size: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id='f1' name='f1'>
<input type='text'>
<input type='button' value='BUTTON TYPE'>
<label><b>⇦</b>Remove this button</label>
<button>BUTTON TAG</button>
<label><b>⇦</b>Replace it with this button</label>
</form>

Related

How to call a JS function when a textbox text property changes? [duplicate]

Is there any way I can create a constant function that listens to an input, so when that input value changes, something is triggered immediately?
I am looking for something using pure javascript, no plugins, no frameworks and I can't edit the HTML.
Something, for example:
When I change the value in the input MyObject, this function runs.
Any help?
This is what events are for.
HTMLInputElementObject.addEventListener('input', function (evt) {
something(this.value);
});
As a basic example...
HTML:
<input type="text" name="Thing" value="" />
Script:
/* event listener */
document.getElementsByName("Thing")[0].addEventListener('change', doThing);
/* function */
function doThing(){
alert('Horray! Someone wrote "' + this.value + '"!');
}
Here's a fiddle: http://jsfiddle.net/Niffler/514gg4tk/
Actually, the ticked answer is exactly right, but the answer can be in ES6 shape:
HTMLInputElementObject.oninput = () => {
console.log('run'); // Do something
}
Or can be written like below:
HTMLInputElementObject.addEventListener('input', (evt) => {
console.log('run'); // Do something
});
Default usage
el.addEventListener('input', function () {
fn();
});
But, if you want to fire event when you change inputs value manualy via JS you should use custom event(any name, like 'myEvent' \ 'ev' etc.) IF you need to listen forms 'change' or 'input' event and you change inputs value via JS - you can name your custom event 'change' \ 'input' and it will work too.
var event = new Event('input');
el.addEventListener('input', function () {
fn();
});
form.addEventListener('input', function () {
anotherFn();
});
el.value = 'something';
el.dispatchEvent(event);
https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
Another approach in 2021 could be using document.querySelector():
const myInput = document.querySelector('input[name="exampleInput"]');
myInput.addEventListener("change", (e) => {
// here we do something
});
This sounds exactly like the problem I had.
And I would have stated the same question, but I guess it's the same wrong question...
IMHO it's just 'onchange' mistaken as 'oninput' which are 2 different things.
Give me a lot of minus for this statement, I dont care, but I guess it may help one or the other ...
HTML form input contain many events. Refer from MDN document, on the sidebar go to Events menu and expand it. You will see many useful events such as beforeinput, change, copy, cut, input, paste, and drag drop events.
iput & change.
The beforeinput, and input events are fired by order when you type the form input value.
When the form input value has changed and you lost focus on that input, the change event is fired.
Cut, copy, paste.
When you cut (CTRL+X on keyboard shortcut) the input value, the cut, beforeinput, input events are fired.
When you copy (CTRL+C on keyboard shortcut), the copy event is fired alone.
When you paste the value from clipboard (CTRL+V on keyboard shortcut), the paste, beforeinput, input events are fired.
JS change value.
To change input value by JavaScript and make important events work, you need to dispatch at least 2 events by order. One is input and two is change. So that you can focus your code to listened to input or change event. It's easier this way.
Here is all sample code.
(() => {
let inputText = document.getElementById('text');
let submitBtn = document.getElementById('submit');
let triggerJSBtn = document.getElementById('button');
submitBtn.addEventListener('click', (event) => {
event.preventDefault(); // just prevent form submitted.
});
triggerJSBtn.addEventListener('click', (event) => {
const thisTarget = event.target;
event.preventDefault();
inputText.value = thisTarget.innerText;
inputText.dispatchEvent(new Event('input'));
inputText.dispatchEvent(new Event('change'));
});
inputText.addEventListener('beforeinput', (event) => {
const thisTarget = event.target;
console.log('beforeinput event. (%s)', thisTarget.value);
});
inputText.addEventListener('input', (event) => {
const thisTarget = event.target;
console.log('input event. (%s)', thisTarget.value);
});
inputText.addEventListener('change', (event) => {
const thisTarget = event.target;
console.log('change event. (%s)', thisTarget.value);
});
inputText.addEventListener('cut', (event) => {
const thisTarget = event.target;
console.log('cut event. (%s)', thisTarget.value);
});
inputText.addEventListener('copy', (event) => {
const thisTarget = event.target;
console.log('copy event. (%s)', thisTarget.value);
});
inputText.addEventListener('paste', (event) => {
const thisTarget = event.target;
console.log('paste event. (%s)', thisTarget.value);
});
})();
/* for beautification only */
code {
color: rgb(200, 140, 50);
}
small {
color: rgb(150, 150, 150);
}
<form id="form">
<p>
Text: <input id="text" type="text" name="text">
</p>
<p>
Text 2: <input id="text2" type="text" name="text2"><br>
<small>(For lost focus after modified first input text so the <code>change</code> event will be triggered.)</small>
</p>
<p>
<button id="submit" type="submit">
Submit
</button>
<button id="button" type="button">
Trigger JS to set input value.
</button>
</p>
<p>Press F12 to view results in your browser console.</p>
</form>
Please press F12 to open browser's console and see result there.
Each time a user inputs some value, do something.
var element = document.getElementById('input');
element.addEventListener('input', function() {
// Do something
});
Keydown, keyup, input are events that fire immediately when input changes,
I would use keydown or input events to get the changed value from the input box.
const myObject = document.getElementById('Your_element_id');
myObject.addEventListener('keydown', function (evt) {
// your code goes here
console.log(myObject.value);
});
If you would like to monitor the changes each time there is a keystroke on the keyboard.
const textarea = document.querySelector(`#string`)
textarea.addEventListener("keydown", (e) =>{
console.log('test')
})
instead of id use title to identify your element and write the code as below.
$(document).ready(()=>{
$("input[title='MyObject']").change(()=>{
console.log("Field has been changed...")
})
});

trigger focus event will fires blur event(without use alert and browser console)

jsfiddle link
<input id = "focus-ipt" type = "text" value = "nothing" />
var $focusIpt = document.querySelector( "#focus-ipt" );
$focusIpt.addEventListener( "blur", function ( e ) {
$focusIpt.value = "blured!";
} );
setTimeout( function () {
$focusIpt.focus();
}, 1000 );
I just trigger focus event,but blur event fired after focus;
I searched for a long time, close the console, use setTimeout,however, can't solve it;I really don't konw how this happened,can anyone help me?
This is actually not the case; focus() does not automatically trigger blur().
The blur() is getting triggered because you are interacting with the DOM. By clicking on one of the buttons in your fiddle (such as Run or Tidy), the #focus-ipt element is no longer active -- the button you're clicking on is.
If you simply wait the time out, without doing anything, the blur() event won't occur. As soon as you click off of the input, the blur() will occur.
This can be seen in the following example:
var $focusIpt = document.querySelector("#focus-ipt");
$focusIpt.addEventListener("blur", function(e) {
$focusIpt.value = "Blurred!";
});
setTimeout(function() {
$focusIpt.focus();
}, 1000);
<input id="focus-ipt" type="text" id="myText" value="Sample Text">
<button type="button">Click me to lose focus</button>
Hope this helps! :)

Handle dialog-close event on input type='color'

Here is a default(html5) color selector:
<input id='color-picker' type=color value='#ff0000'>
By click on the element, a default color-picker dialog opens.
I can easily track the color change event:
$('#color-picker').on('change', function() {
console.log($(this).val());
});
How dialog window close event can be handled? For example, when user clicks Cancel button?
Here is jsfiddle additionally.
Unfortunately, the exact functionality is not possible. I even read through the stack link, it seems that file calls the change event regardless of change, whereas color does not... So, I added the code to the blur event instead. When the user click off the value after editing color for any reason, it will check for cancel. I added a phony submit button to force the user to do it.
$('#color-picker').on('blur', function() {
if ($(this).data("prevColor") == $(this).val()) {
console.log('cancelled');
} else {
//value changed
}
updateData.bind(this)();
});
function updateData() {
$(this).data("prevColor", $(this).val());
}
updateData.bind($("#color-picker"))();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id='color-picker' type=color value='#ff0000'><button>Submit</button>
I've used this for the Cancel and Close Events.
var prevColor;
$('#color-picker').onchange = function(){
if (this.value != prevColor){
prevColor = this.value;
}
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id='color-picker' type=color value='#ff0000'><button>Submit</button>

JQuery focus to previous clicked input bug

I have two input fields. The main idea is that whenever you focus to one of the fields, the button click should print a random number inside it.
My problem is that when you just focus on (click on) the first field, then focus on second (or vice versa), the button click prints to both instead of just to the (last) focused field.
You can try to recreate the problem here: http://jsfiddle.net/sQd8t/3/
JS:
$('.family').focus(function(){
var iD = $(this).attr('id');
$("#sets").one('click',function() {
var ra = Math.floor((Math.random()*10)+1);
$('#'+iD).val(ra);
});
});
HTML:
<center class='mid'>
<input type="text" class="family" id="father" />
<br/><br>
<input type="text" class="family" id="mother" />
<br/>
<br/>
<input type='submit' value='Set text' id="sets"/>
</center>
In the "focus" handler, unbind any existing "click" handler:
$('#sets').unbind('click').one('click', function() { ... });
The way you had it, an additional one-shot "click" handler is bound each time a field gets focus, because jQuery lets you bind as many handlers as you like to an event. In other words, calling .one() does not unbind other handlers. When the click actually happens, all handlers are run.
edit — sorry - "unbind" is the old API; now .off() is preferred.
Put the variable iD outside, and separate the functions:
http://jsfiddle.net/sQd8t/8/
This prevents from adding too many events on each input click/focus.
No need to unbind.
var iD;
$('.family').focus(function() {
iD = $(this).attr('id');
});
$("#sets").on('click', function() {
var ra = Math.floor((Math.random() * 10) + 1);
if (iD!="")$('#' + iD).val(ra);
iD = "";
});
See http://jsfiddle.net/sQd8t/11/
$('.family').focus(function(){
$("#sets").attr('data-target',$(this).attr('id'))
});
$("#sets").click(function() {
var target=$(this).attr('data-target');
if(target){
var ra = Math.floor((Math.random()*10)+1);
$('#'+target).val(ra);
}
});
You can create a data-target attribute which contains the field which must be modified.

How to execute a function using the value of a textbox Onclick of a DIV instead of a Onclick of a textbox

I have this function:
$("#border-radius").click(function(){
var value = $("#border-radius").attr("value");
$("div.editable").click(function (e) {
e.stopPropagation();
showUser(value, '2', this.id)
$(this).css({
"-webkit-border-radius": value
});
});
});
It reads the value of a textbox,
input type="text" id="border-radius" value="20px"
...and does a few things with it that are not relevant to my problem.
The textbox has the id="border-radius", and when it is clicked (and has a value) the function executes, as shown: $("#border-radius").click(function(){ ...do some stuff...
Basically, I want to be able to type a value into the textbox, and then click an object (submit button or div, preferably a div) and have it execute the function after: $("#border-radius").click(function(){ ...do some stuff... Instead of having to click the textbox itself
What can I add/change to enable this?
I think you need to identify the event target.
that you can do it by
event target property
example
$(document).ready(function() {
$("#border-radius").click(function(event) {
alert(event.target.id);
//match target id and than proceed futher
});
});
Put the click handler on #my-button or whatever your button is.
$("#my-button").click(function(){
var value = ... /* your original code */
});
It will still work because you are getting the value like $("#border-radius").attr("value"); and not $(this).attr("value");. So you all you need to change is which element you attach the click function to.
Alternatively, if you want to keep both handlers, you can just use it for both elements like this:
var commonHandler = function(){
var value = ... /* your original code */
};
$("#border-radius").click(commonHandler);
$("#my-button").click(commonHandler);
You can also trigger the click event of #border-radius, but this will execute all the event handlers attached on it:
$("#my-button").click(function () {
$("#border-radius").click();
// or $("#border-radius").trigger('click');
});

Categories