fiddle is here: http://jsfiddle.net/44zAy/11/
Everything is working as I want however, if you click inside the first input and then go to click inside the second, the first one closes and same if you click the x button.
What I need is for it to stay open even if i click inside another and only close if I blur out of it and not by doing a focus on another input. is that possible?
CODE:
var inputWdith = '185px';
var inputWdithReturn = '68px';
jQuery('.resize-close').hide();
jQuery(".resize-input").on('focus', function() {
jQuery(this).animate({
width: inputWdith
},400);
jQuery(this).promise().done(function(){
jQuery(this).next('.resize-close').show();
});
}).bind('blur', function() {
jQuery(this).animate({
width: inputWdithReturn
},500);
jQuery(this).next('.resize-close').hide();
});
jQuery('.resize-close').click(function(){
jQuery(this).prev('.resize-input').animate({
width: inputWdithReturn
},500);;
});
For a quick fix of your current code, use the event.relatedTarget: http://jsfiddle.net/QKVL9/
The problem is that when you click into the second input, the 'blur' event is fired for the first input. So the quick fix is to check whether there is event.relatedTarget != null. If there is a relatedTarget, then stop execution of the 'blur' event for the first input.
But I recommend a complete refactor of this code :)
Related
I have small widget that has a list of links, which can open and close:
<div class="widget">
<input class="focuser">
View options
<ul>
<li>Option 1</li>
<li>Option 1</li>
</ul>
</div>
So, when I click on View options - list appears, and when click on any option - do stuff and close list of options.
And I need to have click-outside-close functionality - when user clicks anywhere outside just close the list.
I achieved this by focusing an invisible input when showing the options, and on blur of the input - hide the options after some timeout. This way:
when user clicks outside - the blur timeout runs out - hide the options.
if user clicks any option - clear the timeout, hide options & do
stuff.
And the problem now is that sometimes the timeout ends before the click. I increased the timeout interval to 200ms, but it's still not 100% sure, and also - this way user sees delay before the options list close.
Any idea how to fix and/or improve this?
EDIT:
This is simplified version of the JavaScript code:
CartSidebar.DwCustomSelect = Ember.View.extend({
blurTimeout: false,
focusOut: function(e) {
if (e.target.className == 'focuser') {
var self = this;
this.blurTimeout = setTimeout(function() {
clearTimeout(self.blurTimeout);
$(self.element).removeClass('opened'); // hide options ..
}, 180);
}
},
click: function(e) {
var clickedElement = e.target;
clearTimeout(this.blurTimeout);
if (clickedElement.tagName.toLowerCase() == 'li') {
$(this.element).removeClass('opened'); // hide options ..
doStuff();
}
}
}
EDIT 2:
I created a plunker, so you can see it in action:
https://plnkr.co/edit/boA6yC0sEbLAZU9tjyso?p=preview
(I did the timeout too small, so you see the problem. But even if you increase the interval - you'll see that the focusOut triggers before the click.)
If you want a functionality where you need to hide your div when user clicks anywhere except that div then you can add a click listener to whole document with the code to hide div.
var a = document.querySelector("a");
var ul = document.querySelector("ul");
a.addEventListener('click', function(e){
e.stopPropagation();
if(ul.classList.contains('show')){
ul.classList.remove('show');
ul.classList.add('hide');
}else{
ul.classList.remove('hide');
ul.classList.add('show');
}
});
document.addEventListener('click', function(){
ul.classList.remove('show');
ul.classList.add('hide');
});
For detail example check the jsbin below
http://jsbin.com/mamexev/edit?html,css,js,output
The timeout thing is one option. But you must define a large interval because it will depend on how fast the browser processes everything. It will work 99.99% of the times, but it's not bulletproof, as you said.
Other trick is to listen to the blur of the whole thing. If you assing a tabindex attribute to an element, it will receive focus events. If you set tabindex="0" it will get an automatic index and you won't have to worry about it.
So, instead of listening to the blur of the input, listen to the blur of the div .widget. When the focus goes from the input to the link or the lis, it will be still within the focus of widget and the blur event won't fire.
I've a simple select initialized with jQuery Chosen, created on a hidden div.
$(".slcFriendlist").chosen({
no_results_text: 'Geen resultaten voor',
width: 300
});
When I click somewhere in my code I show it and I would like to open the select, and mantain it opened
$('.pcPhotoFriend').on('click', function(event){
$('div.pcPostcardFriendlist').show();
$(".slcFriendlist").trigger('chosen:open');
});
But the problem is that there is another event that trigger I guess the click outside the select, or something else, and my select get closed again -I saw it opens, tested with delay in operations- but that's not what I need.
My goal is to have a select always opened.
Do you have any suggestions?
Thanks in advance
solved like that, with the adding of stopPropagation
$('.pcPhotoFriend').on('click', function(event){
event.stopPropagation();
$('div.pcPostcardFriendlist').show();
$(".slcFriendlist").trigger('chosen:open');
});
I am trying to restrict the user from clicking on a button multiple times. They can click on the button once when the page loads. If the page is reloaded the same should apply the user can click on the button only once.
I am using the following code however it doesn't seem to work for me
$("#doAccess").click(function() {
$("#doAccess").removeAttr('onclick');
DoSave();
});
Disable the button after it's been clicked
var accessBtn = $('#doAccess');
accessBtn.click(function() {
accessBtn[0].disabled = true;
DoSave();
});
Sounds like what you really need is:
$("#doAccess").one('click', DoSave);
jsFiddle example
.one() - Attach a handler to an event for the elements. The handler is executed at most once per element per event type.
Why not this?
$("#doAccess").once('click', function() {
DoSave();
});
You should probably also gray out or disable #doAccess, whatever it is.
I use the following code to add the selected div value into a input.
var lastFocus;
$('.num-button').click(function(e){
e.preventDefault();
e.stopPropagation();
//addOrRemoveWatermark(lastFocus);
$(lastFocus).val($(lastFocus).val() + $(this).children('span').html());
});
$('.del').click(function(e){
e.preventDefault();
e.stopPropagation();
//addOrRemoveWatermark(lastFocus);
$(lastFocus).val(function(index, text){
return text.replace(/(\s+)?.$/, '');
});
})
below is a sample image if the input panel I have! This is developed for a touch device and hence the key pad.
The script works fine to add value on each button press in the keypad. The problem I'm facing is for the room number I want to run an ajax call after the user has entered the amount. But since the focus is removed every button click, how can I run the script when the focus is changed to another input. I tried the jquery .focusout() method but it gets fired each and every time the user clicks on a number button.
if anyone can suggest me a work around that would be a great help!
thank you!
Perhaps you could delay the request with something like the following:
var roomNoChanged = false;
$('#room-number').change(function() {
roomNoChanged = true;
});
$('#table-number, #no-of-guests').focus(function() {
if(roomNoChanged) {
roomNoChanged = false;
$.post(...)
}
});
There are two elements in play:
$('#myInput') // an input field for search
$('#myList') // a list to display search results
I want to hide the list when the input no longer has focus, like so:
$('#myInput').blur(function() {
$('#myList').hide();
});
This works great, except when a list item is clicked, because the blur event fires and hides the list before the click is registered. The goal is for the list to stay visible when any part of the list is clicked, even though this will cause the input to blur.
How can I do this? Thanks!
You can accomplish this by keeping a global variable, and setTimouts, to wait a delay of 200ms and then check if one of the 2 elements have focus.
var keepFocus = false;
function hideList(){
if(!keepFocus){
$('#myList').hide();
}
}
$('#myInput').blur(function() {
keepFocus = false;
window.setTimeout(hideList, 200);
}).focus(function(){
keepFocus = true;
});
$('#myList').blur(function() {
keepFocus = false;
window.setTimeout(hideList, 200);
}).focus(function(){
keepFocus = true;
});
I've faced with the exact same problem, so this is how I solved it.
I came up with the fact that blur() fires earlier than click().
So I've tried to change click() to mousedown() and found out that mousedown() fires before blur().
And to imitate click() you'll have to fire mousedown() and then mouseup()
So in your case I would do something like this:
var click_in_process = false; // global
$('#myList').mousedown(function() {
click_in_process = true;
});
$('#myList').mouseup(function() {
click_in_process = false;
$('#myInput').focus();
// a code of $('#myList') clicking event
});
$('#myInput').blur(function() {
if(!click_in_process) {
$('#myList').hide();
// a code of what you want to happen after you really left $('#myInput')
}
});
Demo / example: http://jsfiddle.net/bbrh4/
Hope it helps!
You need to be able to say "do this blur() unless the list gains focus at the same time".
This question says how to detect if an element has focus: Using jQuery to test if an input has focus
Then all you need to do is:
$("#myInput").blur(function () {
if (!$("#myList").is(":focus")) {
$("#myList").hide();
}
});
Pigalev Pavel's answer above works great.
However, If you want an even simplier solution, you can just "prevent default" in the "mousedown" of an element to prevent the blur event from taking place. (since preventing default actually means that in the end, the input never looses focus in the first place!)
Of course, this is only if you're alright with preventing default in the div. It does have some side-effects, like the text is no longer selectable. As long as that's not an issue, this will work.
I suppose if you hold the mouse down over the div, move the mouse outside of the div, and then release the mouse, it also doesn't fire the "blur" event. But in my case, I wasn't too worried about that either, since the click started in the target div.
$("input").focus(function(){
$(this).val("");
});
$("input").blur(function(){
$(this).val("blur event fired!");
});
$("div").mousedown(function(e){
e.preventDefault();
})
div{
height: 200px;
width: 200px;
background: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input>
<div>
Click here to prevent blur event!
</div>
The best way to do this is to attach an event handler to the body element, then another handler to the list that stops event propagation:
$(body).click(function () {
$("#myList").hide();
});
$("#myList").click(function (e) {
e.stopImmediatePropagation();
});
This listens for a click outside of #myInput and hides #myList. At the same time, the second function listens for a click on #myList and if it occurs, it prevents the hide() from firing.