I have an input field and a button. It is necessary that when the button is clicked the input field gets focus.
I need the behaviour to be slightly different depending on whether the input field was focused manually by the user or if it was focused due the button being clicked.
It seems this would be relatively simple, but I couldn't come up with a solution so far. Any ideas very welcome.
$("button").click(function() {
target_input = $("input");
target_input.focus();
});
$("input").focus(function() {
// if focus done manually by user
// do something
// if focus done via button
// do something else
});
Here is a solution that uses no extra variables, instead it checks the event.
$("button").click(function() {
target_input = $("input");
target_input.focus();
});
$("input").focus(function(e) {
// if focus done manually by user
// do something
// if focus done via button
// do something else
if(e.originalEvent.relatedTarget){
// only from button events
}
// here is from all events
});
this e.originalEvent.relatedTarget will return null if we didn't use the button to originate the focus.
remember to add e to the function.
You should be able to use Event.isTrusted for this:
The isTrusted read-only property of the Event interface is a boolean
that is true when the event was generated by a user action, and false
when the event was created or modified by a script or dispatched via
dispatchEvent.
$("input").focus(function(e) {
if(e.isTrusted) {...} else {...}
});
As noted in the comments, neither IE nor Safari like this.
This works without global variables and it is cross-browser working solution:
$('button').click(function () {
$(this).prev('input').focus()
})
$('input').click(function (e) { // yes, listen to click instead
// original event exists only if input was clicked directly
if (e.originalEvent) {
console.log('manually triggered')
}
})
<div style="background-color: yellow;">
<input type="text">
<button>Focus input</button>
<br>
<input type="text">
<button>Focus input</button>
</div>
<script src="https://unpkg.com/jquery"></script>
It seems disabled button "onclick" function is still fired when triggering it programmaticaly, eg:
<div>
<input type="button" onclick="save()" id="saveButton" value="save" disabled="disabled" />
<input type="button" onclick="byPassDisabled()" value="bypass disabled button"/>
<div id="counter">0</div>
function save(){
var count = parseInt($('#counter').html());
$('#counter').html(++count);
}
function byPassDisabled(){
$('#saveButton').click();
}
see http://jsfiddle.net/WzEvs/363/
In my situation, keyboards shortcuts are bound to functions triggering the ".click()" on buttons. I'll find it very annoying to have to disable the shorcuts or check if the button is disabled myself. I'd prefer a general solution fixing this problem.
But why? This behavior doesn't seem fair to me.
Any workaround?
The attribute only disables user interaction, the button is still usable programmatically.
So yeah, you gotta check
function byPassDisabled(){
$('#saveButton:enabled').click();
}
Alternatively don't use inline handlers.
$(document).on('click', '#saveButton:enabled', function(){
// ...
});
For future use...the OP code works because jQuery will still call it's own handlers even if the DOM element is disabled. If one were to use vanilla javascript, the disabled attribute would be honored.
const element = document.getElementById('saveButton');
element.click() //this would not work
You can programmatically trigger click on a disabled button.
There are ways to find if the event is a click on button by user or it has been trigger programmatically. http://jsfiddle.net/WzEvs/373/
$(function () {
$("#saveButton").on('click', function (e) {
if (!e.isTrigger) {
var count = parseInt($('#counter').html());
$('#counter').html(++count);
}
});
$("#bypassButton").on('click', function (e) {
$("#saveButton").click();
});
});
e.isTrigger is true if you call the click() programmatically. Basically you are triggering the click event manually in code.
You can trigger click still although made it disable .As Spokey said it just shows the user-interaction(the usability still persists that can be turned on programmatically) .
off or unbind the click will solve this issue.
Thanks
We have a lot of inputs in a document.
We want to open a dialog that generates text and puts that in the currently focused input.
The problem is that, when I click a button or anything else to open the dialog that input loses focus. I can't determine which input has to get the generated text.
$("#button").click(function(){
// something should goes here to prevent stealing inputs focus
});
Is there any solution to prevent stealing focus by that special button?
You could not use a form button and just use say a <span> make it behave like a button?
UPDATE:
You could use something like
$('span').hover(function(){
focused_element = $("*:focus").get(0);
});
$('span').click(function(){
focused_element.focus();
});
Check out my fiddle
Does your field have a unique ID? If it does, use that ID to set the focus back to the field when the dialog's save/close button is clicked.
Don't worry about having the focus stolen as much as resetting it once you are done.
My solution would be to handle every focus and save it in focusEle:
$(function () {
var focusEle;
$('*').focus(function () {
focusEle = this;
});
$('button').click(function (e) {
console.log(focusEle);
var c = confirm('Love the cat :3?');
$(focusEle).focus();
});
});
With HTML as:
<input type="text">
<button>Press me!</button>
Example is working: http://jsfiddle.net/76uv7/
Depending on #ggzone idea
I have the same problem as the user in this question, which is due to this bug in Webkit. However, the workaround provided will not work for my app. Let me re-state the problem so that you don't have to go read another question:
I am trying to select all the text in a textarea when it gets focus. The following jQuery code works in IE/FF/Opera:
$('#out').focus(function(){
$('#out').select();
});
However, in Chrome/Safari the text is selected--very briefly--but then the mouseUp event is fired and the text is deselected. The following workaround is offered in the above links:
$('#out').mouseup(function(e){
e.preventDefault();
});
However, this workaround is no good for me. I want to select all text only when the user gives the textarea focus. He must then be able to select only part of the text if he chooses. Can anyone think of a workaround that still meets this requirement?
How about this?
$('#out').focus(function () {
$('#out').select().mouseup(function (e) {
e.preventDefault();
$(this).unbind("mouseup");
});
});
The accepted answer (and basically every other solution I found so far) does not work with keyboard focus, i. e. pressing tab, at least not in my Chromium 21. I use the following snippet instead:
$('#out').focus(function () {
$(this).select().one('mouseup', function (e) {
$(this).off('keyup');
e.preventDefault();
}).one('keyup', function () {
$(this).select().off('mouseup');
});
});
e.preventDefault() in the keyup or focus handler does not help, so the unselecting after a keyboard focus seems to not happen in their default handlers, but rather somewhere between the focus and keyup events.
As suggested by #BarelyFitz, it might be better to work with namespaced events in order to not accidentally unbind other event handlers. Replace 'keyup' with 'keyup.selectText' and 'mouseup' with 'mouseup.selectText' for that.
Why not simply:
$('#out').focus(function(){
$(this).one('mouseup', function() {
$(this).select();
});
});
Seems to work in all major browsers...
A very slightly different approach would be to separate the focus event from the mouse sequence. This works really nicely for me - no state variables, no leaked handlers, no inadvertent removal of handlers, and it works with click, tab, or programmatic focus. Code and jsFiddle below -
$('#out').focus(function() {
$(this).select();
});
$('#out').on('mousedown.selectOnFocus', function() {
if (!($(this).is(':focus'))) {
$(this).focus();
$(this).one('mouseup.selectOnFocus', function(up) {
up.preventDefault();
});
}
});
https://jsfiddle.net/tpankake/eob9eb26/27/
Make a bool. Set it to true after a focus event and reset it after a mouse up event. During the mouse up, if it's true, you know the user just selected the text field; therefore you know you must prevent the mouse up from happening. Otherwise, you must let it pass.
var textFieldGotFocus = false;
$('#out').focus(function()
{
$('#out').select();
textFieldGotFocus = true;
});
$('#out').mouseup(function(e)
{
if (textFieldGotFocus)
e.preventDefault();
});
$(document).mouseup(function() { textFieldGotFocus = false; });
It's important that you put the mouseup listener that resets the variable on document, since it's not guaranteed that the user will release the mouse button over the text field.
onclick="var self = this;setTimeout(function() {self.select();}, 0);"
Select the text before putting the focus on the input box.
$('#out').select().focus();
digitalfresh's solution is mostly there, but has a bug in that if you manually trigger .focus() using JS (so not using a click), or if you tab to the field, then you get an unwanted mouseup event bound - this causes the first click that should deselect the text to be ignored.
To solve:
var out = $('#out');
var mouseCurrentlyDown = false;
out.focus(function () {
out.select();
if (mouseCurrentlyDown) {
out.one('mouseup', function (e) {
e.preventDefault();
});
}
}).mousedown(function() {
mouseCurrentlyDown = true;
});
$('body').mouseup(function() {
mouseCurrentlyDown = false;
});
Note: The mouseup event should be on body and not the input as we want to account for the user mousedown-ing within the input, moving the mouse out of the input, and then mouseup-ing.
tpankake's answer converted to a reusable jQuery function..
(If you upvote this, please also upvote his answer)
Load the following AFTER loading the jQuery library:
$.fn.focusSelect = function () {
return this.each(function () {
var me = $(this);
me.focus(function () {
$(this).select();
});
me.on('mousedown.selectOnFocus', function () {
var me2 = $(this);
if (me2.is(':focus') === false) {
me2.focus();
me2.one('mouseup.selectOnFocus', function (up) {
up.preventDefault();
});
}
});
});
};
Use it like this:
$(document).ready(function () {
// apply to all inputs on the page:
$('input[type=text]').focusSelect();
// apply only to one input
$('#out').focusSelect();
});
There are many ways the value of a <input type="text"> can change, including:
keypresses
copy/paste
modified with JavaScript
auto-completed by browser or a toolbar
I want my JavaScript function to be called (with the current input value) any time it changes. And I want it to be called right away, not just when the input loses focus.
I'm looking for the cleanest and most robust way to do this across all browsers (using jQuery preferably).
This jQuery code uses .bind() to catch immediate changes to any element, and should work across all browsers:
$('.myElements').each(function() {
var elem = $(this);
// Save current value of element
elem.data('oldVal', elem.val());
// Look for changes in the value
elem.bind("propertychange change click keyup input paste", function(event){
// If value has changed...
if (elem.data('oldVal') != elem.val()) {
// Updated stored value
elem.data('oldVal', elem.val());
// Do action
....
}
});
});
However, note that .bind() was deprecated in jQuery version 3.0. Anyone using jQuery version 1.7 or newer should use .on() instead.
A real-time solution for jQuery >= 1.7 is on
$("#input-id").on("change keyup paste", function(){
dosomething();
})
if you also want to detect "click" event, just:
$("#input-id").on("change keyup paste click", function(){
dosomething();
})
if you're using jQuery <= 1.6, just use bind or live instead of on.
Unfortunately, I think setInterval wins the prize:
<input type=text id=input_id />
<script>
setInterval(function() { ObserveInputValue($('#input_id').val()); }, 100);
</script>
It's the cleanest solution, at only 1 line of code. It's also the most robust, since you don't have to worry about all the different events/ways an input can get a value.
The downsides of using 'setInterval' don't seem to apply in this case:
The 100ms latency? For many applications, 100ms is fast enough.
Added load on the browser? In general, adding lots of heavy-weight setIntervals on your page is bad. But in this particular case, the added page load is undetectable.
It doesn't scale to many inputs? Most pages don't have more than a handful of inputs, which you can sniff all in the same setInterval.
Binding to the input event seems to work fine in most sane browsers. IE9 supports it too, but the implementation is buggy (the event is not fired when deleting characters).
With jQuery version 1.7+ the on method is useful to bind to the event like this:
$(".inputElement").on("input", null, null, callbackFunction);
Unfortunately there is no event or set of events that matches your criteria. Keypresses and copy/paste can both be handled with the keyup event. Changes through JS are trickier. If you have control over the code that sets the textbox, your best bet is to modify it to either call your function directly or trigger a user event on the textbox:
// Compare the textbox's current and last value. Report a change to the console.
function watchTextbox() {
var txtInput = $('#txtInput');
var lastValue = txtInput.data('lastValue');
var currentValue = txtInput.val();
if (lastValue != currentValue) {
console.log('Value changed from ' + lastValue + ' to ' + currentValue);
txtInput.data('lastValue', currentValue);
}
}
// Record the initial value of the textbox.
$('#txtInput').data('lastValue', $('#txtInput').val());
// Bind to the keypress and user-defined set event.
$('#txtInput').bind('keypress set', null, watchTextbox);
// Example of JS code triggering the user event
$('#btnSetText').click(function (ev) {
$('#txtInput').val('abc def').trigger('set');
});
If you don't have control over that code, you could use setInterval() to 'watch' the textbox for changes:
// Check the textbox every 100 milliseconds. This seems to be pretty responsive.
setInterval(watchTextbox, 100);
This sort of active monitoring won't catch updates 'immediately', but it seems to be fast enough that there is no perceptible lag. As DrLouie pointed out in comments, this solution probably doesn't scale well if you need to watch lots of inputs. You can always adjust the 2nd parameter to setInterval() to check more or less frequently.
Here is a solution that doesn't make use of jQuery (Its really quite obsolete and not necessary these days)
Using the event "input" you can look for any kind of change:
Deleting, Backspacing, Pasting, Typing, anything that will change the inputs value.
The input event is directly related to the text input. ANY time the text is changed in ANY fashion, input is dispatched.
document.querySelector("#testInput").addEventListener("input", test);
function test(e) {
var a = document.getElementById('output');
a.innerText += "Detected an Update!\n";
}
<input id="testInput">
<br>
<a id="output"></a>
Here is a slightly different solution if you didn't fancy any of the other answers:
var field_selectors = ["#a", "#b"];
setInterval(function() {
$.each(field_selectors, function() {
var input = $(this);
var old = input.attr("data-old-value");
var current = input.val();
if (old !== current) {
if (typeof old != 'undefined') {
... your code ...
}
input.attr("data-old-value", current);
}
}
}, 500);
Consider that you cannot rely on click and keyup to capture context menu paste.
Add this code somewhere, this will do the trick.
var originalVal = $.fn.val;
$.fn.val = function(){
var result =originalVal.apply(this,arguments);
if(arguments.length>0)
$(this).change(); // OR with custom event $(this).trigger('value-changed');
return result;
};
Found this solution at val() doesn't trigger change() in jQuery
I have created a sample. May it will work for you.
var typingTimer;
var doneTypingInterval = 10;
var finaldoneTypingInterval = 500;
var oldData = $("p.content").html();
$('#tyingBox').keydown(function () {
clearTimeout(typingTimer);
if ($('#tyingBox').val) {
typingTimer = setTimeout(function () {
$("p.content").html('Typing...');
}, doneTypingInterval);
}
});
$('#tyingBox').keyup(function () {
clearTimeout(typingTimer);
typingTimer = setTimeout(function () {
$("p.content").html(oldData);
}, finaldoneTypingInterval);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<textarea id="tyingBox" tabindex="1" placeholder="Enter Message"></textarea>
<p class="content">Text will be replace here and after Stop typing it will get back</p>
http://jsfiddle.net/utbh575s/
We actually don't need to setup loops for detecting javaScript changes.
We already setting up many event listeners to the element we want to detect. just triggering any un harmful event will make the job.
$("input[name='test-element']").on("propertychange change click keyup input paste blur", function(){
console.log("yeh thats worked!");
});
$("input[name='test-element']").val("test").trigger("blur");
and ofc this is only available if you have the full control on javascript changes on your project.
Although this question was posted 10 years ago, I believe that it still needs some improvements. So here is my solution.
$(document).on('propertychange change click keyup input paste', 'selector', function (e) {
// Do something here
});
The only problem with this solution is, it won't trigger if the value changes from javascript like $('selector').val('some value'). You can fire any event to your selector when you change the value from javascript.
$(selector).val('some value');
// fire event
$(selector).trigger('change');
Or in a single line
$(selector).val('some value').trigger('change');
Well, best way is to cover those three bases you listed by yourself. A simple :onblur, :onkeyup, etc won't work for what you want, so just combine them.
KeyUp should cover the first two, and if Javascript is modifying the input box, well I sure hope it's your own javascript, so just add a callback in the function that modifies it.
Here's a working example that I'm using to implement an autocomplete variation the populates a jqueryui selector (list), but I don't want it to function exactly like the jqueryui autocomplete which does a drop-down menu.
$("#tagFilter").on("change keyup paste", function() {
var filterText = $("#tagFilter").val();
$("#tags").empty();
$.getJSON("http://localhost/cgi-bin/tags.php?term=" + filterText,
function(data) {
var i;
for (i = 0; i < data.length; i++) {
var tag = data[i].value;
$("#tags").append("<li class=\"tag\">" + tag + "</li>");
}
});
});
Can't you just use <span contenteditable="true" spellcheck="false"> element in place of <input type="text">?
<span> (with contenteditable="true" spellcheck="false" as attributes) distincts by <input> mainly because:
It's not styled like an <input>.
It doesn't have a value property, but the text is rendered as innerText and makes part of its inner body.
It's multiline whereas <input> isn't although you set the attribute multiline="true".
To accomplish the appearance you can, of course, style it in CSS, whereas writing the value as innerText you can get for it an event:
Here's a fiddle.
Unfortunately there's something that doesn't actually work in IE and Edge, which I'm unable to find.
you can simply identify all changers in the form, like this
//when form change, show aleart
$("#FormId").change(function () {
aleart('Done some change on form');
});
You can bind the 'input' event to <input type="text">. This will trigger every time the input changes such as copy, paste, keypress, and so on.
$("#input-id").on("input", function(){
// Your action
})