How to close DateTimePicker with a double click - javascript

I am using a jQuery DateTimePicker addon (By: Trent Richardson) and it will only close after you select the date AND the time. However some users don't care about the time and they want the Calendar to close after they choose the date only.
I managed to close the Calendar after picking the Date only but I need to implement a double click and not a single click. How do I do that?
Here is my code:
$(jqCompletedEndID).datetimepicker({
ampm: true,
onSelect: function(){
$(this).datepicker("hide"); $(this).blur();
}
});
I know there is a dblclick event in Javascript but not sure how to apply it in this context.
Thank you!

I have run into the exact same problem / requirement. I tried something very similar to Alex's solution, but it doesn't work because the datetimepicker seems to wipe all styles and event bindings when a day is selected (I assume it's being reconstructed, but haven't checked), making it impossible for the dblclick event to fire.
I've come up with a solution which isn't pretty but does work. You can use the datetimepicker's onSelect event to bind a couple of handlers as follows:
(assuming this._$input is a jQuery reference to the input control being used)
this._$input.datetimepicker({
...
onSelect: function() {
var self = this;
setTimeout(
function () {
$('.ui-datepicker-current-day').bind('click', function () { self._$input.datepicker('hide'); });
$('.ui-datepicker-current-day').bind('dblclick', function () { self._$input.datepicker('hide'); });
},
0
);
}
You're probably wondering why I bind both click and double click, particularly in light of my claim above that double click won't work. It seems that in Chrome, FireFox, Safari, and Opera the event will trigger the "click" event, but in IE it will trigger the "dblclick" event. Also, if you're wondering about the setTimeout, it's required because the popup won't be constructed until after the method is finished, so those selectors won't return anything if executed without it.
You've no doubt noticed that my solution will also close the picker when the currently-selected date is clicked whether or not it's part of a double-click. This is intentional in my case (and I also trigger the same logic in the beforeShow event to wire the handler so clicking on the currently-selected date will always close the picker). In your case, if you want it to work strictly with double clicks, all I can recommend is that you track the time between clicks and make sure they arrive within some threshold.

Try this...
$('#datepicker').datepicker({
//...
});
$('table.ui-datepicker-calendar a').bind('dblclick', function() {
$('#datepicker').val();
});

You can add a doubleclick event handler on the html tag itself. You would be having a emtpy div for the datepicker, so modify it as
<div id="datepicker" ondblclick="close()"></div>
In the close() function write the code to hide the datepicker div.

Related

Jquery event listeners not working on appended elements (and they should, shouldn't they?)

I'm using Jquery UI datepicker for my Rails application, and I want to trigger an event whenever someone clicks on the button for next month. It is not triggering anything though. My JQuery version is v1.12.4.
Here's a sample of my html code:
<input type='text' name='date_from' class="form-control date_picker" placeholder="Data de ida..." id='datetimepicker1' required/>
<div id="datepicker1" class="calendar"></div>
The HTML code for the datepicker is the default generated by JQuery UI.
So here is my javascript attempt:
$('body').on('click','.ui-datepicker-next',function(e){
console.log('Next/prev month')
e.preventDefault();
});
It does nothing! It doesn't raise an error on the console, it doesn't print anything and it doesn't attach the click event to the elements with the ui-datepicker-next class.
If I copy and paste the following code in the console it works well for the current elements in the document.
$('.ui-datepicker-next').click(function(e){
console.log('Next/prev month')
e.preventDefault();
});
It has never happened to me before, so I'm sorry if this question should be more detailed, but I really don't know what else I should mention here.
Edit:
jsfiddle: https://jsfiddle.net/9484zzrL/
This is the best I could do so far to recreate the issue on jsfiddle.
If you click on a day of the selected month it is fine, but if you change the month it doesn't work anymore.
Edit 2:
I believe this recreates perfectly my problem. Simply the event is not triggered when I choose any date in the calendar.
https://jsfiddle.net/awhwr3uv/
Edit:
So I looked at your latest jFiddle. I wondered if you had tried to use something like this:
$("#datepicker1").datepicker({
firstDay: 1,
onSelect: function(date) {
console.log('Date Selected: ' + date);
//Do some other cool stuff here
$(this).hide();
}
});
$("#datepicker2").datepicker({
firstDay: 1,
onSelect: function(date) {
console.log('Date Selected: ' + date);
//Do some other cool stuff here
$(this).hide();
}
});
You can carry out everything you need to in the onSelect option that is in your jFiddle and it even passes you the date to the callback as an argument.
Original
Change this:
$('body').on('click','.ui-datepicker-next',function(e){
console.log('Next/prev month')
e.preventDefault();
//setTimeout(date_picker_listener(),500)
});
To this:
$(document).on('click','.ui-datepicker-next',function(e){
console.log('Next/prev month')
e.preventDefault();
//setTimeout(date_picker_listener(),500)
});
It works in your fiddle.
Edit
I wanted to explain my guess at why your code didn't work.
I think it is because jQuery already has a click listener attached to the body element for the class of the button. Because 2 click listeners are attached to the body for the same class of element, the first one the JavaScript engine reaches is the one that fires.
In effect when you attach a click listener to the body using the on method the JavaScript engine is constantly scanning the body for clicks and then checking if the click matched your selector. Because jQuery already has the click listener on the body for that selector your listener never received the event.
With that in mind by attaching your click listener to the document, you have an entirely new listener set up and the engine is now also scanning the document for clicks and seeing it matches your selector. Because yours is the only one listening on the document yours gets the event.
So I tested this by changing the listener from click to mouseover and sure enough it works.
$('body').on('mouseover','.ui-datepicker-next',function(e){
console.log('Next/prev month')
e.preventDefault();
//setTimeout(date_picker_listener(),500)
});
I hope this helps. It's the best I can come up with as to why your code didn't work.

onChange event firing incorrectly after being loaded programmatically

I have an APEX application where there are many drop down items. I've bound change event handlers to them using the bind function of jQuery.
Now when I load the content of a drop-down programmatically using $('#ELEMENT').trigger('apexrefresh'), the drop-down reloads but the change event handler fires automatically.
How do I prevent this from happening? I tried avoiding binding the event handler using bind and instead adding the onChange attribute to the element. The incorrect behaviour was still present.
Here is the skeletal code:
$(document).ready(function()
{
$('#P7021_MSG_DEF').bind('change', function(e)
{
console.log('bound function onChange() msg_def');
updateStartWord();
}
);
});
function updateMsgDef()
{
console.log('function updateMsgDef() ');
$('#P7021_MSG_DEF').one('apexafterrefresh', function()
{
if( $x('P7021_RESTORE_CHK').value == 'Y')
{
setdefault('P7021_MSG_DEF', vJson.msg_def);
}
updateStartWord();
}
).trigger('apexrefresh');
}
In the above code, when the updateMsgDef is called from another function the function updateStartWord() gets called twice - once by updateMsgDef() itself and again by the onChange handler that was bound to P7021_MSG_DEF item.
If anyone could help on this?
Calling $('#ELEMENT').trigger('apexrefresh') is going to trigger the change event. Short of going back to the drawing board altogether, the solution is going to be a hack whatever you do. You could poke about in (and quite possibly break) Oracle's javascript. You could write your own AJAX to populate the select list.
The easiest way might be to check in your onChange event which element currently has focus, eg:
onChange = "if($( document.activeElement).attr('id')=='YOUR_PAGE_ELEMENT')
{ $( document.activeElement).trigger('apexrefresh'); };"
If the user has changed the select list, it should still have focus. There's no guarantee that will work in all browsers, but I think it should be ok in current Chrome and IE versions.
I've been in a similar situation to yours, and have come to accept that if the page logic is too complicated to implement using DAs, maintaining it is likely going to be a nightmare whatever happens. Much as I like "proper" programming, Apex is really all about the declarative controls.

Run anonymous function on current & future elements?

I want to be able to run an anonymous function on specified future elements once they become part of the DOM. I couldn't find an answer to this. I need a cross-browser event that bubbles, and only runs once when the element is created, or ready, or something along those lines.
Internet Explorer has the "activate" event which is just what I need, except it is only in IE. I tried using the DOMActivate event in Chrome, but it behaves strangely when I tested it on a text input box. It would only fire when the element is clicked on, and it fired twice in a row. It acted like a focus event that is triggered twice, which is not helpful.
Here is an example of what I am trying to accomplish:
$('body').on('activate', '.date-picker', function () {
$(this).datepicker({
dateFormat: 'mm/dd/yy'
});
});
$('body').on('DOMActivate', '.date-picker', function () {
$(this).datepicker({
dateFormat: 'mm/dd/yy'
});
});
I realize I can accomplish this with future elements using a callback after I place them on the DOM, or by triggering my own event, but I was looking for a cleaner solution.
EDIT:
I got it to work like this:
$('body').on('activate', '.date-picker', function (e) {
$(this).datepicker({
dateFormat: 'mm/dd/yy'
});
});
var activateSupported = 'onactivate' in document.documentElement;
if (!activateSupported) {
$(document).bind('DOMNodeInserted', function (e) {
var target = $(e.target);
target.trigger('activate');
target.find('*').trigger('activate');
});
}
This isn't really ideal as it has to make all those extra function calls in browsers other than IE. Anyone have better solutions?
Due to how this plugin works (it is not visible until you focus the input,) you can lazy-bind the plugin using event delegation.
$(document).on("focus", ".date-picker", function (e) {
e.preventDefault();
$(this).removeClass(".date-picker").datepicker({dateFormat: 'mm/dd/yy'}).focus();
});
The first time it is focused, it is initialized. After it is initialized, the focus event is re-triggered to cause the datepicker to open. By removing the .date-picker class, I prevent it from re-initializing the datepicker on subsequent focus events.

How to detect changes in primefaces calendar element?

I detect unsaved data within my form in order to warn the user if he leaves the page. This works so far for all elements, except for the primefaces calendar element.
Currently my approach relates to this answer. But this does not work for the calendar element. I found out that the change listener does not work for programmatically set values in general. Probably this is the reason for my problem. So I tried to implement my own very simple "change listener", by registering a click and blur listener to all my calendar elements. In the click listener I temporarily save the current value of the calendar element. In the blur listener I compare the saved value with the current value. But this approach doesn't work, because I'm not able to get the changed value of the calendar element within the blur listener. I tried to get the value in several ways:
$(this).val();
this.value;
$(this).html();
$(this).attr('value');
But in each case I get the old value. So I think the "simple change listener"-approach doesn't work as well.
My primefaces version is 3.4.2.
JSF implementation (probably not relevant) is: Mojarra 2.1.6
I don't know anything about primefaces but it uses the jquery ui calendar. So you could use the onSelect option of it to detect a change.
$('.hasDatepicker').each(function() {
var onSelect = $(this).datepicker('option', 'onSelect');
$(this).datepicker('option', 'onSelect', function() {
// some change happend here, set your flag that the form is dirty e.g.
setConfirmUnload(true);
// we call the original onSelect to not break the primefaces ajax change event
if(onSelect) { return onSelect.apply(this, arguments); }
});
});

Preventing jQuery timepicker addon from automatically opening

Does anyone know of a method to prevent the jQuery timepicker addon from automatically opening up when the textbox is focused? The documentation doesn't seem to provide a way and I'm currently looking at the source seeing if I can add the functionality but have I overlooked a simple way to accomplish this?
How about just initiate the datetimepicker upon the button clicked (as well as focus the input box), and destroy the object when the picker is closed?
$('#button').click(function() {
$('#timepicker').datetimepicker({
onClose: function(dateText, inst) {
$(this).datetimepicker('destroy');
}
}).focus();
});
Example: http://jsfiddle.net/william/NRH9r/
try to use a jquery function called unbind() to remove the onfocus event from the datetimepicker. You can then call an instance of the datetime picker when you fire a click event, or any other event you wish to fire. Another option would be to call the onfocus event that fires the datetimepicker, And pass in an event object into the callback function. Then call for example event.preventDefault(). This will prevent the onfocus() event from doing what it normally does.
As the timepicker is an addon to the jquery ui datepicker, you can use the showOn option to specify that a button is used to trigger it. See the datepicker example here.
Here's an example of how this can be used for the time picker:
$('input:text.timepicker').timepicker({
showOn: "button",
buttonImage: "/content/images/time_icon.png",
buttonImageOnly: true
});

Categories