Date Picker
Note: I'll not recommend to use this date picker because a better alternative, datebox widget is available. Check here. This code can be used for reference and learning only.
I have created a simple date picker. Code has few parameters which can be changed as per the requirement.
First of all, you will have to make a GUI for date picker panel.
Below is the image for reference for creating the GUI, GUI can be created by going to the Script Editor:File>Build a User Interface menu.
While creating the Interface using GUI editor, make sure that you are giving the same ID to the elements as mentioned in the above image.
Element Hierarchy in User Interface:
Base Id 'Component', holds all the elements.
Absolute Panel Id 'outerPanel'
Month ListBox with Id 'monthListBox'
Year ListBox with Id 'yearListBox'
Label for Days (i.e SUN, MON, TUE, WED, THU, FRI, SAT), Id can be anything
Label for dates, there are 42 labels in the 7x6 matrix, Id starts from 'dl0', 'dl1', 'dl2', ....., upto 'dl41'. It is ordered in left to right and top to bottom fashion. (See the image for reference). You can write nay text on these labels. I have put 'xx' in above image.
You can adjust the color and size of the elements according to your choice.
Let us come to the code part now. In the below code, I have used the date picker with a text box having Id 'myDate'.
/////##########Code to load the form UserInterface#######//////////////
function doGet() {
var myApp = UiApp.createApplication();
var panel = myApp.createVerticalPanel();
var dateBox = myApp.createTextBox().setText('Click here').setId('myDate');
//Create handler to pickDate onclick
var handler = myApp.createServerClickHandler('pickDate');
//Add the click handler to the dateBox
dateBox.addClickHandler(handler);
panel.add(dateBox);
myApp.add(panel);
return myApp;
}
///////////////######Below is the code for Date Picker#######////////////////////////
numFutureYear = 6;//Change as per your requirement
numPastYear = 60;//Change as per your requirement
dateFormat = 'MMM dd, yyyy';//Change as per your requirement e.g MM/dd/yyyy or dd/MM/yyyy
monthArray = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
today = new Date();
function pickDate(p){
var app = UiApp.getActiveApplication();
Logger.log(p.parameter);
app.add(app.loadComponent("MyGui"));
app.getElementById('outerPanel').setStyleAttribute('top',p.parameter.y)
.setStyleAttribute('left',p.parameter.x).setStyleAttribute('z-index','1')
.setStyleAttribute('position','fixed');
var monthListBox = app.getElementById('monthListBox').setName('monthListBox').setStyleAttribute('font-size','8pt');
for (var i = 0; i< monthArray.length; i++) monthListBox.addItem(monthArray[i]);
monthListBox.setSelectedIndex(today.getMonth());
var yearListBox = app.getElementById('yearListBox').setName('yearListBox').setStyleAttribute('font-size','8pt');
var startYear = today.getYear() - numPastYear;
for (var i = 0; i<= numPastYear+numFutureYear; i++){
yearListBox.addItem(startYear.toString());
startYear++;}
yearListBox.setSelectedIndex(numPastYear);
//Add change Handlers on changing the month or year
var dateHandler = app.createServerChangeHandler('updatePicker');
dateHandler.addCallbackElement(app.getElementById('outerPanel'));
yearListBox.addChangeHandler(dateHandler);
monthListBox.addChangeHandler(dateHandler);
//load Current month dates in date picker when picker pops
var currentYear = today.getYear();
var currentMonth = today.getMonth();
var numDaysInCurrentMonth = 32 - new Date(currentYear, currentMonth, 32).getDate();
var day1ofcurrentMonth = new Date(currentYear, currentMonth, 1).getDay();
for(var i = 0; i < 42; i++){
var dlId = 'dl'+i;
if(i < day1ofcurrentMonth || i >= day1ofcurrentMonth+numDaysInCurrentMonth)
app.getElementById(dlId).setVisible(false);
else
app.getElementById(dlId).setText((i-day1ofcurrentMonth+1).toString()).setVisible(true);
}
//Add date select handler to set the date in the textbox
var dateSelectHandler = app.createServerClickHandler('selectDate');
dateSelectHandler.addCallbackElement(app.getElementById('outerPanel'));
for (var j = 0; j<42; j++){
var dlId = 'dl'+j;
app.getElementById(dlId).addClickHandler(dateSelectHandler);
}
return app;
}
//Function to update the date UI on change of month or year
function updatePicker(q){
var app =UiApp.getActiveApplication();
var selctedYear = q.parameter.yearListBox;
var selctedMonth = monthArray.indexOf(q.parameter.monthListBox);
var numDays = 32 - new Date(selctedYear, selctedMonth, 32).getDate();
var day1 = new Date(selctedYear, selctedMonth, 1).getDay();
for(var i = 0; i < 42; i++){
var dlId = 'dl'+i;
if(i < day1 || i >= day1+numDays)
app.getElementById(dlId).setVisible(false);
else
app.getElementById(dlId).setText((i-day1+1).toString()).setVisible(true);
}
return app;
}
//getDate on clicking the date label
function selectDate(e){
var app = UiApp.getActiveApplication();
var selectedDateId = e.parameter.source.split('l')[1];
var month = e.parameter.monthListBox;
var year = e.parameter.yearListBox;
var day1ofSelectedMonth = new Date(year, monthArray.indexOf(month), 1).getDay();
var dd = selectedDateId-day1ofSelectedMonth+2;
var date = new Date(year, monthArray.indexOf(month), dd);
var formattedDate = Utilities.formatDate(date, 'PDT', dateFormat);
app.getElementById('myDate').setText(formattedDate);//myDate is the Id of date Text box
app.getElementById('Component').setVisible(false);
return app;
}
Example Demo: You can try the demo by clicking on the textbox.
Modifying the date format:
You can modify the date format according to the below table
Known Issue:
Since apps script is executed on server side, it takes time to load the date picker panel after clicking on the text box.
Also,if you click more than once, date panel will popup as many times as many clicks, and only the latest date panel will work.
If you select the date from other date panels (except the latest one), it will give you error 'TypeError: Cannot call method "split" of undefined. Line 88'
Please suggest code modification to avoid this issue.