/**
* @author Bikas Vaibhav (http://bikasv.com) 2013
* Rewrote the plug-in at https://github.com/phonegap/phonegap-plugins/tree/master/Android/DatePicker
* It can now accept `min` and `max` dates for DatePicker.
*/
package com.plugin.datepicker;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import java.text.SimpleDateFormat;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.annotation.SuppressLint;
import android.app.DatePickerDialog;
import android.app.DatePickerDialog.OnDateSetListener;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.app.TimePickerDialog.OnTimeSetListener;
import android.content.Context;
import android.content.DialogInterface;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.DatePicker;
import android.widget.DatePicker.OnDateChangedListener;
import android.widget.TimePicker;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import android.os.Build;
@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
public class DatePickerPlugin extends CordovaPlugin {
private static final String ACTION_DATE = "date";
private static final String ACTION_TIME = "time";
private final String pluginName = "DatePickerPlugin";
@Override
public boolean execute(final String action, final JSONArray data, final CallbackContext callbackContext) {
Log.d(pluginName, "DatePicker called with options: " + data);
boolean result = false;
this.show(data, callbackContext);
result = true;
return result;
}
public synchronized void show(final JSONArray data, final CallbackContext callbackContext) {
final DatePickerPlugin datePickerPlugin = this;
final Context currentCtx = cordova.getActivity();
final Calendar c = Calendar.getInstance();
final Runnable runnable;
String action = "date";
long minDateLong = 0, maxDateLong = 0;
int month = -1, day = -1, year = -1, hour = -1, min = -1;
try {
JSONObject obj = data.getJSONObject(0);
action = obj.getString("mode");
String optionDate = obj.getString("date");
String[] datePart = optionDate.split("/");
month = Integer.parseInt(datePart[0]);
day = Integer.parseInt(datePart[1]);
year = Integer.parseInt(datePart[2]);
hour = Integer.parseInt(datePart[3]);
min = Integer.parseInt(datePart[4]);
minDateLong = obj.getLong("minDate");
maxDateLong = obj.getLong("maxDate");
} catch (JSONException e) {
e.printStackTrace();
}
// By default initalize these fields to 'now'
final int mYear = year == -1 ? c.get(Calendar.YEAR) : year;
final int mMonth = month == -1 ? c.get(Calendar.MONTH) : month - 1;
final int mDay = day == -1 ? c.get(Calendar.DAY_OF_MONTH) : day;
final int mHour = hour == -1 ? c.get(Calendar.HOUR_OF_DAY) : hour;
final int mMinutes = min == -1 ? c.get(Calendar.MINUTE) : min;
final long minDate = minDateLong;
final long maxDate = maxDateLong;
if (ACTION_TIME.equalsIgnoreCase(action)) {
runnable = new Runnable() {
@Override
public void run() {
final TimeSetListener timeSetListener = new TimeSetListener(datePickerPlugin, callbackContext);
final TimePickerDialog timeDialog = new TimePickerDialog(currentCtx, timeSetListener, mHour,
mMinutes, true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
timeDialog.setCancelable(true);
timeDialog.setCanceledOnTouchOutside(false);
timeDialog.setOnKeyListener(new Dialog.OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
//callbackContext.success("");
return false;
}
});
}
timeDialog.show();
}
};
} else if (ACTION_DATE.equalsIgnoreCase(action)) {
runnable = new Runnable() {
@Override
public void run() {
final DateSetListener dateSetListener = new DateSetListener(datePickerPlugin, callbackContext);
final DatePickerDialog dateDialog = new DatePickerDialog(currentCtx, dateSetListener, mYear,
mMonth, mDay);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
DatePicker dp = dateDialog.getDatePicker();
if(minDate > 0) {
dp.setMinDate(minDate);
}
if(maxDate > 0 && maxDate > minDate) {
dp.setMaxDate(maxDate);
}
dateDialog.setCancelable(true);
dateDialog.setCanceledOnTouchOutside(false);
dateDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
callbackContext.success("cancel");
}
});
dateDialog.setOnKeyListener(new Dialog.OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
//callbackContext.success("");
return false;
}
});
}
else {
java.lang.reflect.Field mDatePickerField = null;
try {
mDatePickerField = dateDialog.getClass().getDeclaredField("mDatePicker");
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mDatePickerField.setAccessible(true);
DatePicker pickerView = null;
try {
pickerView = (DatePicker) mDatePickerField.get(dateDialog);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
final Calendar startDate = Calendar.getInstance();
startDate.setTimeInMillis(minDate);
final Calendar endDate = Calendar.getInstance();
endDate.setTimeInMillis(maxDate);
final int minYear = startDate.get(Calendar.YEAR);
final int minMonth = startDate.get(Calendar.MONTH);
final int minDay = startDate.get(Calendar.DAY_OF_MONTH);
final int maxYear = endDate.get(Calendar.YEAR);
final int maxMonth = endDate.get(Calendar.MONTH);
final int maxDay = endDate.get(Calendar.DAY_OF_MONTH);
if(startDate !=null || endDate != null) {
pickerView.init(mYear, mMonth, mDay, new OnDateChangedListener() {
@Override
public void onDateChanged(DatePicker view, int year, int month, int day) {
if(maxDate > 0 && maxDate > minDate) {
if(year > maxYear || month > maxMonth && year == maxYear || day > maxDay && year == maxYear && month == maxMonth){
view.updateDate(maxYear, maxMonth, maxDay);
}
}
if(minDate > 0) {
if(year < minYear || month < minMonth && year == minYear || day < minDay && year == minYear && month == minMonth) {
view.updateDate(minYear, minMonth, minDay);
}
}
}
});
}
}
dateDialog.show();
}
};
} else {
Log.d(pluginName, "Unknown action. Only 'date' or 'time' are valid actions");
return;
}
cordova.getActivity().runOnUiThread(runnable);
}
private final class DateSetListener implements OnDateSetListener {
private final DatePickerPlugin datePickerPlugin;
private final CallbackContext callbackContext;
private DateSetListener(DatePickerPlugin datePickerPlugin, CallbackContext callbackContext) {
this.datePickerPlugin = datePickerPlugin;
this.callbackContext = callbackContext;
}
/**
* Return a string containing the date in the format YYYY/MM/DD
*/
@Override
public void onDateSet(final DatePicker view, final int year, final int monthOfYear, final int dayOfMonth) {
String returnDate = year + "/" + (monthOfYear + 1) + "/" + dayOfMonth;
callbackContext.success(returnDate);
}
}
private final class TimeSetListener implements OnTimeSetListener {
private final DatePickerPlugin datePickerPlugin;
private final CallbackContext callbackContext;
private TimeSetListener(DatePickerPlugin datePickerPlugin, CallbackContext callbackContext) {
this.datePickerPlugin = datePickerPlugin;
this.callbackContext = callbackContext;
}
/**
* Return the current date with the time modified as it was set in the
* time picker.
*/
@Override
public void onTimeSet(final TimePicker view, final int hourOfDay, final int minute) {
Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
calendar.set(Calendar.MINUTE, minute);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
String toReturn = sdf.format(calendar.getTime());
callbackContext.success(toReturn);
}
}
}