The simplest solution to hide calendar on blur or click - javascript

http://jsfiddle.net/SXrAb/
Following the jsfiddle link there is a simplified sample of what I need. Currently it shows the calendar on button click, and hides it on input blur.
What I cannot implement additionally is hiding calendar on button click.
So - calendar should:
open on button click if hidden (done)
hide on blur (done)
hide on button click if opened (this is what I'm in stuck with, because blur is triggered before button click event so I have no chance to handle it properly)
UPD:
the solution is expected to work correctly in all cases, like "mousedown on button, drag below, mouseup" (otherwise I wouldn't ask it ;-)

Try this:
var $calendar = $('#calendar');
var mousedown = false;
$('#calendar-input').blur(function() {
if (!mousedown)
$calendar.hide();
});
$('#calendar-button').mousedown(function() {
mousedown = true;
});
$('#calendar-button').mouseup(function() {
mousedown = false;
});
$('#calendar-button').click(function() {
if ($calendar.is(':visible')) {
$calendar.hide();
}
else {
$calendar.show();
$('#calendar-input').focus();
}
});
Demo here: http://jsfiddle.net/Tz73k/
UPDATE: OK, I moved the mouseup event to the document level. I don't think the mouse state can be tricked now by dragging the mouse before releasing it:
var $calendar = $('#calendar');
var mousedown = false;
$('#calendar-input').blur(function() {
if (!mousedown)
$calendar.hide();
});
$('#calendar-button').mousedown(function() {
mousedown = true;
});
$(document).mouseup(function() {
mousedown = false;
});
$('#calendar-button').click(function() {
if ($calendar.is(':visible')) {
$calendar.hide();
}
else {
$calendar.show();
$('#calendar-input').focus();
}
});
Updated fiddle: http://jsfiddle.net/yQ5CT/

It's helpful to think of the calendar and the button as a set, where you only hide the calendar when everything in the set has blurred. To do this you need a system where focus can be "handed off" between the calendar and button without triggering your hide function. To do this you'll need a focus and blur handler on both your calendar and your button, as well as a state variable for isFocused.
var isFocused;
jQuery('#calendar,#calendar-button,#calendar-input').blur(function(){
isFocused = false;
setTimeout(function() {
if (!isFocused) { hide(); }
}, 0);
});
jQuery('#calendar,#calendar-button,#calendar-input').focus(function(){
isFocused = true;
});
The setTimeout is because, when you click the button, focus is lost on calendar before it's gained on the button, so there's momentarily nothing in focus.
Edit
I guess there's actually three elements in the set, the button, the textbox, and the calendar. I updated the example. This also fixes the issue that, in your example, you can't click between the calendar and the textbox without the calendar hiding. Presumably the real calendar can be manipulated by clicking it.
Edit 2
For this to work you'll need to make your calendar focusable by giving it a tabindex.
<span id="calendar" tabindex="-1">I'm a calendar ;-)</span>

Hiya Demo here http://jsfiddle.net/SXrAb/50/ -- (non alert version) http://jsfiddle.net/SXrAb/51/
Thanks zerkms!
JQuery Code
var $calendar = $('#calendar');
$calendar.hide();
var isBlurEventInvoked = true;
var calendarShow = false;
$('#calendar-input').blur(function() {
alert(isBlurEventInvoked + " ==== " + calendarShow);
if (isBlurEventInvoked && calendarShow){
$calendar.hide();
isBlurEventInvoked = true;
}
});
$('#calendar-button').click(function() {
if (!$calendar.is(':visible') && isBlurEventInvoked){
$calendar.show();
$('#calendar-input').focus();
calendarShow = true;
isBlurEventInvoked = true;
}else if ($calendar.is(':visible')) {
$calendar.hide();
isBlurEventInvoked = false;
calendarShow = false;
}
});
​

Related

How to avoid triggering false function between change and click

I have an input and a clear button. If the user type something in the input field and blur it, change() will be trigger and do something. But if I want to click clear button and trigger click(), change() will still be triggered. How do I solve this?
I tried this, but it doesn't work. var clear will never be true.
$("#inputid").change(function() {
var clear = false;
$("#clearbtn").click(function() {
// if clear button is clicked, do something
clear = true;
});
if (clear) {
return;
}
// if clear button is not clicked, do something else
...
this is quite tricky
the problem is onchange event is called before the clear button click event is called
to overcome this you can introduce a timer in the onchange event so that it waits for user's immediate action
like this:
$(document).ready(function(){
var clear = false;
var isTimerOn = false;
function HandleChange(){
if(clear){
// if clear button is clicked, do something
$("#inputid").val("");
}else{
// if clear button is not clicked, do something else
alert("do something else");
}
clear = false;
isTimerOn = false;
}
$("#inputid").change(function() {
isTimerOn = true;
setTimeout(HandleChange, 80);
});
$("#clearbtn").click(function() {
clear = true;
if(!isTimerOn){
HandleChange();
}
});
});
here's fiddle: https://jsfiddle.net/6d9r1qsc/
You should move the click event outside of the change event.
$("#clearbtn").click(function() {
// if clear button is clicked, do something
$("#inputid").val("");
});

JQuery focus and click running on same time on element

I have a button which has 2 different behaviors
While navigating with keyboard with tab key, when the button gets blur is should move focus to button 1
When we hit enter key, then it should move focus to button 2
Case 1 is working fine, but when we hit enter key the focus moves to Button 2 and then moving to button 1, Here I found blur also calling when we hit the enter button so it calling the concern function, is there any way to achieve my goal?
$('#btn').on('focus', function(){
}).on('blur', function(){
setTimeout(function() {
$('.span-hlo')[0].focus();
},250);
});
$('#btn').on('click', function(){
setTimeout(function() {
$('.span-welcome')[0].focus();
},250);
});
Fiddle example
Update your jquery Like this
var lastClick = null;
$('#btn').mousedown(function(e) {
lastClick = e.target;
}).focus(function(e){
if (e.target == lastClick) {
$('.span-welcome')[0].focus();
} else {
$('.span-hlo')[0].focus();
}
lastClick = null;
});

Correct way to prevent triggering `click` if inner element is not hovered when mouse is released

I need to prevent hiding of a modal dialog when user clicks on the dialog, then moves the mouse outside of the dialog, and releases it. The dialog is placed inside outer div on which the click event is registered. Here is the example of the modal dialog and its setup.
So I've done the following:
var pointerDownElement = null;
$('.d1').on('mousedown', function(event) {
// this is how I do it to prevent triggering of click event
pointerDownElement = event.target;
// this is how a browser does it
pointerDownElement = event.currentTarget;
});
$('.d1').on('mouseup', function(event) {
var element = event.target;
if (element === pointerDownElement) {
console.log('triggering click');
}
});
Is this approach correct?
You're definitely on the right track. Slightly modified code:
var pointerDownElement = null;
$('.d1').on('mousedown', function(event) {
event.preventDefault();
pointerDownElement = event.currentTarget;
return false;
});
$('.d1').on('mouseup', function(event) {
if (event.target=== pointerDownElement) {
console.log('triggering click');
}
});
No need to assign a value to a variable if you're only going to use it once. Also, event.preventDefault(); and return false; will guarantee the default behavior of the event doesn't take place (not that there typically is one for mousedown, but I'm assuming you have a reason for including this code).

How do I call live event with blur together

I have some question with these events.
My code is something like this:
dialogX.find('#inputExample').blur(function() {
var button = $(this).parent().find('#buttonExample');
if(!(button.is(':clicked'))) //this doesn't work, just test
button.hide();
});
dialogX.find('#buttonExample').live('click', function() {
alert('Test!');
$(this).hide();
});
The question is, when I'm on input (#inputExample) and later click on button (#buttonExample), blur is called and live event is never called.
***I have to use live instead of on, because JQuery version.
Someone could help me?
dialogX.find('#inputExample').blur(function() {
var button = $(this).parent().find('#buttonExample');
if(disableBlur)
button.hide();
});
var disableBlur = false;
dialogX.live('mousedown', function(e) {
if($(e.target).prop('id')=='buttonExample')
disableBlur = true;
else
disableBlur = false;
});

Notify user on browser close only

I am trying to implement notifying when the user closes or reloades the page.Crrently i am using the following code
function unloadPage(){
return "Your changes will not be saved.";
}
window.onbeforeclose = unloadPage;
This works fine.But the problem is this happens whenever a navigation takes place.That is either a page refresh or a form submission or a hyperlink click or whatever navigation takes place..I just want to work this code only for browser refreshing and closing.I knew about setting a flag and checking it.
But i have to integrate this in a big application.So it will be difficult to add the code in every page.So is there an easy way.
Is there a way to catch the refresh or browser cosing so that can use it.
Note that in your code, you're using onbeforeclose, but the event name is beforeunload, so property is onbeforeunload, not onbeforeclose.
I just want to work this code only for browser refreshing and closing. Is there a way to catch the refresh or browser cosing so that can use it.
No. Instead, you'll have to capture each link and form submission and either set a flag telling your onbeforeunload handler not to return a string, or removing your onbeforeunload handler (probably the flag is cleaner).
For example:
var warnBeforeClose = true;
function unloadPage(){
if (warnBeforeClose) {
return "Your changes will not be saved.";
}
}
window.onbeforeunload = unloadPage;
// ...when the elements exist:
$("a").click(dontWarn);
$("form").submit(dontWarn);
function dontWarn() {
// Don't warn
warnBeforeClose = false;
// ...but if we're still on the page a second later, set the flag again
setTimeout(function() {
warnBeforeClose = true;
}, 1000);
}
Or without setTimeout (but still with a timeout):
var warningSuppressionTime = 0;
function unloadPage(){
if (+new Date() - warningSuppressionTime > 1000) { // More than a second
return "Your changes will not be saved.";
}
}
window.onbeforeunload = unloadPage;
// ...when the elements exist:
$("a").click(dontWarn);
$("form").submit(dontWarn);
function dontWarn() {
// Don't warn for the next second
warningSuppressionTime = +new Date();
}
Update in 2017: Also note that as of at least a couple of years ago, browsers don't show the message you return; they just use the fact you returned something other than null as a flag to show their own, built-in message instead.
One of the simple solutions to your problem is to have a flag and then call your function only if the flag is valid. In this case , you can bind the anchor tags, F5 key and form submit button click to events that set the flag as false. So your alert bar will be visible only if the above cases don't happen :)
Here's the script:
var validNavigation = false;
function endSession() {
// Browser or broswer tab is closed
alert("bye");
}
function wireUpEvents() {
window.onbeforeunload = function() {
if (!validNavigation) {
endSession();
}
}
// Attach the event keypress to exclude the F5 refresh
$(document).bind('keypress', function(e) {
if (e.keyCode == 116){
validNavigation = true;
}
});
// Attach the event click for all links in the page
$("a").bind("click", function() {
validNavigation = true;
});
// Attach the event submit for all forms in the page
$("form").bind("submit", function() {
validNavigation = true;
});
// Attach the event click for all inputs in the page
$("input[type=submit]").bind("click", function() {
validNavigation = true;
});
}
// Wire up the events as soon as the DOM tree is ready
$(document).ready(function() {
wireUpEvents();
});
Check this link
It gives you information on how to handle onbeforeunload event.
The idea is to have a global flag on the page. When any change is done to the fields, this flag is set to true. When clicked on save button, then this flag needs to be set to false.
In the onbeforeunload event, check whether the flag is true, then show the message accordingly.
var needToConfirm = true;
window.onbeforeunload = confirmExit;
function confirmExit()
{
if (needToConfirm)
{
// check on the elements whether any change has been done on the fields.
// If any change has been done, then set message here.
}
}
function saveClicked()
{
needToConfirm = false;
}
DEMO
(Run or refresh the fiddle to see the alert onbeforeunload() event message and click on the link "kk" ,it wont show onbeforeunload() event message. Try it in your webpage)
I have a solution for you, you don have to add onclick event to each tags and all.
Just add this to any where on your pages .
<input type="hidden" value="true" id="chk"/>
and add this code to your document head tag
<script>
window.onbeforeunload = confirmExit;
function confirmExit()
{
if(document.getElementById("chk").value=="true")
{
return "Your changes will not be saved.";
}
}
document.onclick = myClickHandler;
function myClickHandler() {
document.getElementById("chk").value="false";
}
<script>
Hope this helps
Thank you

Categories

Resources