Hide an html element when it loses focus using JavaScript - javascript

I've made a datepicker for a custom form and I want to hide it when the input lost the focus and the next focused element is not the datepicker (when you focus another input for example). The problem is that the blur event on the input happens before focus on the datepicker. This is the regular behaviour of the JS events. But I want to close the datepicker only if the input loses the focus and the datepicker is not focused then. Is there any way to achieve this without blocking the user interface using setTimeout() or something similar?
I'm not asking for a code solution, just the process to follow or any alternative. Thanks.
This is a screenshot of the datepicker and the input:
And this is the html code just to give an idea on what's going on (It has Angular bindings and template references mixed):
<div class="col-lg-2 form-group">
<label for="date">Fecha</label>
<input type="text"
class="form-control datepicker-input"
id="date"
placeholder="Fecha"
readonly="true"
formControlName="date"
#datepickerInput>
<app-datepicker [datepickerInput]="datepickerInput"
(pickDate)="onPickDate($event)"></app-datepicker>
</div>

I would treat the date picker as a popup:
Add a full screen transparent overlay behind the calendar
When the user clicks that overlay (not on the calendar itself that is), close the calendar
While the calendar is open, respond to specific key events like [Esc] to close the calendar
Hope that helps

I'm not real sure to understand your need... Since what you wish to do sounds like the normal behavior of bootstrap's datepicker. But you mentioned a custom form... So I don't know.
Now the issue is about a delay between blur the input and focus the datepicker dropdown.
Here, I would talk about mouseup on the dropdown, since focus is more about inputs than divs. And it doesn't work using click, since that event is used by datepicker and there must be a return false somewhere because it just doesn't fire on a datepicker dropdown. Anyway... Your setTimeout idea is something simple to achieve.
The trick:
Set a timeout on input blur to hide the dropdown.
On mouseup on the dropdown, clear that timeout.
Normally, if the user is focussing the input and clicks on the opened dropdown, the delay in between is around 100ms. Using that value results in fail once on 3~4 times. So let's use 150ms.
Here is the code:
$("#date").datepicker();
var dp_timeout;
$(".datepicker-input").on("blur",function(){
dp_timeout = setTimeout(function(){
$(".datepicker").hide();
console.log("Timeout executed");
},150);
});
$(document).on("mouseup",".datepicker-dropdown",function(){
clearTimeout(dp_timeout);
console.log("Timeout canceled");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.7.1/js/bootstrap-datepicker.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.7.1/css/bootstrap-datepicker.css" rel="stylesheet"/>
<div class="col-lg-2 form-group">
<label for="date">Fecha</label>
<input type="text"
class="form-control datepicker-input"
id="date"
placeholder="Fecha"
readonly="true"
formControlName="date"
#datepickerInput>
<app-datepicker [datepickerInput]="datepickerInput"
(pickDate)="onPickDate($event)"></app-datepicker>
</div>

Related

Select new input to fire flatpickr

I have a date picker that when I choose a new date I wish to fire another date picker on another input
Input one:
<input name="pDate" type="text" class="form-control date-with-time-inputs" onchange="changeDate()" id="p_date" placeholder="" value="{{$times['now']}}">
Then I have onchange event
<script>
function changeDate() {
const input = document.getElementById('d_date');
input.select();
console.log('clicked');
}
</script>
And then the second input as so
<input name="dDate" type="date" class="form-control date-with-time-inputs" id="d_date" placeholder="" value="{{$times['tomorrow']}}">
The console log fires and the function is working but the 2nd input is not firing up.
You can't open/click() it from JS(only focus() but that would not help you):
The HTML5 <input> with type='date' will only work with a few browsers.
Also, as a programmer you have no control over its appearance or any
other aspect (such as showing and hiding it) (Quick FAQs on input type date)
Thus, if you must do this, the HTML5 <input type='date'> tag is not an
option. You'll have to use something build in JavaScript such as
jQuery UI or Bootstrap date picker.
Found here: https://stackoverflow.com/a/18327043/12753766

How to add event listener to div without tabindex=0?

I have something like this control:
I need to track focus on any element inside this control. If I focus input or If I focus (click) calendar icon, I want to know that focus performed.
My idea is to add click listener on wrapper of input + calendar trigger. It is some div.
Out of the box I can't add focus listener to the div. To achieve this I need to add tabindex=0 to this div. This method will work, but it has one minus.
For example, I have form with many controls. Example code is below:
<div class="container">
<input onfocus="onFocus()" />
<div tabindex="0" onfocus="onFocus()">some div</div>
<div tabindex="0" onfocus="onFocus(event.target)">
<input onfocus="onFocus()" />
</div>
<input onfocus="onFocus()" />
</div>
When I focus first input and start looping through TAB key I want this behavior: focus calendar icon, focus next input, focus next calendar icon etc. But with tabindex=0 I break this behaviour. You can check it in this pen. You can see this broken behaviour after some div block.
Well, I have another option to add listener specifically for input and calendar icon (or any other icon). The problem is I have dynamic amount of icons on each field. And I have to add focus listener for each. Much simpler for me (and another developers) is the way when I have only one focus listener on the top (as I think).
Is it somehow possible to add ability to add focus listener to the div without breaking focus loop (like I shown on the codepen example).
Use element.addEventListener('focusin', handler). focus and blur don't bubble, focusin and focusout do.
document.querySelector('.container')
.addEventListener('focusin', function(event) {
console.log(event.target)
})
<div class="container">
<input name="a" />
<div contenteditable="true">some div</div>
<div>
<input name="b" />
</div>
<input name="c"/>
</div>

JS focusout and click autosuggestions on a search input field

I built a search-box where I have suggestions displayed as user types in.
<div id="search-box">
<input val="" type="text" id="s" >
<div id="suggest-box">
<div class="suggestions">word1</div>
<div class="suggestions">word2</div>
<div class="suggestions">word3</div>
</div>
</div>
I did add for mobile this code so when the user tap "done" on the mobile keyboard the suggestions box closes up and ti doesn't allow me to click on the suggestions
document.addEventListener('focusout', function(e) {
$("#suggest-box").hide();
});
the problem is that the user can't click on the suggestions though...
how to fix it?
Not sure what the question is..
You can't click the suggestions? They're DIV's and are by default not clickable, unless you add an event listener on it, like so:
suggestionElement.addEventListener('click', function()
{
input.value = 'suggestion';
});
Here's a basic working suggestion box:
https://jsfiddle.net/76p4z033/1/

Datepicker some problems with opening

I use in my web app datepicker jquery but it I have some problem:
I have two tabs in one of them I have two menu, were I use datepicker in each other of menu.
And second tab has one menu and there I also use datepicker.
When I load my web page, and try to set some date with datepicker it is work (datepicker was opened). But after that I go to the second menu in this tab or another tab and try to set some date in my input date, but datepicker not opens. I also use ajax in this page.
Whats wrong? thx!
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<input type="text" name="dateTime" id="dateTime" placeholder="yyyy-mm-dd" required />
<script>
$(function() {
$("#dateTime").datepicker({ dateFormat: "yy-mm-dd" , changeMonth: true });
});
</script>
The problem is the selector
$("#dateTime")
ID in a page is supposed to be unique
Use classes instead.
Because you are using a ID selector it tried to find the first instance of the element. Once it finds it, stops searching again. So it will never be applied to the element in the other tab..
Change
<input type="text" name="dateTime" id="dateTime"
to
<input type="text" name="dateTime" class="dateTime"
And then change the selector to
$(".dateTime")

javascript class not working when written to div using getElementById

I have been using a datepicker js class known as tcal. After you link to the class on your server, you can call it with one line of code.
in header
<link rel="stylesheet" type="text/css" href="tcal.css" />
<script type="text/javascript" src="tcal.js"></script>
html
Pick date: <input type="text" size=8 name="eventdate" class="tcal" value=>
It has been working fine.
However, to streamline a page, I am now trying to take it out of the html and display it in a div only when a user clicks on it using getElementById. while I can display the input box ok, when written to the browser this way, the class no longer seems to work.
js
function pickDate() {
document.getElementById('show').innerHTML = 'Pick date: <input type="text" size=8 name="eventdate" class="tcal" value=>';
}
html
Pick Date<div id="show"></div>
When user clicks, input box appears. However, datepicker calendar does not pop up when you click in tox. Does anyone know why tcal is not working when written to browser this way?
Thanks for any suggestions.
the reason for this happening is that you are adding input box in the dom later your datepicker code is initialized just reinitialize datepicker code
as i see your library may don't have a code to initialize is seperately you can do hide and show instead of adding into the dom later, if the text box will be available in the starting of page ready it will be initialized so use the following code
html -
<div id="something" style="display:none;">Pick date: <input type="text" size=8 name="eventdate" class="tcal" value=></div>
js -
document.getElementById('something').style.display="block";

Categories

Resources