diff --git a/admin/inc/class.customfields.inc.php b/admin/inc/class.customfields.inc.php index e7181fc228..c36211e36e 100644 --- a/admin/inc/class.customfields.inc.php +++ b/admin/inc/class.customfields.inc.php @@ -82,8 +82,8 @@ class customfields 'float' => array('cf_len' => true), 'label' => array('cf_values' => true), 'select' => array('cf_len' => false, 'cf_rows' => true, 'cf_values' => true), - 'date' => array('cf_len' => true, 'cf_rows' => false), - 'date-time' => array('cf_len' => true, 'cf_rows' => false), + 'date' => array('cf_len' => true, 'cf_rows' => false, 'cf_values' => true), + 'date-time' => array('cf_len' => true, 'cf_rows' => false, 'cf_values' => true), 'select-account' => array('cf_len' => false, 'cf_rows' => true), 'htmlarea' => array('cf_len' => true, 'cf_rows' => true), 'button' => array('cf_values' => true), @@ -328,7 +328,7 @@ class customfields { list($var,$value) = explode('=',trim($line),2); $var = trim($var); - $values[$var] = empty($value) ? $var : $value; + $values[$var] = trim($value)==='' ? $var : $value; } } $content['cf_values'] = $values; diff --git a/etemplate/inc/class.etemplate_widget_customfields.inc.php b/etemplate/inc/class.etemplate_widget_customfields.inc.php index 52355e42a0..5015330d5d 100644 --- a/etemplate/inc/class.etemplate_widget_customfields.inc.php +++ b/etemplate/inc/class.etemplate_widget_customfields.inc.php @@ -277,6 +277,8 @@ class etemplate_widget_customfields extends etemplate_widget_transformer case 'date': case 'date-time': $widget->attrs['dataformat'] = $type == 'date' ? 'Y-m-d' : 'Y-m-d H:i:s'; + if($field['values']['min']) $widget->attrs['min'] = $field['values']['min']; + if($field['values']['max']) $widget->attrs['min'] = $field['values']['max']; break; case 'link-to': diff --git a/etemplate/inc/class.etemplate_widget_date.inc.php b/etemplate/inc/class.etemplate_widget_date.inc.php index a8807cf7f4..ad041dca2e 100644 --- a/etemplate/inc/class.etemplate_widget_date.inc.php +++ b/etemplate/inc/class.etemplate_widget_date.inc.php @@ -162,6 +162,44 @@ class etemplate_widget_date extends etemplate_widget_transformer { $date = new egw_time($value); } + if (!empty($this->attrs['min'])) + { + if(is_numeric($this->attrs['min'])) + { + $min = new egw_time(strtotime( $this->attrs['min'] . 'days')); + } + else + { + $min = new egw_time(strtotime($this->attrs['min'])); + } + if($value < $min) + { + self::set_validation_error($form_name,lang( + "Value has to be at least '%1' !!!", + $min->format($this->type != 'date') + ),''); + $value = $min; + } + } + if (!empty($this->attrs['max'])) + { + if(is_numeric($this->attrs['max'])) + { + $max = new egw_time(strtotime( $this->attrs['max'] . 'days')); + } + else + { + $max = new egw_time(strtotime($this->attrs['max'])); + } + if($value < $max) + { + self::set_validation_error($form_name,lang( + "Value has to be at maximum '%1' !!!", + $max->format($this->type != 'date') + ),''); + $value = $max; + } + } if(!$value) { // Not null, blank diff --git a/etemplate/js/et2_extension_customfields.js b/etemplate/js/et2_extension_customfields.js index 06a179acd2..aaa51a0179 100644 --- a/etemplate/js/et2_extension_customfields.js +++ b/etemplate/js/et2_extension_customfields.js @@ -233,6 +233,16 @@ var et2_customfields_list = et2_valueWidget.extend([et2_IDetachedDOM, et2_IInput } this.rows[id] = cf[0]; + // Set any additional attributes set in options, but not for widgets that pass actual options + if(['select','radio','radiogroup','checkbox','button'].indexOf(field.type) == -1 && !jQuery.isEmptyObject(field.values)) + { + var w = et2_registry[attrs.type ? attrs.type : field.type]; + for(var attr_name in field.values) + { + if (typeof w.prototype.attributes[attr_name] != "undefined") + attrs[attr_name] = field.values[attr_name]; + } + } // Create widget var widget = this.widgets[field_name] = et2_createWidget(attrs.type ? attrs.type : field.type, attrs, this); } diff --git a/etemplate/js/et2_widget_date.js b/etemplate/js/et2_widget_date.js index 7d8a6684e8..316141e799 100644 --- a/etemplate/js/et2_widget_date.js +++ b/etemplate/js/et2_widget_date.js @@ -47,7 +47,31 @@ var et2_date = et2_inputWidget.extend( "ignore": true, "description": "Date/Time format. Can be set as an options to date widget", "default": '' - } + }, + year_range: { + name: "Year range", + type: "string", + default: "c-10:c+10", + description: "The range of years displayed in the year drop-down: either relative to today's year (\"-nn:+nn\"), relative to the currently selected year (\"c-nn:c+nn\"), absolute (\"nnnn:nnnn\"), or combinations of these formats (\"nnnn:-nn\"). Note that this option only affects what appears in the drop-down, to restrict which dates may be selected use the min and/or max options." + }, + min: { + "name": "Minimum", + "type": "any", + "default": et2_no_init, + "description": 'Minimum allowed date. Multiple types supported:\ +Date: A date object containing the minimum date.\ +Number: A number of days from today. For example 2 represents two days from today and -1 represents yesterday.\ +String: A string in the user\'s date format, or a relative date. Relative dates must contain value and period pairs; valid periods are "y" for years, "m" for months, "w" for weeks, and "d" for days. For example, "+1m +7d" represents one month and seven days from today.' + }, + max: { + "name": "Maximum", + "type": "any", + "default": et2_no_init, + "description": 'Maximum allowed date. Multiple types supported:\ +Date: A date object containing the maximum date.\ +Number: A number of days from today. For example 2 represents two days from today and -1 represents yesterday.\ +String: A string in the user\'s date format, or a relative date. Relative dates must contain value and period pairs; valid periods are "y" for years, "m" for months, "w" for weeks, and "d" for days. For example, "+1m +7d" represents one month and seven days from today.' + }, }, legacyOptions: ["data_format"], @@ -256,6 +280,70 @@ var et2_date = et2_inputWidget.extend( return this.input_date.val() == "" ? null : this.date.getTime(); }, + /** + * The range of years displayed in the year drop-down: either relative + * to today's year ("-nn:+nn"), relative to the currently selected year + * ("c-nn:c+nn"), absolute ("nnnn:nnnn"), or combinations of these formats + * ("nnnn:-nn"). Note that this option only affects what appears in the + * drop-down, to restrict which dates may be selected use the min_date + * and/or max_date options. + * @param {string} _value + */ + set_year_range: function(_value) + { + if(this.input_date) + { + this.input_date.datepicker('option','yearRange',_value); + } + this.options.year_range = _value; + }, + + /** + * Set the minimum allowed date + * + * The minimum selectable date. When set to null, there is no minimum. + * Multiple types supported: + * Date: A date object containing the minimum date. + * Number: A number of days from today. For example 2 represents two days + * from today and -1 represents yesterday. + * String: A string in the format defined by the dateFormat option, or a + * relative date. Relative dates must contain value and period pairs; + * valid periods are "y" for years, "m" for months, "w" for weeks, and + * "d" for days. For example, "+1m +7d" represents one month and seven + * days from today. + * @param {Date|Number|String} _value + */ + set_min: function(_value) { + if(this.input_date) + { + this.input_date.datepicker('option','minDate',_value); + } + this.options.min = _value; + }, + + /** + * Set the maximum allowed date + * + * The maximum selectable date. When set to null, there is no maximum. + * Multiple types supported: + * Date: A date object containing the maximum date. + * Number: A number of days from today. For example 2 represents two days + * from today and -1 represents yesterday. + * String: A string in the format defined by the dateFormat option, or a + * relative date. Relative dates must contain value and period pairs; + * valid periods are "y" for years, "m" for months, "w" for weeks, and + * "d" for days. For example, "+1m +7d" represents one month and seven + * days from today. + * @param {Date|Number|String} _value + */ + set_max: function(_value) { + if(this.input_date) + { + this.input_date.datepicker('option','maxDate',_value); + } + this.options.max = _value; + }, + /** * Setting date * @@ -792,7 +880,10 @@ var et2_date_ro = et2_valueWidget.extend([et2_IDetachedDOM], "data_format": { "ignore": true, "description": "Format data is in. This is not used client-side because it's always a timestamp client side." - } + }, + min: {ignore: true}, + max: {ignore: true}, + year_range: {ignore: true} }, legacyOptions: ["data_format"],