Browse Source

form wip

tags/2.0.0-beta
Qiang Xue 12 years ago
parent
commit
8a07bce836
  1. 149
      framework/assets/yii.activeForm.js
  2. 5
      framework/widgets/ActiveField.php

149
framework/assets/yii.activeForm.js

@ -67,7 +67,7 @@
settings.validationUrl = $form.attr('action'); settings.validationUrl = $form.attr('action');
} }
$.each(attributes, function (i) { $.each(attributes, function (i) {
this.value = getInputValue($form.find('#' + this.inputID)); this.value = getInputValue($form.find(this.inputSelector));
attributes[i] = $.extend(settings, this); attributes[i] = $.extend(settings, this);
}); });
$form.data('yiiActiveForm', { $form.data('yiiActiveForm', {
@ -77,6 +77,10 @@
bindAttributes(attributes); bindAttributes(attributes);
/**
* Clean up error status when resetting the form.
* Note that neither $form.reset(...) nor $form.on('reset', ...) works.
*/
$form.bind('reset', resetForm); $form.bind('reset', resetForm);
if (settings.validateOnSubmit) { if (settings.validateOnSubmit) {
@ -84,42 +88,7 @@
$form.data('submitObject', $(this)); $form.data('submitObject', $(this));
}); });
var validated = false; var validated = false;
$form.submit(function () { $form.submit(submitForm);
if (validated) {
validated = false;
return true;
}
if (settings.timer !== undefined) {
clearTimeout(settings.timer);
}
settings.submitting = true;
if (settings.beforeValidate === undefined || settings.beforeValidate($form)) {
$.fn.yiiactiveform.validate($form, function (data) {
var hasError = false;
$.each(settings.attributes, function () {
hasError = $.fn.yiiactiveform.updateInput(this, data, $form) || hasError;
});
$.fn.yiiactiveform.updateSummary($form, data);
if (settings.afterValidate === undefined || settings.afterValidate($form, data, hasError)) {
if (!hasError) {
validated = true;
var $button = $form.data('submitObject') || $form.find(':submit:first');
// TODO: if the submission is caused by "change" event, it will not work
if ($button.length) {
$button.click();
} else { // no submit button in the form
$form.submit();
}
return;
}
}
settings.submitting = false;
});
} else {
settings.submitting = false;
}
return false;
});
} }
}); });
}, },
@ -139,7 +108,8 @@
* @param $e jQuery the jQuery object of the input element * @param $e jQuery the jQuery object of the input element
* @return string the input value * @return string the input value
*/ */
var getInputValue = function ($e) { var getInputValue = function ($input) {
// TBD
var type, var type,
c = []; c = [];
if (!$e.length) { if (!$e.length) {
@ -159,19 +129,32 @@
} }
}; };
var findInput = function ($form, attribute) {
var $e = $form.find(attribute.inputSelector);
if (!$e.length) {
return undefined;
}
if ($e[0].tagName.toLowerCase() === 'div') {
// checkbox list or radio list
return $e.find('input');
} else {
return $e;
}
};
var bindAttributes = function (attributes) { var bindAttributes = function (attributes) {
$.each(attributes, function (i, attribute) { $.each(attributes, function (i, attribute) {
if (this.validateOnChange) { if (this.validateOnChange) {
$form.find('#' + this.inputID).change(function () { $form.find(this.inputSelector).change(function () {
validateAttribute(attribute, false); validateAttribute(attribute, false);
}).blur(function () { }).blur(function () {
if (attribute.status !== 2 && attribute.status !== 3) { if (attribute.status !== 2 && attribute.status !== 3) {
validateAttribute(attribute, !attribute.status); validateAttribute(attribute, !attribute.status);
} }
}); });
} }
if (this.validateOnType) { if (this.validateOnType) {
$form.find('#' + this.inputID).keyup(function () { $form.find(this.inputSelector).keyup(function () {
if (attribute.value !== getAFValue($(this))) { if (attribute.value !== getAFValue($(this))) {
validateAttribute(attribute, false); validateAttribute(attribute, false);
} }
@ -293,27 +276,61 @@
}, attribute.validationDelay); }, attribute.validationDelay);
}; };
var submitForm = function () {
if (validated) {
validated = false;
return true;
}
if (settings.timer !== undefined) {
clearTimeout(settings.timer);
}
settings.submitting = true;
if (settings.beforeValidate === undefined || settings.beforeValidate($form)) {
$.fn.yiiactiveform.validate($form, function (data) {
var hasError = false;
$.each(settings.attributes, function () {
hasError = $.fn.yiiactiveform.updateInput(this, data, $form) || hasError;
});
$.fn.yiiactiveform.updateSummary($form, data);
if (settings.afterValidate === undefined || settings.afterValidate($form, data, hasError)) {
if (!hasError) {
validated = true;
var $button = $form.data('submitObject') || $form.find(':submit:first');
// TODO: if the submission is caused by "change" event, it will not work
if ($button.length) {
$button.click();
} else { // no submit button in the form
$form.submit();
}
return;
}
}
settings.submitting = false;
});
} else {
settings.submitting = false;
}
return false;
};
var resetForm = function () { var resetForm = function () {
/* var settings = $(this).data('yiiActiveForm').settings;
* In case of resetting the form we need to reset error messages var attributes = $(this).data('yiiActiveForm').attributes;
* NOTE1: $form.reset - does not exist
* NOTE2: $form.on('reset', ...) does not work
*/
/* /*
* because we bind directly to a form reset event, not to a reset button (that could or could not exist), * because we bind directly to a form reset event, not to a reset button (that could or could not exist),
* when this function is executed form elements values have not been reset yet, * when this function is executed form elements values have not been reset yet,
* because of that we use the setTimeout * because of that we use the setTimeout
*/ */
setTimeout(function () { setTimeout(function () {
$.each(settings.attributes, function () { $.each(attributes, function () {
this.status = 0; this.status = 0;
var $error = $form.find('#' + this.errorID), var $error = $form.find('#' + this.errorID),
$container = $.fn.yiiactiveform.getInputContainer(this, $form); $container = getInputContainer(this, $form);
$container.removeClass( $container.removeClass(
this.validatingCssClass + ' ' + settings.validatingCssClass + ' ' +
this.errorCssClass + ' ' + settings.errorCssClass + ' ' +
this.successCssClass settings.successCssClass
); );
$error.html('').hide(); $error.html('').hide();
@ -321,20 +338,10 @@
/* /*
* without the setTimeout() we would get here the current entered value before the reset instead of the reseted value * without the setTimeout() we would get here the current entered value before the reset instead of the reseted value
*/ */
this.value = getAFValue($form.find('#' + this.inputID)); this.value = getInputValue($form.find('#' + this.inputID));
});
/*
* If the form is submited (non ajax) with errors, labels and input gets the class 'error'
*/
$form.find('label, input').each(function () {
$(this).removeClass(settings.errorCss);
}); });
$('#' + settings.summaryID).hide().find('ul').html(''); $('#' + settings.summaryID).hide().find('ul').html('');
//.. set to initial focus on reset }, 10);
if (settings.focus !== undefined && !window.location.hash) {
$form.find(settings.focus).focus();
}
}, 1);
}; };
@ -401,7 +408,7 @@
* @param messages array the json data obtained from the ajax validation request * @param messages array the json data obtained from the ajax validation request
*/ */
var updateSummary = function (form, messages) { var updateSummary = function (form, messages) {
var settings = $(form).data('settings'), var settings = $(form).data('yiiActiveForm'),
content = ''; content = '';
if (settings.summaryID === undefined) { if (settings.summaryID === undefined) {
return; return;
@ -418,4 +425,12 @@
$('#' + settings.summaryID).toggle(content !== '').find('ul').html(content); $('#' + settings.summaryID).toggle(content !== '').find('ul').html(content);
}; };
var getSettings = function (form) {
return $(form).data('yiiActiveForm').settings;
};
var getAttributes = function (form) {
return $(form).data('yiiActiveForm').attributes;
};
})(window.jQuery); })(window.jQuery);

5
framework/widgets/ActiveField.php

@ -103,7 +103,7 @@ class ActiveField extends Component
/** /**
* Generates a tag that contains the first validation error of [[attribute]]. * Generates a tag that contains the first validation error of [[attribute]].
* If there is no validation, the tag will be returned and styled as hidden. * Note that even if there is no validation error, this method will still return an empty error tag.
* @param array $options the tag options in terms of name-value pairs. If this is null, [[errorOptions]] will be used. * @param array $options the tag options in terms of name-value pairs. If this is null, [[errorOptions]] will be used.
* The options will be rendered as the attributes of the resulting tag. The values will be HTML-encoded * The options will be rendered as the attributes of the resulting tag. The values will be HTML-encoded
* using [[encode()]]. If a value is null, the corresponding attribute will not be rendered. * using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
@ -121,9 +121,6 @@ class ActiveField extends Component
} }
$attribute = Html::getAttributeName($this->attribute); $attribute = Html::getAttributeName($this->attribute);
$error = $this->model->getFirstError($attribute); $error = $this->model->getFirstError($attribute);
if ($error === null) {
$options['style'] = isset($options['style']) ? rtrim($options['style'], ';') . '; display:none' : 'display:none';
}
$tag = isset($options['tag']) ? $options['tag'] : 'span'; $tag = isset($options['tag']) ? $options['tag'] : 'span';
unset($options['tag']); unset($options['tag']);
return Html::tag($tag, Html::encode($error), $options); return Html::tag($tag, Html::encode($error), $options);

Loading…
Cancel
Save