Multiple datepicker using Pikaday - javascript

Im using Pikaday as a datepicker because JQuery Datepicker is having conflict with Prototype Library.
A few issues here.
How do i use pikaday datepicker in multiple text box
How to format the date. Previously by using JQuery Datepicker, to change the format I only need to
add dateFormat:"dd M yy",
Here is the sample code
<input type="text" id="datepicker">
<script src="pikaday.js"></script>
<script>
var picker = new Pikaday(
{
changeMonth: true,
changeYear: true,
field: document.getElementById('datepicker'),
firstDay: 1,
minDate: new Date('2000-01-01'),
maxDate: new Date('2020-12-31'),
yearRange: [2000,2020]
});
</script>

I guess you're looking for a way to have pikaday work together for a date range type of thing and then manipulate the last one according to the date you selected in the first on?
...
I realize this is a bit late but perhaps someone else is interested in an answer:
Pikaday does not offer anything inhouse here but I was able to work around this by destroying the instance and creating it again when a day has been picked in the "from" picker.
HTML:
From: <input type="text" name="from" id="from">
To: <span id="toField"><input type="text" name="to" id="to"></span>
Javascript:
function dateRange() { //destroy to field and init with new param
var picker = new Pikaday({ field: document.getElementById("from") });
if(picker.toString()) {
$("#to").pikaday('destroy');
$("#to").remove();
$("#toField").html('<input type="text" name="to" id="to">');
$("#to").pikaday({ //should have the same param as the original init
format: "YYYY-M-DD",
minDate: moment(picker.toString(), "YYYY-MM-DD").toDate()
});
}
}
$(function() { //pikaday init
$("#from").pikaday({
format: "YYYY-MM-DD", //adjust to your liking
minDate: moment().subtract({days: 1}).toDate()
});
$("#to").pikaday({
format: "YYYY-MM-DD",
minDate: moment().subtract({days: 1}).toDate()
});
});
PS: don't forget to include your jquery, pickaday and moment js files...
Hope it helps

In case this stumps anyone else - you need to actually trigger the code in #Dominik's answer once a date has been selected, using the "onSelect" trigger. My code has ended up like this (because I'm using the jquery plugin version throughout in a UK format):
var dateFormat = "DD/MM/YYYY";
function dateRange() { //destroy to field and init with new param
var $from = $("#from").pikaday({
format: dateFormat,
});
if($from.val()) {
$("#to").pikaday('destroy');
$("#to").remove();
$("#toField").html('<input type="text" name="to" id="to">');
$("#to").pikaday({
format: dateFormat,
minDate: moment($from.val(), dateFormat).toDate()
});
}
}
$("#from").pikaday({
format: dateFormat,
minDate: moment().subtract({days: 1}).toDate(),
onSelect: dateRange
});
$("#to").pikaday({
format: dateFormat,
minDate: moment().subtract({days: 1}).toDate()
});

I realize this is not quite an answer to the op question, but if it's preferable to select a date range using one control, this is the method I'm using:
var cal = document.getElementById('datepicker');
var picker = new Pikaday({
onSelect: (function() {
var init = true,
start,
end;
return function(date) {
if (init) {
start = date;
picker.setStartRange(date);
picker.setEndRange(null);
rangeClear();
} else {
end = date;
picker.setEndRange(date);
rangeSet(start, end);
}
picker.draw();
init = !init;
}
}())
});
cal.appendChild(picker.el);
Where the rangeSet and rangeClear functions would exist elsewhere with the following signatures:
function rangeSet(start, end) {
//do something with the start and end dates
}
function rangeClear() {
//clear the start and end dates
}
You can see this working here: http://codepen.io/cshanejennings/pen/OMWLLg

