Index: core/admin_templates/incs/form_blocks.tpl =================================================================== --- core/admin_templates/incs/form_blocks.tpl (revision 13557) +++ core/admin_templates/incs/form_blocks.tpl (working copy) @@ -720,6 +720,22 @@ + + '': '', + + + + '': '', + + + + + {} + + {} + + + @@ -860,7 +876,7 @@ .InitEvents(); - .SetMessage('required_error', ''); + .SetMessage('required_error', ''); .SetMessage('unique_error', ''); .SetMessage('delete_confirm', ''); .SetMessage('add_button', ''); Index: core/admin_templates/js/form_controls.js =================================================================== --- core/admin_templates/js/form_controls.js (revision 13557) +++ core/admin_templates/js/form_controls.js (working copy) @@ -15,7 +15,23 @@ } MultiInputControl.prototype.registerControl = function($field_name, $type, $required, $options) { - this.Controls[$field_name] = {'type' : $type, 'required' : $required, 'options' : $options}; + if (Object.prototype.toString.call($type) === "[object String]") { + this.Controls[$field_name] = { + 'type' : $type, + 'required' : $required, + 'options' : $options, + }; + } + else { + if ($required === undefined || $required === false) { + // type, required, options, default + this.Controls[$field_name] = $type; + } + else { + // upgrade control + $.extend(this.Controls[$field_name], $type); + } + } } MultiInputControl.prototype.getControl = function ($field, $appendix, $prepend) { @@ -34,6 +50,10 @@ $value = $control.options[$control.selectedIndex].value; break; + case 'radio': + $value = $("input[name='" + jq(this.FieldMask.replace('#FIELD_NAME#', $field)) + "']:checked").val(); + break; + /*case 'datetime': $value = this.getControl($field + '_date').value + ' ' + this.getControl($field + '_time').value; break;*/ @@ -47,6 +67,10 @@ } MultiInputControl.prototype.setControlValue = function ($field, $value) { + if ($value === null && this.Controls[$field]['default'] !== undefined) { + $value = this.Controls[$field]['default']; + } + switch (this.Controls[$field]['type']) { case 'select': var $i = 0; @@ -54,12 +78,8 @@ if ($value === null) { $control.selectedIndex = 0; } - while ($i < $control.options.length) { - if ($control.options[$i].value == $value) { - $control.selectedIndex = $i; - break; - } - $i++; + else { + $($control).val($value).change(); } break; @@ -68,6 +88,15 @@ this.getControl($field, null, '_cb').checked = parseInt($value) == 1; break; + case 'radio': + if ($value === null) { + $("input[name='" + jq(this.FieldMask.replace('#FIELD_NAME#', $field)) + "']:checked").attr('checked', '').change(); + } + else { + $( this.getControl($field, $value) ).attr('checked', 'checked').change(); + } + break; + /*case 'datetime': $value = $value.split(' '); this.getControl($field + '_date').value = $value[0]; @@ -75,7 +104,8 @@ break;*/ default: - this.getControl($field).value = ($value === null) ? '' : $value; + var $control = this.getControl($field); + $($control).val($value === null ? '' : $value).change(); break; } } @@ -101,14 +131,14 @@ } } - if (this.Controls[$field]['type'] == 'checkbox') { - $value = this.Controls[$field]['options'][ parseInt($value) ]; + if (this.Controls[$field]['type'] == 'checkbox' || this.Controls[$field]['type'] == 'radio') { + $value = this.Controls[$field]['options'][$value]; } return $value; } -MultiInputControl.prototype.formatLine = function($record_index) { +MultiInputControl.prototype.formatLine = function($record_index, $escape) { var $ret = this.ResultMask; for (var $field_name in this.Controls) { @@ -116,9 +146,13 @@ $ret = $ret.replace('#' + $field_name + '#', this.formatValue($field_name, $value)); } - return this.htmlspecialchars($ret); + return $escape === undefined || $escape ? this.htmlspecialchars($ret) : $ret; } +MultiInputControl.prototype.isReadOnly = function($record_index) { + return false; +} + MultiInputControl.prototype._getRecordIndex = function ($selected_index) { var $object = this.getControl(this.FieldName, 'minput'); @@ -130,9 +164,10 @@ } MultiInputControl.prototype.makeRequest = function($request_type, $record, $skip_index) { - var $url = this.ValidateURL; + var $url = this.ValidateURL + '&request_type=' + encodeURIComponent($request_type); + for (var $field_name in $record) { - $url += '&' + this.FieldMask.replace('#FIELD_NAME#', $field_name) + '=' + escape($record[$field_name]); + $url += '&' + this.FieldMask.replace('#FIELD_NAME#', $field_name) + '=' + encodeURIComponent($record[$field_name]); } Request.makeRequest($url, this.BusyRequest, '', this.successCallback, this.errorCallback, [$request_type, $record, $skip_index], this); @@ -200,6 +235,7 @@ if ($option_index < $options.length) { // update existing record $options[$option_index].innerHTML = this.formatLine( this._getRecordIndex($option_index) ); + $options[$option_index].disabled = this.isReadOnly( this._getRecordIndex($option_index) ); } else { // create new record @@ -207,6 +243,7 @@ $options.add($new_option, $options.length); $new_option.value = $option_index; // will be used in move up/down & sorting (if any) $new_option.innerHTML = this.formatLine(this.Records.length - 1); + $new_option.disabled = this.isReadOnly(this.Records.length - 1); } } @@ -326,11 +363,11 @@ MultiInputControl.prototype.ValidateRequired = function($record) { for (var $field_name in $record) { if (this.Controls[$field_name]['required'] && !$record[$field_name]) { - alert(this.Messages['required_error']); - return false; + this.Errors[$field_name] = this.Messages['required_error']; } } - return true; + + return !this.displayErrors(); } MultiInputControl.prototype.compareRecords = function($record_a, $record_b) { @@ -369,14 +406,18 @@ } MultiInputControl.prototype.displayErrors = function() { - var $has_errors = false; - var $field_label = ''; + var $ret = []; + for (var $field_name in this.Errors) { - $has_errors = true; - alert(this.FieldLabels[$field_name] + ': ' + this.Errors[$field_name]); + $ret.push(this.FieldLabels[$field_name] + ': ' + this.Errors[$field_name]); } - return $has_errors; + if ($ret.length) { + alert( $ret.join("\n") ); + return true; + } + + return false; } MultiInputControl.prototype.successCallback = function($request, $params, $object) { Index: core/kernel/db/db_tag_processor.php =================================================================== --- core/kernel/db/db_tag_processor.php (revision 13557) +++ core/kernel/db/db_tag_processor.php (working copy) @@ -1141,6 +1141,9 @@ array_shift($options); } + $index = 0; + $option_count = count($options); + if (strpos($value, '|') !== false) { // multiple checkboxes OR multiselect $value = explode('|', substr($value, 1, -1) ); @@ -1148,7 +1151,10 @@ $block_params['key'] = $key; $block_params['option'] = $val; $block_params[$selected_param_name] = ( in_array($key, $value) ? ' '.$selected : ''); + $block_params['is_last'] = $index == $option_count - 1; $o .= $this->Application->ParseBlock($block_params); + + $index++; } } else { @@ -1157,7 +1163,10 @@ $block_params['key'] = $key; $block_params['option'] = $val; $block_params[$selected_param_name] = (strlen($key) == strlen($value) && ($key == $value) ? ' '.$selected : ''); + $block_params['is_last'] = $index == $option_count - 1; $o .= $this->Application->ParseBlock($block_params); + + $index++; } } return $o; Index: core/units/helpers/controls/minput_helper.php =================================================================== --- core/units/helpers/controls/minput_helper.php (revision 13557) +++ core/units/helpers/controls/minput_helper.php (working copy) @@ -46,17 +46,28 @@ return $xml ? ''.$xml.'' : ''; } + /** + * Returns validation errors in XML format + * + * @param kDBItem $object + * @param Array $fields_hash + * @return string + */ function prepareErrorsXML(&$object, $fields_hash) { $xml = ''; + $errors = Array (); + foreach ($fields_hash as $field_name => $field_value) { - $object->SetField($field_name, $field_value); if (!$object->ValidateField($field_name)) { - $xml .= ''.$object->GetErrorMsg($field_name, false).''; + $field_options = $object->GetFieldOptions($field_name); + $error_field = array_key_exists('error_field', $field_options) ? $field_options['error_field'] : $field_name; + + $errors[$error_field] = ''.$object->GetErrorMsg($error_field, false).''; } } - return ''.$xml.''; + return ''.implode('', $errors).''; } /** @@ -73,6 +84,21 @@ if ($items_info) { list ($id, $field_values) = each($items_info); + foreach ($field_values as $field_name => $field_value) { + $object->SetField($field_name, $field_value); + } + + $event_mapping = Array ( + 'AddRecord' => 'OnBeforeItemCreate', + 'SaveRecord' => 'OnBeforeItemUpdate', + ); + + $request_type = $this->Application->GetVar('request_type'); + + if (array_key_exists($request_type, $event_mapping)) { + $event->CallSubEvent($event_mapping[$request_type]); + } + echo $this->prepareErrorsXML($object, $field_values); }