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:

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.