The following is my Javascript (without jQuery) solution for From and To datepickers using Pikaday. It's working in Chrome and Firefox, but it does not work in Chrome-Android.
var nowDT = new Date();
var nowDTStr = nowDT.toShortDate();
var sin = document.createElement('input');
sin.setAttribute('type', 'text');
sin.setAttribute('id', this.id + "_cp_sin");
sin.style.width = '20%';
sin.style.cssFloat = 'left';
this.controlPanel.appendChild(sin);
this.sinPika = new Pikaday({
field: sin,
firstDay: 1,
minDate: new Date('2001-01-01'),
maxDate: new Date(nowDTStr),
yearRange: [2001, nowDT.getFullYear()]
});
this.sinPika.setDate(nowDTStr);
var ein = document.createElement('input');
ein.setAttribute('type', 'text');
ein.setAttribute('id', this.id + "_cp_ein");
ein.style.width = '20%';
ein.style.cssFloat = 'right';
this.controlPanel.appendChild(ein);
this.einPika = new Pikaday({
field: ein,
firstDay: 1,
minDate: new Date('2001-01-01'),
maxDate: new Date(nowDTStr),
yearRange: [2001, nowDT.getFullYear()]
});
this.einPika.setDate(nowDTStr);
Since I have sinPika and einPika objects added as members to my class, they're accessible elsewhere in my class in other methods, where Pika objects are used to fetch the dates set by users. Only thing is that this solution is not working in Chrome-Android for me. Could anyone try and let me know what you find?
Thanks!
Edit
I found the problem why Pikaday wasn't working on chrome-android for me. The reason is that the pikaday.js (https://github.com/dbushell/Pikaday/blob/master/pikaday.js) is different from the one here http://dbushell.github.io/Pikaday/, in that the difference lies in attaching the mousedown, touchend events. Pikaday.js on github attaches like this:
addEvent(self.el, 'ontouchend' in document ? 'ontouchend' : 'mousedown', self._onMouseDown, true);
(I think, Javascript defines touchend not ontouchend, may be, this is the reason why Pikaday.js from github repo does not work.)
And the one on dbushell.github.io/Pikaday attaches like this:
addEvent(self.el, 'mousedown', self._onMouseDown, true);
Using the script from http://dbushell.github.io/Pikaday/ works on chrome-android, the one on git repo does not.

Related

JQuery-UI Datepicker() click Done programmitally

