20

I have an HTML form with multiple text inputs. I want to clear the element that had the focus immediately prior to when the 'Clear' button is pressed. How do I get that element in JavaScript?

Note: Reworded to take comments into account.

mklement0
  • 382,024
  • 64
  • 607
  • 775
HashimR
  • 3,803
  • 8
  • 32
  • 49
  • 1
    The current focused element when the "Clear" button is pressed will be the "Clear" button itself. OK, so I'm being a bit silly and obviously you want to know which field just lost focus, but what if the user navigates to "Clear" using the tab key? – nnnnnn Sep 07 '11 at 05:23
  • 1
    you should edit the tile of this question, because none of the answer really answers "How to get current focused element in javascript" and I came here by searching that... – Baptiste Pernet Mar 07 '12 at 16:31
  • @BaptistePernet: Check out blessed's answer... – HashimR Apr 16 '12 at 12:01

9 Answers9

14

Create a global variable for storing the current focused element's id,

var cur_id;

call one function for onblur of each of elements and pass id

<input type="text" id="name" name="name" onBlur="setId(this.id)">

and write the set the id to global variable from that function

function setId(id) {
    cur_id = id;
}

and write a function for onclick of clear button, like this

function clear() {
    document.getElementById(cur_id).value = "";
}
Tim Down
  • 318,141
  • 75
  • 454
  • 536
laradev
  • 868
  • 1
  • 10
  • 22
  • how about creating a *local* variable? too edgy, I know – Ricardo Tomasi Sep 07 '11 at 06:06
  • @shesek - this isn't obtrusive, it's just hard to maintain due to the multiple inline onblurs. (Your answer is better.) The whole requirement is obtrusive in that it isn't possible without JavaScript. – nnnnnn Sep 07 '11 at 06:09
  • 4
    @shesek: It's valid and causes no harm, and may be appropriate in context, so I'd say that's a harsh downvote. – Tim Down Sep 07 '11 at 08:30
  • I don't think obtrusive JavaScript is ever appropriate and it should be avoided at all costs. JavaScript code shouldn't live within HTML pages, that's just wrong. That being said... I am undoing the downvote - because its such a common practice, maybe it is a bit too harsh. **edit** Sorry, apparently you can't undo votes after 3 hours (unless the answer was edited since) – shesek Sep 07 '11 at 09:16
  • @shesek: I've edited the answer to have better code formatting, so you can now remove the downvote if you want. I do agree that in general unobtrusive JavaScript is the way to go but I'd still use an event handler attribute for a trivial demo or similar because it's just simpler and quicker to type than the other alternatives. HTML5 still supports event handler attributes, so they're not going away any time soon. – Tim Down Sep 08 '11 at 23:38
  • I used a "live" jquery event handler to do this for all input elements, even dynamically added ones: `var prev_focused; $(document).on('blur', ':input', function(e) { prev_focused = e.target; });` I'm not sure how to do that without jquery, would have to look it up again. – Sam Watkins May 10 '19 at 07:02
13

When you click "clear" button, only element focused is "clear" button. You'll have to workaround it. (trigger onblur event)

genesis
  • 50,477
  • 20
  • 96
  • 125
  • yea. that is the problem. i tried to use document.activeElement but no use. :( – HashimR Sep 07 '11 at 05:18
  • 2
    Ohh that paradox is tragic... * sob sob * – DhruvPathak Sep 07 '11 at 05:19
  • 2
    I hate the way the `focus` event doesn't have a `justblurred` (or similar) property. It could be `null` where it's not a particular element. – nnnnnn Sep 07 '11 at 05:33
  • @genesis φ - onblur doesn't do what I was wishing for: like some other answers have said you still have to take the trouble to save the blurred element and then access that from your onfocus handler (and some browsers trigger those events in a weird order, which doesn't help). I was wishing that the focus event itself could tell you what just blurred, and perhaps the blur event should tell you what just focused, so that you don't have to write your own coordination code to achieve it. – nnnnnn Sep 07 '11 at 23:54
8

