Hello,
This is an old issue that I first wrote about seven years ago(!):
http://sourceforge.net/tracker/index. ... roup_id=41586&atid=430842The bottom line is, date boxes right now are always initialized with a date. If no date is given when the box is created, then it defaults to today's date. This is a big problem because when you are parsing what the user submits in a form, you have no way of knowing if the user really picked today's date, or whether they just left the date box alone.
To solve this problem, you need to provide a non-date, non-blank default value, so you can then test for that value when you are processing the user's submission. Then you can know for sure if the user left the box alone, or if they intentionally blanked the date, or intentionally chose today's date (or any other date).
I have made some changes to four files in Impress 1.3 to allow for this. I think the changes are minimally invasive. They do not interfere with existing functionality, they just change the way the boxes are rendered, so that if you initialize the box with no date, ie: "", then a non-date default value is used, instead of the current date. When the user clicks on the calendar, it still defaults to the current date.
The four changes are:
1. class/xoopsform/formtextdateselect.php
It looks like there's a bug in this file actually. Rather than just passing everything that it gets up to the new icms class, it is altering the date value, even though the icms class will do exactly the same thing. So I suggest commenting/removing one line:
//$value = !is_numeric($value) ? time() : (int) ($value);
parent::__construct($caption, $name, $size, $value);
2. language/english/global.php
There's two new constants that I suggest adding to this configuration file, where other locale-specific values are kept:
define("_DATE_DEFAULT", "YYYY-mm-dd");
define("_CAL_MONDAYFIRST", "false");
The first is the value that is shown to users in a date box that is initialized with no date. The second is a flag that tells the calendar whether to start weeks on Monday or not (I couldn't find any configuration option in the gui or code to control this elsewhere).
3. libraries/icms/form/elements/Date.php
This is where the bulk of the changes go, but as I said, they don't hinder any existing functionality:
public function __construct($caption, $name, $size = 15, $value= 0) {
if($value === "") {
$value = _DATE_DEFAULT;
} elseif(!is_numeric($value)) {
$value = time();
} else {
$value = intval($value);
}
parent::__construct($caption, $name, $size, 25, $value);
}
/**
* Render the Date field
*/
public function render() {
global $icmsConfigPersona;
$ele_name = $this->getName();
if($icmsConfigPersona['use_jsjalali']) {
include_once ICMS_ROOT_PATH . '/include/jalali.php';
}
if($this->getValue(false) !== _DATE_DEFAULT) {
$ele_value = date(_SHORTDATESTRING, $this->getValue(false));
$jstime = formatTimestamp($this->getValue(false), _SHORTDATESTRING);
if(_CALENDAR_TYPE=='jalali') {
$jalali_ele_value = icms_conv_nr2local(jdate(_SHORTDATESTRING, $ele_value));
} else {
$jalali_ele_value = $ele_value;
}
} else {
$ele_value = $this->getValue(false);
$jstime = formatTimestamp(time(), _SHORTDATESTRING);
$jalali_ele_value = $ele_value;
}
include_once ICMS_ROOT_PATH . '/include/calendar' . ($icmsConfigPersona['use_jsjalali'] == true ? 'jalali' : '') . 'js.php';
$result = "<input type='text' name='".$ele_name."' id='".$ele_name."' size='".$this->getSize()."' maxlength='".$this->getMaxlength()."' value='".$ele_value."'".$this->getExtra()." /> <img src='" . ICMS_URL . "/images/calendar.png' alt='"._CALENDAR."' title='"._CALENDAR."' id='btn_".$ele_name."' onclick='return showCalendar("".$ele_name."");'>";
if ($icmsConfigPersona['use_jsjalali']) {
$result = "<input id='tmp_".$ele_name."' readonly='readonly' size='".$this->getSize()."' maxlength='".$this->getMaxlength()."' value='".$jalali_ele_value."' /><input type='hidden' name='".$ele_name."' id='".$ele_name."' value='".$ele_value."' ".$this->getExtra()." /> <img src='" . ICMS_URL . "/images/calendar.png' alt='"._CALENDAR."' title='"._CALENDAR."' id='btn_".$ele_name."'><script type='text/javascript'>
Calendar.setup({
inputField : 'tmp_".$ele_name."',
ifFormat : '%Y-%m-%d',
button : 'btn_".$ele_name."',
langNumbers : true,
dateType : '"._CALENDAR_TYPE."',
onUpdate : function(cal){document.getElementById('".$ele_name."').value = cal.date.print('%Y-%m-%d');}
});
</script>";
}
return $result;
}
So basically...check if the date is "" or not, and if so, initialize with the _DATE_DEFAULT constant. Otherwise, do the normal thing we're doing now.
When rendering the box, check if the value is the _DATE_DEFAULT text or not, and if it is, then set things up to draw the box on screen with that text in it, and with the initialization date for the calendar set to today's date. If the value is a real date, do exactly what we're doing now.
There's some extra conditions and stuff in there to account for the slightly different way the jalali calendar does things, but basically that's it. If you do a diff of this against the 1.3 code, you'll see all the little differences.
4. include/calendarjs.php
There are a couple changes here, to make the calendar respect the Monday First flag, and to avoid trying to parse a non-date value as if it were a date. Here's the original code:
function showCalendar(id) {
var el = xoopsGetElementById(id);
if (calendar != null) {
calendar.hide();
} else {
var cal = new Calendar(true, "' . $time . '", selected, closeHandler);
calendar = cal;
cal.setRange(2000, 2015);
calendar.create();
}
calendar.sel = el;
calendar.parseDate(el.value);
calendar.showAtElement(el);
Calendar.addEvent(document, "mousedown", checkCalendar);
return false;
}
And the same block with the necessary changes:
function showCalendar(id) {
var el = xoopsGetElementById(id);
if (calendar != null) {
calendar.hide();
} else {
var cal = new Calendar('._CAL_MONDAYFIRST.', "' . $time . '", selected, closeHandler); // THIS LINE CHANGED
calendar = cal;
cal.setRange(2000, 2015);
calendar.create();
}
calendar.sel = el;
if (el.value != "" && el.value != "'._DATE_DEFAULT.'") { // calendar.parseDate(el.value) is now inside a condition
calendar.parseDate(el.value);
} else {
calendar.parseDate("'.$time.'");
}
calendar.showAtElement(el);
Calendar.addEvent(document, "mousedown", checkCalendar);
return false;
}
That's it. I think this would be a great addition to Impress, addressing a very long standing issue. And there should be no effect on existing modules at all, this simply introduces the possibility of being precise about what the user meant by the value they submit in a datebox.
As a complement to this, it may be worth supporting an additional value in the initialization of date box elements: {TODAY} or something like that, which can be used if you truly want the current date to be the default value. Supporting {TODAY+7} and other notations like that would be pretty trivial too.
--Julian