I have previously entered value 1111, 1222, and 1333 into a HTML text input. Now if I enter 1 to the text input, it should popup a list with value 1111, 1222, and 1333 as available options. How do you trigger an event when any one of these options is selected?
I have a javascript function that performs a calculation on values entered into the text input via "onkeyup" event. This works very well if the user just enter value via keyboard. However, it does not work if the user is selecting a previously entered value from the auto popup list.
I know we can turn off the auto popup list by adding autocomplete="off" to the form/text input. But is there any solution to make it work with the auto popup list? I have tried all available event options including "onchange", but none of those works.
The HTML code is very simple:
<input id="elem_id_1" name="output" type="text" value="0" onkeyup="update();"/>
The js function is very simple too:
function update() {
var a = $('elem_id_1').value;
$('elem_id_2').value = a / 100;
}
Have you tried the onchange event? I'm not sure if it fires for auto-complete selection, but you could also try the onpropertychange event and check for the value property:
textInput.onpropertychange = function ()
{
if (event.propertyName == "value")
doCalculation();
}
This would also work on right-click->paste or right-click->cut, which wouldn't fire your calculation using your current method.
EDIT
It looks like you might have to use a combination of events and timers. Set an interval on focus of the edit and clear it on blur. I'd also use the onpropertychange for IE to make it more efficient and keep the keyup event to make it rather quick too.
//- If it's IE, use the more efficient onpropertychange event
if (window.navigator.appName == "Microsoft Internet Explorer")
{
textInput.onpropertychange = function ()
{
if (event.propertyName == "value")
doCalculation();
}
}
else
{
var valueCheck, lastValue = "";
textInput.onkeyup = function ()
{
doCalculation();
}
textInput.onfocus = function ()
{
valueCheck = window.setInterval(function ()
{
// Check the previous value against (and set to) the new value
if (lastValue != (lastValue = textInput.value))
doCalculation();
}, 100);
}
textInput.onblur = function ()
{
window.clearInterval(valueCheck);
}
}
If your calculation routine is tiny (like a simple mathematical equation), I would just leave out the previous value check and run the calculation every 100ms.
Related
I have the following input field:
<input onPaste={pasteFunction} keyUp={keyupFunction} />
I want either the pasteFunction or keyupFunction to run, NOT both. But when a user pastes text into this field both events get triggered and both run.
Is there a way to prevent keyUp if something was pasted into the field?
I tried to set a flag and reset it:
function pasteFunction() {
pasteInProgress = true;
//etc...
pasteInProgress = false;
}
function keyupFunction() {
if (pasteInProgress) return;
//etc...
}
But this doesn't work as pasteInProgress is set to false before keyupFunction is triggered.
You could try storing the time instead, for example.
function pasteFunction() {
lastPaste = Date.now();
//etc...
}
function keyupFunction() {
//less than one second has passed.
if (Date.now()-lastPaste<1000) return;
//etc...
}
Maybe try experimenting with different times depending on the application, but it is still a "hacky" way to solve it. I think there could be better ways.
Is there a way to prevent keyUp if something was pasted into the field?
Assuming you are using a ui library (react?), you could store a value in the component state when something was pasted into the field.
this.state = {
hasPasted: false;
}
function pasteFunction() {
this.state.hasPasted = true; // could also be a timestamp if you need granularity
}
function keyupFunction(e) { // assuming you can pass event here
if (this.state.hasPasted){
// you may want to preventDefault() here
e.preventDefault();
return;
};
}
Without you sharing more context/code, this should do it.
I have an
<input type="number" class="post-purchase-amount"/>.
I am calling an
ajax call when the value get changed. It is working (with the following code) when the cursor is in the
text box itself and doing any changes. But it not working when i click the spinner (up/down button) of the input type.
parentPanel.on("change", ".post-purchase-amount", null, function (event) {
updateAmount($(this));
});
My problem is that i could use the "input" event here but that can call the ajax
every time when in change the value like if i want to send value 65
then it calls twice when typing each number. I need to call ajax only when the value has been changed not every key
stroke.
Sorry for my English. Thanks in advance
How about you create a function to throttle the input and trigger it on keypress instead. Something like this:
function throttle(func, interval) {
var last = 0;
return function() {
var now = Date.now();
if (last + interval < now) {
last = now;
return func.apply(this, arguments);
}
};
}
parentPanel.on("keypress", ".post-purchase-amount", null, throttle(function(event) {
updateAmount($(this));
}, 800));
Your problem is that you are watching for a change and anytime you make a change this is going to fire. What you could do instead is use focusout to watch when you "exit" the number input. What the below function does is it checks to see if the previous value is equal to the new value when you exit focus on the input. If the current value is not the same then it has been updated.
var prevVal = $('.numOfPeople').val();
$('.numOfPeople').on('focusout', null, function(e) {
var curVal = $('.numOfPeople').val();
if(prevVal !== curVal) {
//Value is different so do your updates here.
preVal = curVal;
$('#changed').show();
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input class="numOfPeople" type="number" name="quantity" min="1" max="5">
<p id="changed" style="display: none;">Value has changed</p>
I have a hidden input in my HTML code and i want to know when the input value has changed.
<input type="hidden" id="myInputHidden" />
I can make something like this:
$('#myInputHidden').on('change', function() {
alert('triggered');
});
In the first place, this doesn't work and in many posts i have read that i must trigger manually the event.
The problem is that i don't know when (and where) the input value is changed so i cannot trigger that event.
The only way to implement a change event to a hidden field is by dirty-checking, e.g:
(function() {
var myHidden = document.getElementById('myInputHidden'),
currentValue = myHidden.value;
setTimeout(function myHiddenOnChange() {
if (myHidden.value !== currentValue) {
currentValue = myHidden.value;
myHiddenChanged.call(myHidden);
}
setTimeout(myHiddenOnChange, 30);
}, 30);
function myHiddenChanged() {
// that's your hidden field's 'change' event
}
})();
I don't recommend it, but another approach is to override the HTMLInputElement.prototype descriptor:
(function() {
var _htmlInputElementValue = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value'),
_htmlInputElementValueSet = _htmlInputElementValue.set,
_ev = document.createEvent('Event');
_ev.initEvent('change', true, true);
_htmlInputElementValue.set = function() {
_htmlInputElementValueSet.apply(this, [].slice.call(arguments));
if (this.type === 'hidden') {
this.dispatchEvent(_ev);
}
}
Object.defineProperty(HTMLInputElement.prototype, 'value', _htmlInputElementValue);
})();
Doing that, anytime someone changes the value property of a hidden field, it triggers the change event, so, if you're listening to that event, your code will start working.
I'm trying to fire a function whenever the value of an input field changes. The input field is in a lightbox so I have to delegate the event:
var validateDonation = function(elem) {
var msg,
value = elem.value;
if (value == '') { msg = 'Please enter an amount'; }
else if(parseInt(value, 10) < 1) { msg = 'Please enter an amount greater than 1'; }
else if(parseInt(value, 10) > 100) { msg = 'Please enter an amount less than 100'; }
else { msg = ''; }
if(msg != '') {
console.log(msg);
}
}
and
$('body').delegate('#donation_amount', 'change', function(event) {
validateDonation(this);
});
If I use keyup instead of change the console log works just fine. But not on change. Why?
https://msdn.microsoft.com/en-us/library/ms536912(v=vs.85).aspx
onchange: This event is fired when the contents are committed and not while the value is changing. For example, on a text box, this event is not fired while the user is typing, but rather when the user commits the change by leaving the text box that has focus. In addition, this event is executed before the code specified by onblur when the control is also losing the focus.
If you want the change to be instantly updated then you would want to use the oninput event
oninput: The DOM input event is fired synchronously when the value of an <input> or <textarea> element is changed. Additionally, it fires on contenteditable editors when its contents are changed.
For IE less than IE9 i believe you need to use the onpropertychange event as well as oninput to accommodate modern browsers.
Here is a fiddle to show you the event fires immediately
http://jsfiddle.net/SeanWessell/9jfkcapp/
Try this...
$('body').delegate('#donation_amount', 'input propertychange', function (event) {
validateDonation(this);
});
How to add multiple event listeners in the same initialization?
For example:
<input type="text" id="text">
<button id="button_click">Search</button>
JavaScript:
var myElement = document.getElementById('button_click');
myElement.addEventListener('click', myFunc());
This is working correctly however I would like to have another event listener for this input filed in the same call if that is possible, so when user clicks enter or presses the button it triggers the same event listener.
Just one note. User needs to be focused on the input field to trigger an "enter" event.
Just bind your function to 2 listeners, each one of the wished element:
document.getElementById('button_click').addEventListener('click', myFunc);
document.getElementById('text').addEventListener('keyup', keyupFunc);
where the new function test if the user pressed enter and then execute the other function :
function keyupFunc(evt) {
if(evt.keyCode === 13) // keycode for return
myFunc();
}
Working jsFiddle : http://jsfiddle.net/cG7HW/
Try this:
function addMultipleEvents(elements, events){
var tokens = events.split(" ");
if(tokens.length == elements.length){
for(var i = 0; i< tokens.length; i++){
elements[i].addEventListener(tokens[i], (e.which == 13 || e.which == 48)?myFunc:); //not myFunc()
}
}
}
var textObj = document.getElementById("textId");
var btnObj = document.getElementById("btnId");
addMultipleEvents([textObj,btnObj], 'click keyup');
UPDATE:
function addMultipleEvents(elements, events) {
var tokens = events.split(" ");
if (tokens.length == elements.length) {
for (var i = 0; i < tokens.length; i++) {
elements[i].addEventListener(tokens[i], myFunc); //not myFunc()
}
}
}
var textObj = document.getElementById("textId");
var btnObj = document.getElementById("btnId");
addMultipleEvents([btnObj, textObj], 'click keyup');
function myFunc(e) {
if (e.which == 13 || e.which == 1) {
alert("hello");
}
}
Working Fiddle
I think the best way to do this is by using for loops.
const events = ["click", "mouseover"]
for (i in events) {
document.getElementById("button_click").addEventListener(events[i], () => myFunc())
}
The code above loops through every events inside an array and adds it to the button.
Yeah this is a good question and can apply to other scenarios. You have a form and a user will have input text field, a radio box, a select option. So now you want the submit button to go from disabled to enabled. You decide to add an event listener to check if fieldA and fieldB and fieldC is first to enable submit button.
If you use event listener on Keyup", and all your fields are valid, the submit button will become enabled only if the last field is a text field because the event will only be triggered when you let go the key. This means it will not trigger if the radio box or select option is selected with your mouse. We must not rely in the order the fields are filled for the logic to work. Again, If you use "click", it sucks, because user will have to click somewhere on page in order for the event listener to fire and run the logic. So i think we'll need an event lister on mouseup, keyup and change for this example below. I assume you made all your validations and variables for the form fields already. We need a function with parameters of multiple events names as a string, the element we want to target (document, or button or form), and a custom function that contains our logic.
// Create function that takes parameters of multiple event listeners, an element to target, and a function to execute logic
function enableTheSubmitButton(element, eventNamesString, customFunction) {
eventNamesString.split(' ').forEach(e => element.addEventListener(e, listener, false));
}
// Call the above function and loop through the three event names inside the string, then invoke each event name to your customFunction, you can add more events or change the event names maybe mousedown, keyup etc.
enableSubmitButton(document, 'keyup mouseup change', function(){
// The logic inside your customFunction
if (isNameValid && isLocationValid && isProjectValid){
publishButton.disabled = false;
} else {
publishButton.disabled = true;
// Do more stuff like: "Hey your fields are not valid."
}
});
// The isNameValid isLocationValid, isProjectValid are coming from your previous validation Javascript for perhaps a select field, radio buttons, and text fields. I am adding it as an example, they have to be equal to true.
// The publishButton is a variable to target the form submit button of which you want enabled or disabled based one weather the form fields are valid or not.
// For example: const publishButton = document.getElementById("publish");