The simplest way is to store a reference to document.activeElement within the mousedown event on the button, although this is a mouse-centric approach and won't work for button "clicks" from keyboards and other devices.

Live demo: http://jsfiddle.net/tEP6w/

Code:

var clearButton = document.getElementById("clear");
var previousActiveElement = null;

clearButton.onmousedown = function() {
    previousActiveElement = document.activeElement;
};

clearButton.onclick = function() {
    if (previousActiveElement && previousActiveElement != this) {
        previousActiveElement.value = "";
    }
};

A better approach would be to store a reference to document.activeElement as the button is about to receive the focus. However, this is a little tricky to achieve nicely in all browsers.

Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • The key here seems to be that the mousedown event occurs before blur, so you can record the active element at that time. Here is another SO question with info about the order of events: https://stackoverflow.com/questions/282245/what-is-the-event-precedence-in-javascript – Freerobots Jun 22 '18 at 16:29
7
var focused, inputs = document.getElementsByTagName('input');
for (var i=0, input; i<inputs.length && (input = inputs[i]); i++) {
    if (input.type === 'text') {
        input.addEventListener('focus', function(){
            focused = this;
        });
    }
}

Or in jQuery: var focused; $('input:text').focus(function(){focused = this;});

Then, when you want to clear the focused element, focused.value='';

MortezaE
  • 378
  • 3
  • 13
shesek
  • 4,584
  • 1
  • 28
  • 27
  • 1
    Oh, sorry, I'm used to 99% of JavaScript questions being jquery related. I'll update the answer, but it'll take me some time typing that from my mobile – shesek Sep 07 '11 at 05:25
2

As Genesis mentions, the clear button will have the focus when clicked. However, you may be able to work around this by having an onBlur event for your form that would store the id of the previously touched element in a variable or hidden form input.

JW8
  • 1,496
  • 5
  • 21
  • 36
0

Working on the ideas above, and if you're working with a form, you can define a hidden input and assign it a value of the last focused input's id:

<input type="hidden" id="focused_element" value="">

$('input:text, textarea').focus(function() {
    $('#focused_element').val($(this).attr('id'));
});

and then pick up the value at the appropriate later time:

var focused = $('#focused_element').val();
RickL
  • 3,318
  • 10
  • 38
  • 39
0

Building my answer on Tim Down's answer, using 'pointerdown' event will work even on touchscreens.

var toBeCleared;

const btnClear = document.querySelector('#btn-clear'); // your clear button

btnClear.addEventListener('pointerdown', function(event) {
  toBeCleared = document.activeElement;
});

btnClear.addEventListener('click', function(event) {
  toBeCleared.value = "";
});

Xavier Mukodi
  • 166
  • 1
  • 10
0

You can trigger an event when a clear button was clicked and save it in a state, after that you can consult the state and get the last focus and trigger focus on the element.

To do that you can use the auxiliary code:

let lastFocus;
let currentFocus = document.activeElement;

function setCurrentFocusAsLastFocus() {
  currentFocus = document.activeElement;
  lastFocus = currentFocus;
}

function backToLastFocus() {
  lastFocus.focus();
  document.getElementById(lastFocus.id).focus();
}
Istiyak Tailor
  • 1,570
  • 3
  • 14
  • 29
0

I don't know if this is a good place to put this or someone else already wrote this exact solution. But this is my take. And I only tested this in chrome.

I discovered that the "focusin" event bubbles on MDN (https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event), followed the trail to "focusout" and tested this code and it worked for me

This would work without having to select all elements and track them all at once or having to declare 2 variables for tracking the previous and current

(function trackActiveElement () {

    document.lastActiveElement = undefined;

    document.addEventListener("focusout",function( focusEvent ) {
        var target = focusEvent.target;
        document.lastActiveElement = target
    })
    
}())
Dharman
  • 30,962
  • 25
  • 85
  • 135
plpepin
  • 9
  • 2
  • Wow, works! (firefox). Self taught here let me see if I have this straight: Self executing function, given name trackActiveElement (which can help for debug?) Didn't declare a global var but it's basically lastActiveElement attached to document. – aamarks Jan 10 '22 at 09:53