Does anybody know how I can trigger the datepicker to fire its onClose() function as if the user made the selection and clicked the Done button?
Maybe I'm looking in the wrong place but I cannot seem to find a way to fire an event that mimics the user selecting the datepicker and clicking on the Done button.
Here's my scenario: I want the date to change when users select an option button. If the user selects the option "YEAR" then #StartDate changes to Jan 2016 and #EndDate changes to Dec 2016. If the user selects the option "MONTH" then #StartDate changes to Jan 2017 and #EndDate changes to Jan 2017.
There are max and min and other requirements handled in the initModule for both datepickers that only get executed when the user selects the datepickers, changes these dates, and clicks on the Done button. I want to fire these events without the user having to manually change the dates.
In my initModule method:
// ----------------Begin Public Methods----------------------------//
var initModule = function () {
var currYear = new Date().getFullYear();
// Hookup datepickers
$(#EndDate).datepicker({
changeMonth: true,
changeYear: true,
showButtonPanel: true,
dateFormat: 'MM yy',
minDate: new Date(2013, 9, 1),
maxDate: '-1d',
beforeShow: function () {
setTimeout(function () {
$("#ui-datepicker-div").addClass('calendar-off');
}, 0);
},
onClose: function () {
var month = $(#ui-datepicker-div .ui-datepicker-month :selected").val();
var year = $(#ui-datepicker-div .ui-datepicker-year :selected").val();
$(this).datepicker('setDate' new Date(year, month, 1));
onChangeEndDate();
}
});
.
.
.
.
.
};
return { initModule: initModule };
So, I've tried $("#EndDate").click('onClose'); and $("#EndDate").trigger('onClose'); and I've poked around everywhere to find an answer to no avail.
How to I get execution into the onClose: function () without the user having to manually change the date in the datepicker and select the Done button?
According to the API documentation, the hide() method will close the datepicker.
So, if you want to close the datepicker, you should do
$(#EndDate).datepicker( "hide" );

Getting React state of input that has been selected from datepicker

Currently working on creating a react component for a form. I am applying a datepicker via a regular javascript file to my inputs which are being rendered in react (jsx).
I am trying to pull the state from the inputs when a date is selected from the datepicker. Unfortunately react is not picking up the value. I know it is probably something to do with calling the datepicker from a regular javascript file onto the rendered inputs. Thing is, when I am calling a regular .val on the input once I have selected a date, it gives me the value.
Also should mention, I am using bootstrap-datepicker
Any suggestions or recommendations would be greatly appreciated :)
form.js.jsx
var StepOne = React.createClass({
getInitialState: function() {
return {start: '', end: ''};
},
startDateChange: function(e) {
this.setState({start: e.target.value});
},
endDateChange: function(e) {
this.setState({end: e.target.value});
},
render: function() {
return (
<div className="stepOne">
<ul>
<li>
<label>Starts</label>
<input id="event-start" type="text" value={this.state.start} onChange={this.startDateChange} />
<label>Ends</label>
<input id="event-end" type="text" value={this.state.end} onChange={this.endDateChange} />
</li>
</ul>
</div>
);
},
}); // end of component
stepone_datepicker.js
$(function() {
var date = new Date();
date.setDate(date.getDate()-1);
$('#event-start, #event-end').each(function() {
$(this).datepicker({
autoclose: true,
minDate: new Date(),
startDate: date
});
});
});
The code in the stepone_datepicker.js file is probably executing before your React component has rendered into the DOM.
Using id to reference a DOM node inside a React component is very rarely a good idea and generally ends up as confusing spaghetti code.
React gives us a way to get hold of the DOM nodes with it's refs mechanism.
First, move the date picker code into a new method in your component.
makeDatePicker: function(element) {
var date = new Date();
date.setDate(date.getDate() - 1);
$(element).datepicker({
autoclose: true,
minDate: new Date(),
startDate: date
});
}
Now we can add the ref attribute to each input and use this new method as the callback.
<label>Starts</label>
<input ref={this.makeDatePicker} type="text" value={this.state.start} onChange={this.startDateChange} />
<label>Ends</label>
<input ref={this.makeDatePicker} type="text" value={this.state.end} onChange={this.endDateChange} />
When the element is ready, React will call makeDatePicker and pass the DOM node as the first argument.
After that, you can intercept the DOM node and apply the jQuery plugin.
This way you could even render multiple instances of the StepOne component and not have to worry about collisions between id attributes.
It's not the correct way to do it maybe better to use react-datepicker
But you can do this to trigger onChange event manually
$(function() {
var date = new Date();
date.setDate(date.getDate()-1);
$('#event-start, #event-end').each(function() {
$(this).datepicker({
autoclose: true,
minDate: new Date(),
startDate: date,
onSelect: function( selectedDate ) {
var event = new Event('input', { bubbles: true });
this.dispatchEvent(event);
}
});
});
});
and maybe better to use react-dom to get the DOM node anyway the code that i post with the minimum changes

jQuery datepicker not working on dynamically inserted html element

This same question has been asked repeatedly, and the only time it has been answered is the one where the fellow was trying to initialise datepicker in the .onReady() function. I am not doing that. In fact, I am actually doing what that solution is doing; implementing datepicker immediately after creating the element.
Here is my template code:
<input type=text name="txt_you_History_From_Date_XXX" id="txt_you_History_From_Date_XXX" class="month-picker inputField" size=16 maxlength=16>
You will notice the month-picker class. Also, you will notice the "XXX" placeholders.
Here is the code that inserts that template code:
//
// find the next available id
//
for (var i = 0; ; i++) {
if (!$("#divEmployer_" + i.toString()).length) {
break;
}
}
//
// get html, and replace the placeholders with id, then append.
//
$.get("content/contentHistoryEmployerTemplate.html", function (data) {
while (data.indexOf("XXX") >= 0) {
data = data.replace("XXX", i.toString());
}
$("#employerDIV").append(data);
});
//
// activate datepicker on all month-picker class elements
//
$('.month-picker').datepicker({
changeMonth: true,
changeYear: true,
showButtonPanel: true,
dateFormat: 'MM yy',
onClose: function (dateText, inst) {
$(this).datepicker('setDate', new Date(inst.selectedYear, inst.selectedMonth, 1));
}
});
//alert("here");
I do see the "here" alert if I uncomment it, so I know the code is being run.
The datepicker() throws no error.
I know the function is available because if I comment out my jquery-ui-min.js in my <HEAD>, a reference to datepicker() does then throw an error.
But the field does not respond when it receives focus. The datepicker does not appear.
Can anyone tell me what's wrong? Thanks!
You are trying to instantiate the datepicker before the element exists. Put that code inside the async callback.
$.get("content/contentHistoryEmployerTemplate.html", function (data) {
while (data.indexOf("XXX") >= 0) {
data = data.replace("XXX", i.toString());
}
$("#employerDIV").append(data);
// PUT DATEPICKER HERE
});

Setting Datepicker min/maxDates with $scope variables

The problem I am facing is that I have created a datepicker and I want to set its min date and max date based on the days I gather from a json.
The problem is that by the time the datepicker is initialised the $scope variables are null.
$scope.dates = [];
$scope.stats = {};
$scope.latestDay;
$scope.startDay;
$controller('rightsController', {
$scope : $scope
});
init();
$("#datepick").datepicker({
changeMonth: true,
changeYear: true,
buttonImageOnly: true,
dateFormat: 'dd/mm/yy',
minDate: ''+$scope.startDay,
maxDate: ''+$scope.latestDay
});
function init() {
fetchHourlyStats0();
}
$scope.fetchComparativeStats = function() {
fetchHourlyStats0();
}
function fetchHourlyStats0() {
var promiseStats = statsFactory.getHourlyStats();
$q.all([ promiseStats ]).then(function(values) {
$scope.stats = values[0].data;
i = 0;
for ( var k in $scope.stats) {
$scope.dates[i] = k;
var v = $scope.stats[k];
i++;
}
var length = $scope.dates.length-1;
$scope.latestDay = $scope.dates[0];
$scope.startDay = $scope.dates[length];
})
}
Is it possible to create the datepicker after the data access object is created and after I fill the variables?
First of all, I really suggest you to stop mixing Jquery and Angular. Have a look at this thread : "Thinking in AngularJS" if I have a jQuery background?
I think you will have it really difficult to get the value set by jquery into your picker.
But, this is not your issue right now.
function fetchHourlyStats0() {
var promiseStats = statsFactory.getHourlyStats();
$q.all([ promiseStats ]).then(function(values) {
// code removed
$scope.latestDay = $scope.dates[0];
$scope.startDay = $scope.dates[length];
$("#datepick").datepicker({
changeMonth: true,
changeYear: true,
buttonImageOnly: true,
dateFormat: 'dd/mm/yy',
minDate: ''+$scope.startDay,
maxDate: ''+$scope.latestDay
});
});
}
You can simply run your jquery code inside the .then() of your promise to defer the creation of your date picker.
Also, promiseStats looks like a single promise. You don't need to inject $q into your controller. Use directly your first promise :
statsFactory.getHourlyStats().then(function(values){
//
});
or
var promiseStats = statsFactory.getHourlyStats();
promiseStats.then(function(values){
//
});

How to get current viewMode property from "Bootstrap Datepicker"

How to get current viewMode property from "Bootstrap Datepicker"?
I initialize the control with viewMode= 'years' and I want to close datepicker on changeDate event, only when viewMode='days'.
The user selects a year, then a month, and finally a day. In that moment the control must be closed.
This is the code:
$("#date").datepicker(
{viewMode: 'years',
format: 'dd/mm/yyyy'
});
$('#date').on('changeDate', function (ev) {
//close when viewMode='0' (days)
})
Can anyone help?
Check this : http://jsfiddle.net/nAXnM/
HTML
<input type="text" class="span2" value="02/16/12" data-date-format="mm/dd/yy" id="dp2" >
JS
$("#dp2").datepicker({
viewMode: 'years',
format: 'dd/mm/yyyy'
});
$('#dp2').on('changeDate', function (ev) {
//close when viewMode='0' (days)
if(ev.viewMode === 'days'){
$('#dp2').datepicker('hide');
}
})
If you're using the forked version of Bootstrap Datepicker, to close the UI widget when a date is selected, set the autoclose option to true:
$("#date").datepicker({
autoclose: true
});

Categories