mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #216 from halkyon/master
Removed old behaviour.js client-side form validation
This commit is contained in:
commit
7c4bc36a9b
@ -195,11 +195,6 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
|||||||
// Audit logging hook
|
// Audit logging hook
|
||||||
if(empty($_REQUEST['executeForm']) && !$this->isAjax()) $this->extend('accessedCMS');
|
if(empty($_REQUEST['executeForm']) && !$this->isAjax()) $this->extend('accessedCMS');
|
||||||
|
|
||||||
// Requirements
|
|
||||||
|
|
||||||
// Suppress behaviour/prototype validation instructions in CMS, not compatible with ajax loading of forms.
|
|
||||||
Validator::set_javascript_validation_handler('none');
|
|
||||||
|
|
||||||
// Set the members html editor config
|
// Set the members html editor config
|
||||||
HtmlEditorConfig::set_active(Member::currentUser()->getHtmlEditorConfigForCMS());
|
HtmlEditorConfig::set_active(Member::currentUser()->getHtmlEditorConfigForCMS());
|
||||||
|
|
||||||
@ -264,7 +259,6 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
|||||||
SAPPHIRE_DIR . '/javascript/DateField.js',
|
SAPPHIRE_DIR . '/javascript/DateField.js',
|
||||||
SAPPHIRE_DIR . '/javascript/HtmlEditorField.js',
|
SAPPHIRE_DIR . '/javascript/HtmlEditorField.js',
|
||||||
SAPPHIRE_DIR . '/javascript/TabSet.js',
|
SAPPHIRE_DIR . '/javascript/TabSet.js',
|
||||||
SAPPHIRE_DIR . '/javascript/Validator.js',
|
|
||||||
SAPPHIRE_DIR . '/javascript/i18n.js',
|
SAPPHIRE_DIR . '/javascript/i18n.js',
|
||||||
SAPPHIRE_ADMIN_DIR . '/javascript/ssui.core.js',
|
SAPPHIRE_ADMIN_DIR . '/javascript/ssui.core.js',
|
||||||
SAPPHIRE_DIR . '/javascript/GridField.js',
|
SAPPHIRE_DIR . '/javascript/GridField.js',
|
||||||
@ -913,7 +907,6 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
|||||||
// The clientside (mainly LeftAndMain*.js) rely on ajax responses
|
// The clientside (mainly LeftAndMain*.js) rely on ajax responses
|
||||||
// which can be evaluated as javascript, hence we need
|
// which can be evaluated as javascript, hence we need
|
||||||
// to override any global changes to the validation handler.
|
// to override any global changes to the validation handler.
|
||||||
$validator->setJavascriptValidationHandler('prototype');
|
|
||||||
$form->setValidator($validator);
|
$form->setValidator($validator);
|
||||||
} else {
|
} else {
|
||||||
$form->unsetValidator();
|
$form->unsetValidator();
|
||||||
|
@ -392,18 +392,20 @@ class ModelAdmin_CollectionController extends Controller {
|
|||||||
* @return Form
|
* @return Form
|
||||||
*/
|
*/
|
||||||
public function SearchForm() {
|
public function SearchForm() {
|
||||||
$context = singleton($this->modelClass)->getDefaultSearchContext();
|
$SNG_model = singleton($this->modelClass);
|
||||||
|
$context = $SNG_model->getDefaultSearchContext();
|
||||||
$fields = $context->getSearchFields();
|
$fields = $context->getSearchFields();
|
||||||
$columnSelectionField = $this->ColumnSelectionField();
|
$columnSelectionField = $this->ColumnSelectionField();
|
||||||
$fields->push($columnSelectionField);
|
$fields->push($columnSelectionField);
|
||||||
$validator = new RequiredFields();
|
|
||||||
$validator->setJavascriptValidationHandler('none');
|
$validator = ($SNG_model->hasMethod('getCMSValidator')) ? $SNG_model->getCMSValidator() : new RequiredFields();
|
||||||
|
$clearAction = new ResetFormAction('clearsearch', _t('ModelAdmin.CLEAR_SEARCH','Clear Search'));
|
||||||
|
|
||||||
$form = new Form($this, "SearchForm",
|
$form = new Form($this, "SearchForm",
|
||||||
$fields,
|
$fields,
|
||||||
new FieldList(
|
new FieldList(
|
||||||
new FormAction('search', _t('MemberTableField.SEARCH', 'Search')),
|
new FormAction('search', _t('MemberTableField.SEARCH', 'Search')),
|
||||||
$clearAction = new ResetFormAction('clearsearch', _t('ModelAdmin.CLEAR_SEARCH','Clear Search'))
|
$clearAction
|
||||||
),
|
),
|
||||||
$validator
|
$validator
|
||||||
);
|
);
|
||||||
@ -423,26 +425,28 @@ class ModelAdmin_CollectionController extends Controller {
|
|||||||
*/
|
*/
|
||||||
public function CreateForm() {
|
public function CreateForm() {
|
||||||
$modelName = $this->modelClass;
|
$modelName = $this->modelClass;
|
||||||
|
$SNG_model = singleton($modelName);
|
||||||
|
|
||||||
if($this->hasMethod('alternatePermissionCheck')) {
|
if($this->hasMethod('alternatePermissionCheck')) {
|
||||||
if(!$this->alternatePermissionCheck()) return false;
|
if(!$this->alternatePermissionCheck()) return false;
|
||||||
} else {
|
} else {
|
||||||
if(!singleton($modelName)->canCreate(Member::currentUser())) return false;
|
if(!$SNG_model->canCreate(Member::currentUser())) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$buttonLabel = sprintf(_t('ModelAdmin.CREATEBUTTON', "Create '%s'", PR_MEDIUM, "Create a new instance from a model class"), singleton($modelName)->i18n_singular_name());
|
$buttonLabel = sprintf(_t('ModelAdmin.CREATEBUTTON', "Create '%s'", PR_MEDIUM, "Create a new instance from a model class"), $SNG_model->i18n_singular_name());
|
||||||
|
|
||||||
|
$validator = ($SNG_model->hasMethod('getCMSValidator')) ? $SNG_model->getCMSValidator() : new RequiredFields();
|
||||||
|
$createButton = FormAction::create('add', $buttonLabel)->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'accept');
|
||||||
|
|
||||||
$form = new Form($this, "CreateForm",
|
$form = new Form($this, "CreateForm",
|
||||||
new FieldList(),
|
new FieldList(),
|
||||||
new FieldList(
|
new FieldList($createButton),
|
||||||
$createButton = FormAction::create('add', $buttonLabel)
|
$validator
|
||||||
->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'accept')
|
);
|
||||||
),
|
|
||||||
$validator = new RequiredFields()
|
|
||||||
);
|
|
||||||
$createButton->dontEscape = true;
|
$createButton->dontEscape = true;
|
||||||
$validator->setJavascriptValidationHandler('none');
|
|
||||||
$form->setHTMLID("Form_CreateForm_" . $this->modelClass);
|
$form->setHTMLID("Form_CreateForm_" . $this->modelClass);
|
||||||
|
|
||||||
return $form;
|
return $form;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,15 +502,11 @@ class ModelAdmin_CollectionController extends Controller {
|
|||||||
new FormAction('import', _t('ModelAdmin.IMPORT', 'Import from CSV'))
|
new FormAction('import', _t('ModelAdmin.IMPORT', 'Import from CSV'))
|
||||||
);
|
);
|
||||||
|
|
||||||
$validator = new RequiredFields();
|
|
||||||
$validator->setJavascriptValidationHandler('none');
|
|
||||||
|
|
||||||
$form = new Form(
|
$form = new Form(
|
||||||
$this,
|
$this,
|
||||||
"ImportForm",
|
"ImportForm",
|
||||||
$fields,
|
$fields,
|
||||||
$actions,
|
$actions
|
||||||
$validator
|
|
||||||
);
|
);
|
||||||
$form->setHTMLID("Form_ImportForm_" . $this->modelClass);
|
$form->setHTMLID("Form_ImportForm_" . $this->modelClass);
|
||||||
return $form;
|
return $form;
|
||||||
@ -802,9 +802,7 @@ class ModelAdmin_CollectionController extends Controller {
|
|||||||
$fields = $newRecord->getCMSFields();
|
$fields = $newRecord->getCMSFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
$validator = ($newRecord->hasMethod('getCMSValidator')) ? $newRecord->getCMSValidator() : null;
|
$validator = ($newRecord->hasMethod('getCMSValidator')) ? $newRecord->getCMSValidator() : new RequiredFields();
|
||||||
if(!$validator) $validator = new RequiredFields();
|
|
||||||
$validator->setJavascriptValidationHandler('none');
|
|
||||||
|
|
||||||
$actions = new FieldList (
|
$actions = new FieldList (
|
||||||
FormAction::create("doCreate", _t('ModelAdmin.ADDBUTTON', "Add"))
|
FormAction::create("doCreate", _t('ModelAdmin.ADDBUTTON', "Add"))
|
||||||
@ -922,7 +920,6 @@ class ModelAdmin_RecordController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$validator = ($this->currentRecord->hasMethod('getCMSValidator')) ? $this->currentRecord->getCMSValidator() : new RequiredFields();
|
$validator = ($this->currentRecord->hasMethod('getCMSValidator')) ? $this->currentRecord->getCMSValidator() : new RequiredFields();
|
||||||
$validator->setJavascriptValidationHandler('none');
|
|
||||||
|
|
||||||
$actions = $this->currentRecord->getCMSActions();
|
$actions = $this->currentRecord->getCMSActions();
|
||||||
if($this->currentRecord->canEdit(Member::currentUser())){
|
if($this->currentRecord->canEdit(Member::currentUser())){
|
||||||
|
@ -73,6 +73,45 @@ not when simply using the CMS or developing other CMS functionality.
|
|||||||
If you want to extend the CMS stylesheets for your own projects without SCSS,
|
If you want to extend the CMS stylesheets for your own projects without SCSS,
|
||||||
please create a new CSS file and link it into the CMS via `[api:LeftAndMain::require_css()]`.
|
please create a new CSS file and link it into the CMS via `[api:LeftAndMain::require_css()]`.
|
||||||
|
|
||||||
|
### Built-in Javascript validation removed ###
|
||||||
|
|
||||||
|
Built-in client-side form validation using behaviour.js has been removed, and is no longer supported.
|
||||||
|
|
||||||
|
Server-side validation remains. Developers are encouraged to use custom Javascript validation on their
|
||||||
|
forms if requiring client-side validation.
|
||||||
|
|
||||||
|
These classes/files have been removed:
|
||||||
|
|
||||||
|
Validator.js
|
||||||
|
CustomRequiredFields.php
|
||||||
|
|
||||||
|
These functions are now deprecated and will throw a notice if used:
|
||||||
|
|
||||||
|
Validator::set_javascript_validation_handler()
|
||||||
|
Validator::get_javascript_validator_handler()
|
||||||
|
Validator::setJavascriptValidationHandler()
|
||||||
|
|
||||||
|
These functions have been removed:
|
||||||
|
|
||||||
|
Validator::javascript() (abstract function)
|
||||||
|
Validator::includeJavascriptValidation()
|
||||||
|
FormField::jsValidation()
|
||||||
|
AjaxUniqueTextField::jsValidation()
|
||||||
|
ConfirmedPasswordField::jsValidation()
|
||||||
|
CreditCardField::jsValidation()
|
||||||
|
CurrencyField::jsValidation()
|
||||||
|
CustomRequiredFields::javascript()
|
||||||
|
DateField::jsValidation()
|
||||||
|
DatetimeField::jsValidation()
|
||||||
|
EmailField::jsValidation()
|
||||||
|
FieldGroup::jsValidation()
|
||||||
|
FormField::jsValidation()
|
||||||
|
NumericField::jsValidation()
|
||||||
|
PhoneNumberField::jsValidation()
|
||||||
|
RequiredFields::javascript()
|
||||||
|
TableField::jsValidation()
|
||||||
|
TimeField::jsValidation()
|
||||||
|
|
||||||
### FormField consistently adds classes to HTML elements ###
|
### FormField consistently adds classes to HTML elements ###
|
||||||
|
|
||||||
The [api:FormField] API has been refactored to use SilverStripe templates
|
The [api:FormField] API has been refactored to use SilverStripe templates
|
||||||
|
@ -34,8 +34,6 @@ class AjaxUniqueTextField extends TextField {
|
|||||||
Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang');
|
Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang');
|
||||||
Requirements::javascript(SAPPHIRE_DIR . "/javascript/UniqueFields.js");
|
Requirements::javascript(SAPPHIRE_DIR . "/javascript/UniqueFields.js");
|
||||||
|
|
||||||
$this->jsValidation();
|
|
||||||
|
|
||||||
$url = Convert::raw2att( $this->validateURL );
|
$url = Convert::raw2att( $this->validateURL );
|
||||||
|
|
||||||
if($this->restrictedRegex)
|
if($this->restrictedRegex)
|
||||||
@ -54,63 +52,7 @@ class AjaxUniqueTextField extends TextField {
|
|||||||
return $this->createTag('input', $attributes);
|
return $this->createTag('input', $attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
function jsValidation() {
|
|
||||||
$formID = $this->form->FormName();
|
|
||||||
$id = $this->id();
|
|
||||||
$url = Director::absoluteBaseURL() . $this->validateURL;
|
|
||||||
|
|
||||||
if($this->restrictedRegex) {
|
|
||||||
$jsCheckFunc = <<<JS
|
|
||||||
Element.removeClassName(this, 'invalid');
|
|
||||||
var match = this.value.match(/{$this->restrictedRegex}/);
|
|
||||||
if(match) {
|
|
||||||
Element.addClassName(this, 'invalid');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
JS;
|
|
||||||
} else {
|
|
||||||
$jsCheckFunc = "return true;";
|
|
||||||
}
|
|
||||||
|
|
||||||
$jsFunc = <<<JS
|
|
||||||
Behaviour.register({
|
|
||||||
'#$id' : {
|
|
||||||
onkeyup: function() {
|
|
||||||
var self = this;
|
|
||||||
if(this.checkValid()) {
|
|
||||||
jQuery.ajax({
|
|
||||||
'url': '{$url}?ajax=1&{$this->name}=' + encodeURIComponent(this.value),
|
|
||||||
method: 'get',
|
|
||||||
success: function(response) {
|
|
||||||
if(response.responseText == 'ok')
|
|
||||||
Element.removeClassName(self, 'inuse');
|
|
||||||
else {
|
|
||||||
Element.addClassName(self, 'inuse');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function(response) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
checkValid: function() {
|
|
||||||
$jsCheckFunc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
JS;
|
|
||||||
Requirements::customScript($jsFunc, 'func_validateAjaxUniqueTextField');
|
|
||||||
|
|
||||||
//return "\$('$formID').validateCurrency('$this->name');";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate( $validator ) {
|
function validate( $validator ) {
|
||||||
|
|
||||||
$result = DB::query(sprintf(
|
$result = DB::query(sprintf(
|
||||||
"SELECT COUNT(*) FROM \"%s\" WHERE \"%s\" = '%s'",
|
"SELECT COUNT(*) FROM \"%s\" WHERE \"%s\" = '%s'",
|
||||||
$this->restrictedTable,
|
$this->restrictedTable,
|
||||||
|
@ -204,97 +204,6 @@ class ConfirmedPasswordField extends FormField {
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
function jsValidation() {
|
|
||||||
$formID = $this->form->FormName();
|
|
||||||
$jsTests = '';
|
|
||||||
|
|
||||||
$jsTests .= "
|
|
||||||
// if fields are hidden, reset values and don't validate
|
|
||||||
var containers = $$('.showOnClickContainer', $('#'+fieldName));
|
|
||||||
if(containers.length && !Element.visible(containers[0])) {
|
|
||||||
passEl.value = null;
|
|
||||||
confEl.value = null;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
";
|
|
||||||
|
|
||||||
$error1 = _t('ConfirmedPasswordField.HAVETOMATCH', 'Passwords have to match.');
|
|
||||||
$jsTests .= "
|
|
||||||
if(passEl.value != confEl.value) {
|
|
||||||
validationError(confEl, \"$error1\", \"error\");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
";
|
|
||||||
|
|
||||||
$error2 = _t('ConfirmedPasswordField.NOEMPTY', 'Passwords can\'t be empty.');
|
|
||||||
if(!$this->canBeEmpty) {
|
|
||||||
$jsTests .= "
|
|
||||||
if(!passEl.value || !confEl.value) {
|
|
||||||
validationError(confEl, \"$error2\", \"error\");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(($this->minLength || $this->maxLength)) {
|
|
||||||
if($this->minLength && $this->maxLength) {
|
|
||||||
$limit = "{{$this->minLength},{$this->maxLength}}";
|
|
||||||
$errorMsg = sprintf(_t('ConfirmedPasswordField.BETWEEN', 'Passwords must be %s to %s characters long.'), $this->minLength, $this->maxLength);
|
|
||||||
} elseif($this->minLength) {
|
|
||||||
$limit = "{{$this->minLength}}.*";
|
|
||||||
$errorMsg = sprintf(_t('ConfirmedPasswordField.ATLEAST', 'Passwords must be at least %s characters long.'), $this->minLength);
|
|
||||||
} elseif($this->maxLength) {
|
|
||||||
$limit = "{0,{$this->maxLength}}";
|
|
||||||
$errorMsg = sprintf(_t('ConfirmedPasswordField.MAXIMUM', 'Passwords must be at most %s characters long.'), $this->maxLength);
|
|
||||||
}
|
|
||||||
$limitRegex = '/^.' . $limit . '$/';
|
|
||||||
$jsTests .= "
|
|
||||||
if(passEl.value && !passEl.value.match({$limitRegex})) {
|
|
||||||
validationError(confEl, \"{$errorMsg}\", \"error\");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
";
|
|
||||||
}
|
|
||||||
|
|
||||||
$error3 = _t('ConfirmedPasswordField.LEASTONE', 'Passwords must have at least one digit and one alphanumeric character.');
|
|
||||||
if($this->requireStrongPassword) {
|
|
||||||
$jsTests .= "
|
|
||||||
if(!passEl.value.match(/^(([a-zA-Z]+\d+)|(\d+[a-zA-Z]+))[a-zA-Z0-9]*$/)) {
|
|
||||||
validationError(
|
|
||||||
confEl,
|
|
||||||
\"$error3\",
|
|
||||||
\"error\"
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
";
|
|
||||||
}
|
|
||||||
|
|
||||||
$jsFunc =<<<JS
|
|
||||||
Behaviour.register({
|
|
||||||
"#$formID": {
|
|
||||||
validateConfirmedPassword: function(fieldName) {
|
|
||||||
var passEl = _CURRENT_FORM.elements['Password[_Password]'];
|
|
||||||
var confEl = _CURRENT_FORM.elements['Password[_ConfirmPassword]'];
|
|
||||||
$jsTests
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
JS;
|
|
||||||
Requirements :: customScript($jsFunc, 'func_validateConfirmedPassword');
|
|
||||||
|
|
||||||
//return "\$('$formID').validateConfirmedPassword('$this->name');";
|
|
||||||
return <<<JS
|
|
||||||
if(typeof fromAnOnBlur != 'undefined'){
|
|
||||||
if(fromAnOnBlur.name == '$this->name')
|
|
||||||
$('$formID').validateConfirmedPassword('$this->name');
|
|
||||||
}else{
|
|
||||||
$('$formID').validateConfirmedPassword('$this->name');
|
|
||||||
}
|
|
||||||
JS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the field was actually
|
* Determines if the field was actually
|
||||||
* shown on the clientside - if not,
|
* shown on the clientside - if not,
|
||||||
|
@ -35,62 +35,6 @@ class CreditCardField extends TextField {
|
|||||||
else return $this->value;
|
else return $this->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function jsValidation() {
|
|
||||||
$formID = $this->form->FormName();
|
|
||||||
$error1 = _t('CreditCardField.VALIDATIONJS1', 'Please ensure you have entered the');
|
|
||||||
$error2 = _t('CreditCardField.VALIDATIONJS2', 'credit card number correctly.');
|
|
||||||
$first = _t('CreditCardField.FIRST', 'first');
|
|
||||||
$second = _t('CreditCardField.SECOND', 'second');
|
|
||||||
$third = _t('CreditCardField.THIRD', 'third');
|
|
||||||
$fourth = _t('CreditCardField.FOURTH', 'fourth');
|
|
||||||
$jsFunc =<<<JS
|
|
||||||
Behaviour.register({
|
|
||||||
"#$formID": {
|
|
||||||
validateCreditCard: function(fieldName) {
|
|
||||||
if(!$(fieldName + "_Holder")) return true;
|
|
||||||
|
|
||||||
// Creditcards are split into multiple values, so get the inputs from the form.
|
|
||||||
var cardParts = $(fieldName + "_Holder").getElementsByTagName('input');
|
|
||||||
|
|
||||||
var cardisnull = true;
|
|
||||||
var i=0;
|
|
||||||
|
|
||||||
for(i=0; i < cardParts.length ; i++ ){
|
|
||||||
if(cardParts[i].value == null || cardParts[i].value == "")
|
|
||||||
cardisnull = cardisnull && true;
|
|
||||||
else
|
|
||||||
cardisnull = false;
|
|
||||||
}
|
|
||||||
if(!cardisnull){
|
|
||||||
// Concatenate the string values from the parts of the input.
|
|
||||||
for(i=0; i < cardParts.length ; i++ ){
|
|
||||||
// The creditcard number cannot be null, nor have less than 4 digits.
|
|
||||||
if(
|
|
||||||
cardParts[i].value == null || cardParts[i].value == "" ||
|
|
||||||
cardParts[i].value.length < 3 ||
|
|
||||||
!cardParts[i].value.match(/[0-9]{4}/)
|
|
||||||
){
|
|
||||||
switch(i){
|
|
||||||
case 0: number = "$first"; break;
|
|
||||||
case 1: number = "$second"; break;
|
|
||||||
case 2: number = "$third"; break;
|
|
||||||
case 3: number = "$fourth"; break;
|
|
||||||
}
|
|
||||||
validationError(cardParts[i],"$error1 " + number + " $error2","validation",false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
JS;
|
|
||||||
Requirements :: customScript($jsFunc, 'func_validateCreditCard');
|
|
||||||
|
|
||||||
return "\$('$formID').validateCreditCard('$this->name');";
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate($validator){
|
function validate($validator){
|
||||||
// If the field is empty then don't return an invalidation message
|
// If the field is empty then don't return an invalidation message
|
||||||
if(!trim(implode("", $this->value))) return true;
|
if(!trim(implode("", $this->value))) return true;
|
||||||
|
@ -48,37 +48,6 @@ class CurrencyField extends TextField {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see http://regexlib.com/REDetails.aspx?regexp_id=126
|
|
||||||
*/
|
|
||||||
function jsValidation() {
|
|
||||||
$formID = $this->form->FormName();
|
|
||||||
$error = _t('CurrencyField.VALIDATIONJS', 'Please enter a valid currency.');
|
|
||||||
$jsFunc =<<<JS
|
|
||||||
Behaviour.register({
|
|
||||||
"#$formID": {
|
|
||||||
validateCurrency: function(fieldName) {
|
|
||||||
var el = _CURRENT_FORM.elements[fieldName];
|
|
||||||
if(!el || !el.value) return true;
|
|
||||||
|
|
||||||
var value = \$F(el);
|
|
||||||
if(value.length > 0 && !value.match(/^\s*(-?\\\$?|\\\$-?)?(\d{1,3}(\,\d{3})*|(\d+))(\.\d{2})?\s*\$/)) {
|
|
||||||
validationError(el,"$error","validation",false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
JS;
|
|
||||||
|
|
||||||
Requirements::customScript($jsFunc, 'func_validateCurrency_' .$formID);
|
|
||||||
|
|
||||||
return <<<JS
|
|
||||||
if(\$('$formID')) \$('$formID').validateCurrency('$this->name');
|
|
||||||
JS;
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate($validator) {
|
function validate($validator) {
|
||||||
if(!empty ($this->value) && !preg_match('/^\s*(\-?\$?|\$\-?)?(\d{1,3}(\,\d{3})*|(\d+))(\.\d{2})?\s*$/', $this->value)) {
|
if(!empty ($this->value) && !preg_match('/^\s*(\-?\$?|\$\-?)?(\d{1,3}(\,\d{3})*|(\d+))(\.\d{2})?\s*$/', $this->value)) {
|
||||||
$validator->validationError($this->name, _t('Form.VALIDCURRENCY', "Please enter a valid currency."), "validation", false);
|
$validator->validationError($this->name, _t('Form.VALIDCURRENCY', "Please enter a valid currency."), "validation", false);
|
||||||
|
@ -1,148 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* CustomRequiredFields allow you to create your own validation on forms, while still having the ability to have required fields (as used in [RequiredFields](http://api.silverstripe.org/current/sapphire/form/RequiredFields.html)).
|
|
||||||
*
|
|
||||||
* The constructor of CustomRequiredFields takes an array. Each array element is one of two things - either the name of a field that is required, or an array containing two items, 'js' and 'php'. These items are functions called to validate in javascript or php respectively.
|
|
||||||
*
|
|
||||||
* Some useful javascript:
|
|
||||||
* 1. _CURRENT_FORM is the current form
|
|
||||||
* 2. _CURRENT_FORM.elements is an array of the fields
|
|
||||||
* 3. validationError(element, message, type) will create a validation error
|
|
||||||
* 4. clearErrorMessage(element) will clear the validation error
|
|
||||||
* 5. require('FieldName') create a required field ($this->requireField('FieldName') is the php equivalent)
|
|
||||||
*
|
|
||||||
* An example for creating required fields only if payment type is CreditCard:
|
|
||||||
*
|
|
||||||
* <code>
|
|
||||||
* new CustomRequiredFields(
|
|
||||||
* array(
|
|
||||||
* "PaymentMethod",
|
|
||||||
* array(
|
|
||||||
* "js" => "
|
|
||||||
* for( var i = 0; i <= this.elements.PaymentMethod.length -1; i++){
|
|
||||||
* if(this.elements.PaymentMethod[i].value == 'CC' && this.elements.PaymentMethod[i].checked == true){
|
|
||||||
* require('CardHolderName');
|
|
||||||
* require('CreditCardNumber');
|
|
||||||
* require('DateExpiry');
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* ",
|
|
||||||
* "php" => 'if($data[PaymentMethod] == "CC") {
|
|
||||||
* $this->requireField($field,"$field is required","required");
|
|
||||||
* $this->requireField("CardHolderName", $data);
|
|
||||||
* $this->requireField("CreditCardNumber", $data);
|
|
||||||
* $this->requireField("DateExpiry", $data);
|
|
||||||
* }',
|
|
||||||
* )
|
|
||||||
* )
|
|
||||||
* );
|
|
||||||
* </code>
|
|
||||||
*
|
|
||||||
* And example for confirming mobile number and email address:
|
|
||||||
*
|
|
||||||
* <code>
|
|
||||||
* $js = <<<JS
|
|
||||||
* if(_CURRENT_FORM.elements["MobileNumberConfirm"].value == _CURRENT_FORM.elements["MobileNumber"].value) {
|
|
||||||
* clearErrorMessage(_CURRENT_FORM.elements["MobileNumberConfirm"].parentNode);
|
|
||||||
* } else {
|
|
||||||
* validationError(_CURRENT_FORM.elements["MobileNumberConfirm"], "Mobile numbers do not match", "validation");
|
|
||||||
* }
|
|
||||||
* JS;
|
|
||||||
*
|
|
||||||
* $js2 = <<<JS2
|
|
||||||
* if(_CURRENT_FORM.elements["EmailConfirm"].value == _CURRENT_FORM.elements["Email"].value) {
|
|
||||||
* clearErrorMessage(_CURRENT_FORM.elements["EmailConfirm"].parentNode);
|
|
||||||
* } else {
|
|
||||||
* validationError(_CURRENT_FORM.elements["EmailConfirm"], "Email addresses do not match", "validation");
|
|
||||||
* }
|
|
||||||
* JS2;
|
|
||||||
*
|
|
||||||
* //create validator
|
|
||||||
* $validator=new CustomRequiredFields(array('FirstName', 'Surname', 'Email', 'MobileNumber', array('js' => $js, 'php' => 'return true;'), array('js' => $js2, 'php'=>'return true;')));
|
|
||||||
* </code>
|
|
||||||
*
|
|
||||||
* @package forms
|
|
||||||
* @subpackage validators
|
|
||||||
*/
|
|
||||||
class CustomRequiredFields extends RequiredFields{
|
|
||||||
protected $required;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pass each field to be validated as a seperate argument
|
|
||||||
* @param $required array The list of required fields
|
|
||||||
*/
|
|
||||||
function __construct($required) {
|
|
||||||
$this->required = $required;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the client side validation from form fields
|
|
||||||
* which is generated at the header of each page
|
|
||||||
*/
|
|
||||||
function javascript() {
|
|
||||||
$code = '';
|
|
||||||
$fields = $this->form->Fields();
|
|
||||||
foreach($fields as $field){
|
|
||||||
//if the field type has some special specific specification for validation of itself
|
|
||||||
$valid = $field->jsValidation();
|
|
||||||
if($valid){
|
|
||||||
$code .= $valid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(is_array($this->required)){
|
|
||||||
|
|
||||||
foreach($this->required as $field) {
|
|
||||||
if(is_array($field) && isset($field['js'])){
|
|
||||||
$code .= $field['js'] . "\n";
|
|
||||||
}else if($fields->dataFieldByName($field)) {
|
|
||||||
$code .= " require('$field');\n";
|
|
||||||
//Tabs for output tabbing :-)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
USER_ERROR("CustomRequiredFields::requiredfields is not set / not an array",E_USER_WARNING);
|
|
||||||
}
|
|
||||||
return $code;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the server side validation from form fields
|
|
||||||
* which is executed on form submission
|
|
||||||
*/
|
|
||||||
function php($data) {
|
|
||||||
$fields = $this->form->Fields();
|
|
||||||
$valid = true;
|
|
||||||
foreach($fields as $field) {
|
|
||||||
$valid = ($field->validate($this) && $valid);
|
|
||||||
}
|
|
||||||
if($this->required){
|
|
||||||
foreach($this->required as $key => $fieldName) {
|
|
||||||
if(is_string($fieldName)) $formField = $fields->dataFieldByName($fieldName);
|
|
||||||
if(is_array($fieldName) && isset($fieldName['php'])){
|
|
||||||
eval($fieldName['php']);
|
|
||||||
}else if($formField) {
|
|
||||||
// if an error is found, the form is returned.
|
|
||||||
if(!strlen($data[$fieldName]) || preg_match('/^\s*$/', $data[$fieldName])) {
|
|
||||||
$this->validationError(
|
|
||||||
$fieldName,
|
|
||||||
sprintf(_t('Form.FIELDISREQUIRED', "%s is required."),
|
|
||||||
$formField->Title()),
|
|
||||||
"required"
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* allows you too add more required fields to this object after construction.
|
|
||||||
*/
|
|
||||||
function appendRequiredFields($requiredFields){
|
|
||||||
$this->required = array_merge($this->required,$requiredFields->getRequired());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -252,104 +252,6 @@ class DateField extends TextField {
|
|||||||
return $field;
|
return $field;
|
||||||
}
|
}
|
||||||
|
|
||||||
function jsValidation() {
|
|
||||||
// JavaScript validation of locales other than en_NZ are not supported at the moment...
|
|
||||||
if($this->getLocale() != 'en_NZ') return;
|
|
||||||
|
|
||||||
$formID = $this->form->FormName();
|
|
||||||
|
|
||||||
if(Validator::get_javascript_validator_handler() == 'none') return true;
|
|
||||||
|
|
||||||
if($this->getConfig('dmyfields')) {
|
|
||||||
$error = _t('DateField.VALIDATIONJS', 'Please enter a valid date format.');
|
|
||||||
// Remove hardcoded date formats from translated strings
|
|
||||||
$error = preg_replace('/\(.*\)/', '', $error);
|
|
||||||
$error .= ' (' . $this->getConfig('dateformat') .')';
|
|
||||||
|
|
||||||
$jsFunc =<<<JS
|
|
||||||
Behaviour.register({
|
|
||||||
"#$formID": {
|
|
||||||
validateDMYDate: function(fieldName) {
|
|
||||||
var day_value = \$F(_CURRENT_FORM.elements[fieldName+'[day]']);
|
|
||||||
var month_value = \$F(_CURRENT_FORM.elements[fieldName+'[month]']);
|
|
||||||
var year_value = \$F(_CURRENT_FORM.elements[fieldName+'[year]']);
|
|
||||||
|
|
||||||
// TODO NZ specific
|
|
||||||
var value = day_value + '/' + month_value + '/' + year_value;
|
|
||||||
if(value && value.length > 0 && !value.match(/^[0-9]{1,2}\/[0-9]{1,2}\/([0-9][0-9]){1,2}\$/)) {
|
|
||||||
validationError(_CURRENT_FORM.elements[fieldName+'[day]'],"$error","validation",false);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
JS;
|
|
||||||
Requirements :: customScript($jsFunc, 'func_validateDMYDate_'.$formID);
|
|
||||||
|
|
||||||
return <<<JS
|
|
||||||
if(\$('$formID')){
|
|
||||||
if(typeof fromAnOnBlur != 'undefined'){
|
|
||||||
if(fromAnOnBlur.name == '$this->name')
|
|
||||||
\$('$formID').validateDMYDate('$this->name');
|
|
||||||
}else{
|
|
||||||
\$('$formID').validateDMYDate('$this->name');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JS;
|
|
||||||
} else {
|
|
||||||
$error = _t('DateField.VALIDATIONJS', 'Please enter a valid date format (DD/MM/YYYY).');
|
|
||||||
$jsFunc =<<<JS
|
|
||||||
Behaviour.register({
|
|
||||||
"#$formID": {
|
|
||||||
validateDate: function(fieldName) {
|
|
||||||
|
|
||||||
var el = _CURRENT_FORM.elements[fieldName];
|
|
||||||
if(el)
|
|
||||||
var value = \$F(el);
|
|
||||||
|
|
||||||
if(Element.hasClassName(el, 'dmydate')) {
|
|
||||||
// dmy triple field validation
|
|
||||||
var day_value = \$F(_CURRENT_FORM.elements[fieldName+'[day]']);
|
|
||||||
var month_value = \$F(_CURRENT_FORM.elements[fieldName+'[month]']);
|
|
||||||
var year_value = \$F(_CURRENT_FORM.elements[fieldName+'[year]']);
|
|
||||||
|
|
||||||
// TODO NZ specific
|
|
||||||
var value = day_value + '/' + month_value + '/' + year_value;
|
|
||||||
if(value && value.length > 0 && !value.match(/^[0-9]{1,2}\/[0-9]{1,2}\/([0-9][0-9]){1,2}\$/)) {
|
|
||||||
validationError(_CURRENT_FORM.elements[fieldName+'[day]'],"$error","validation",false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// single field validation
|
|
||||||
if(value && value.length > 0 && !value.match(/^[0-9]{1,2}\/[0-9]{1,2}\/[0-90-9]{2,4}\$/)) {
|
|
||||||
validationError(el,"$error","validation",false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
JS;
|
|
||||||
Requirements :: customScript($jsFunc, 'func_validateDate_'.$formID);
|
|
||||||
|
|
||||||
return <<<JS
|
|
||||||
if(\$('$formID')){
|
|
||||||
if(typeof fromAnOnBlur != 'undefined'){
|
|
||||||
if(fromAnOnBlur.name == '$this->name')
|
|
||||||
\$('$formID').validateDate('$this->name');
|
|
||||||
}else{
|
|
||||||
\$('$formID').validateDate('$this->name');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate an array with expected keys 'day', 'month' and 'year.
|
* Validate an array with expected keys 'day', 'month' and 'year.
|
||||||
* Used because Zend_Date::isDate() doesn't provide this.
|
* Used because Zend_Date::isDate() doesn't provide this.
|
||||||
@ -538,10 +440,6 @@ class DateField_Disabled extends DateField {
|
|||||||
return "date_disabled readonly";
|
return "date_disabled readonly";
|
||||||
}
|
}
|
||||||
|
|
||||||
function jsValidation() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate($validator) {
|
function validate($validator) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -269,10 +269,6 @@ class DatetimeField extends FormField {
|
|||||||
return ($dateValid && $timeValid);
|
return ($dateValid && $timeValid);
|
||||||
}
|
}
|
||||||
|
|
||||||
function jsValidation() {
|
|
||||||
return $this->dateField->jsValidation() . $this->timeField->jsValidation();
|
|
||||||
}
|
|
||||||
|
|
||||||
function performReadonlyTransformation() {
|
function performReadonlyTransformation() {
|
||||||
$field = new DatetimeField_Readonly($this->name, $this->title, $this->dataValue());
|
$field = new DatetimeField_Readonly($this->name, $this->title, $this->dataValue());
|
||||||
$field->setForm($this->form);
|
$field->setForm($this->form);
|
||||||
@ -314,10 +310,6 @@ class DatetimeField_Readonly extends DatetimeField {
|
|||||||
return "<span class=\"readonly\" id=\"" . $this->id() . "\">$val</span>";
|
return "<span class=\"readonly\" id=\"" . $this->id() . "\">$val</span>";
|
||||||
}
|
}
|
||||||
|
|
||||||
function jsValidation() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate($validator) {
|
function validate($validator) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -10,40 +10,6 @@ class EmailField extends TextField {
|
|||||||
return 'email text';
|
return 'email text';
|
||||||
}
|
}
|
||||||
|
|
||||||
function jsValidation() {
|
|
||||||
$formID = $this->form->FormName();
|
|
||||||
$error = _t('EmailField.VALIDATIONJS', 'Please enter an email address.');
|
|
||||||
$jsFunc =<<<JS
|
|
||||||
Behaviour.register({
|
|
||||||
"#$formID": {
|
|
||||||
validateEmailField: function(fieldName) {
|
|
||||||
var el = _CURRENT_FORM.elements[fieldName];
|
|
||||||
if(!el || !el.value) return true;
|
|
||||||
|
|
||||||
if(el.value.match(/^[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
validationError(el, "$error","validation");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
JS;
|
|
||||||
//fix for the problem with more than one form on a page.
|
|
||||||
Requirements::customScript($jsFunc, 'func_validateEmailField' .'_' . $formID);
|
|
||||||
|
|
||||||
//return "\$('$formID').validateEmailField('$this->name');";
|
|
||||||
return <<<JS
|
|
||||||
if(typeof fromAnOnBlur != 'undefined'){
|
|
||||||
if(fromAnOnBlur.name == '$this->name')
|
|
||||||
$('$formID').validateEmailField('$this->name');
|
|
||||||
}else{
|
|
||||||
$('$formID').validateEmailField('$this->name');
|
|
||||||
}
|
|
||||||
JS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates for RFC 2822 compliant email adresses.
|
* Validates for RFC 2822 compliant email adresses.
|
||||||
*
|
*
|
||||||
|
@ -169,21 +169,6 @@ HTML;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This allows fields within this fieldgroup to still allow them to get valuated.
|
|
||||||
*/
|
|
||||||
function jsValidation(){
|
|
||||||
$fs = $this->FieldList();
|
|
||||||
$validationCode = '';
|
|
||||||
|
|
||||||
foreach($fs as $subfield) {
|
|
||||||
if($value = $subfield->jsValidation()) {
|
|
||||||
$validationCode .= $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $validationCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
function php($data){
|
function php($data){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -127,14 +127,6 @@ class Form extends RequestHandler {
|
|||||||
*/
|
*/
|
||||||
protected $securityToken = null;
|
protected $securityToken = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* HACK This is a temporary hack to allow multiple calls to includeJavascriptValidation on
|
|
||||||
* the validator (if one is present).
|
|
||||||
*
|
|
||||||
* @var boolean
|
|
||||||
*/
|
|
||||||
public $jsValidationIncluded = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array $extraClasses List of additional CSS classes for the form tag.
|
* @var array $extraClasses List of additional CSS classes for the form tag.
|
||||||
*/
|
*/
|
||||||
@ -324,23 +316,19 @@ class Form extends RequestHandler {
|
|||||||
if(!$this->validate()) {
|
if(!$this->validate()) {
|
||||||
if(Director::is_ajax()) {
|
if(Director::is_ajax()) {
|
||||||
// Special case for legacy Validator.js implementation (assumes eval'ed javascript collected through FormResponse)
|
// Special case for legacy Validator.js implementation (assumes eval'ed javascript collected through FormResponse)
|
||||||
if($this->validator->getJavascriptValidationHandler() == 'prototype') {
|
$acceptType = $request->getHeader('Accept');
|
||||||
return FormResponse::respond();
|
if(strpos($acceptType, 'application/json') !== FALSE) {
|
||||||
|
// Send validation errors back as JSON with a flag at the start
|
||||||
|
$response = new SS_HTTPResponse(Convert::array2json($this->validator->getErrors()));
|
||||||
|
$response->addHeader('Content-Type', 'application/json');
|
||||||
} else {
|
} else {
|
||||||
$acceptType = $request->getHeader('Accept');
|
$this->setupFormErrors();
|
||||||
if(strpos($acceptType, 'application/json') !== FALSE) {
|
// Send the newly rendered form tag as HTML
|
||||||
// Send validation errors back as JSON with a flag at the start
|
$response = new SS_HTTPResponse($this->forTemplate());
|
||||||
$response = new SS_HTTPResponse(Convert::array2json($this->validator->getErrors()));
|
$response->addHeader('Content-Type', 'text/html');
|
||||||
$response->addHeader('Content-Type', 'application/json');
|
|
||||||
} else {
|
|
||||||
$this->setupFormErrors();
|
|
||||||
// Send the newly rendered form tag as HTML
|
|
||||||
$response = new SS_HTTPResponse($this->forTemplate());
|
|
||||||
$response->addHeader('Content-Type', 'text/html');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $response;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
} else {
|
} else {
|
||||||
if($this->getRedirectToFormOnValidationError()) {
|
if($this->getRedirectToFormOnValidationError()) {
|
||||||
if($pageURL = $request->getHeader('Referer')) {
|
if($pageURL = $request->getHeader('Referer')) {
|
||||||
@ -697,9 +685,6 @@ class Form extends RequestHandler {
|
|||||||
// Forms shouldn't be cached, cos their error messages won't be shown
|
// Forms shouldn't be cached, cos their error messages won't be shown
|
||||||
HTTP::set_cache_age(0);
|
HTTP::set_cache_age(0);
|
||||||
|
|
||||||
// workaround to include javascript validation
|
|
||||||
if($this->validator && !$this->jsValidationIncluded) $this->validator->includeJavascriptValidation();
|
|
||||||
|
|
||||||
$attrs = $this->getAttributes();
|
$attrs = $this->getAttributes();
|
||||||
|
|
||||||
// Remove empty
|
// Remove empty
|
||||||
@ -1259,10 +1244,6 @@ class Form extends RequestHandler {
|
|||||||
* the attributes of the form. These fields can be used to send the form to Ajax.
|
* the attributes of the form. These fields can be used to send the form to Ajax.
|
||||||
*/
|
*/
|
||||||
function formHtmlContent() {
|
function formHtmlContent() {
|
||||||
// Call FormAttributes to force inclusion of custom client-side validation of fields
|
|
||||||
// because it won't be included by the template
|
|
||||||
if($this->validator && !$this->jsValidationIncluded) $this->validator->includeJavascriptValidation();
|
|
||||||
|
|
||||||
$this->IncludeFormTag = false;
|
$this->IncludeFormTag = false;
|
||||||
$content = $this->forTemplate();
|
$content = $this->forTemplate();
|
||||||
$this->IncludeFormTag = true;
|
$this->IncludeFormTag = true;
|
||||||
|
@ -663,15 +663,6 @@ class FormField extends RequestHandler {
|
|||||||
else return "<$tag$preparedAttributes />";
|
else return "<$tag$preparedAttributes />";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* javascript handler Functions for each field type by default
|
|
||||||
* formfield doesnt have a validation function
|
|
||||||
*
|
|
||||||
* @todo shouldn't this be an abstract method?
|
|
||||||
*/
|
|
||||||
function jsValidation() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validation Functions for each field type by default
|
* Validation Functions for each field type by default
|
||||||
* formfield doesnt have a validation function
|
* formfield doesnt have a validation function
|
||||||
|
@ -18,40 +18,6 @@ class NumericField extends TextField{
|
|||||||
return 'numeric text';
|
return 'numeric text';
|
||||||
}
|
}
|
||||||
|
|
||||||
function jsValidation() {
|
|
||||||
$formID = $this->form->FormName();
|
|
||||||
$error = _t('NumericField.VALIDATIONJS', 'is not a number, only numbers can be accepted for this field');
|
|
||||||
$jsFunc =<<<JS
|
|
||||||
Behaviour.register({
|
|
||||||
"#$formID": {
|
|
||||||
validateNumericField: function(fieldName) {
|
|
||||||
el = _CURRENT_FORM.elements[fieldName];
|
|
||||||
if(!el || !el.value) return true;
|
|
||||||
|
|
||||||
if(!isNaN(el.value)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
validationError(el, "'" + el.value + "' $error","validation");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
JS;
|
|
||||||
|
|
||||||
Requirements::customScript($jsFunc, 'func_validateNumericField');
|
|
||||||
|
|
||||||
//return "\$('$formID').validateNumericField('$this->name');";
|
|
||||||
return <<<JS
|
|
||||||
if(typeof fromAnOnBlur != 'undefined'){
|
|
||||||
if(fromAnOnBlur.name == '$this->name')
|
|
||||||
$('$formID').validateNumericField('$this->name');
|
|
||||||
}else{
|
|
||||||
$('$formID').validateNumericField('$this->name');
|
|
||||||
}
|
|
||||||
JS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** PHP Validation **/
|
/** PHP Validation **/
|
||||||
function validate($validator){
|
function validate($validator){
|
||||||
if($this->value && !is_numeric(trim($this->value))){
|
if($this->value && !is_numeric(trim($this->value))){
|
||||||
|
@ -124,51 +124,6 @@ class PhoneNumberField extends FormField {
|
|||||||
$record->$fieldName = $completeNumber;
|
$record->$fieldName = $completeNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @todo Very basic validation at the moment
|
|
||||||
*/
|
|
||||||
function jsValidation() {
|
|
||||||
$formID = $this->form->FormName();
|
|
||||||
|
|
||||||
$jsFunc =<<<JS
|
|
||||||
Behaviour.register({
|
|
||||||
"#$formID": {
|
|
||||||
validatePhoneNumber: function(fieldName) {
|
|
||||||
if(!$(fieldName + "_Holder")) return true;
|
|
||||||
|
|
||||||
// Phonenumbers are split into multiple values, so get the inputs from the form.
|
|
||||||
var parts = $(fieldName + "_Holder").getElementsByTagName('input');
|
|
||||||
var isNull = true;
|
|
||||||
|
|
||||||
// we're not validating empty fields (done by requiredfields)
|
|
||||||
for(i=0; i < parts.length ; i++ ) {
|
|
||||||
isNull = (parts[i].value == null || parts[i].value == "") ? isNull && true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!isNull) {
|
|
||||||
// Concatenate the string values from the parts of the input.
|
|
||||||
var joinedNumber = "";
|
|
||||||
for(i=0; i < parts.length; i++) joinedNumber += parts[i].value;
|
|
||||||
if(!joinedNumber.match(/^[0-9\+\-\(\)\s\#]*\$/)) {
|
|
||||||
// TODO Find a way to mark multiple error fields
|
|
||||||
validationError(
|
|
||||||
fieldName+"-Number",
|
|
||||||
"Please enter a valid phone number",
|
|
||||||
"validation",
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
JS;
|
|
||||||
Requirements :: customScript($jsFunc, 'func_validatePhoneNumber');
|
|
||||||
|
|
||||||
return "\$('$formID').validatePhoneNumber('$this->name');";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @todo Very basic validation at the moment
|
* @todo Very basic validation at the moment
|
||||||
*/
|
*/
|
||||||
|
@ -53,39 +53,6 @@ class RequiredFields extends Validator {
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function javascript() {
|
|
||||||
$js = "";
|
|
||||||
$fields = $this->form->Fields();
|
|
||||||
$dataFields = $this->form->Fields()->dataFields();
|
|
||||||
if($dataFields) {
|
|
||||||
foreach($dataFields as $field) {
|
|
||||||
// if the field type has some special specific specification for validation of itself
|
|
||||||
$validationFunc = $field->jsValidation();
|
|
||||||
if($validationFunc) $js .= $validationFunc . "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$useLabels = $this->useLabels ? 'true' : 'false';
|
|
||||||
|
|
||||||
if($this->required) {
|
|
||||||
foreach($this->required as $field) {
|
|
||||||
if($fields->dataFieldByName($field)) {
|
|
||||||
//$js .= "\t\t\t\t\trequire('$field', false, $useLabels);\n";
|
|
||||||
$js .= <<<JS
|
|
||||||
if(typeof fromAnOnBlur != 'undefined'){\n
|
|
||||||
if(fromAnOnBlur.name == '$field')\n
|
|
||||||
require(fromAnOnBlur);\n
|
|
||||||
}else{
|
|
||||||
require('$field');
|
|
||||||
}
|
|
||||||
JS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $js;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows validation of fields via specification of a php function for validation which is executed after
|
* Allows validation of fields via specification of a php function for validation which is executed after
|
||||||
* the form is submitted
|
* the form is submitted
|
||||||
|
@ -484,41 +484,6 @@ class TableField extends TableListField {
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
function jsValidation() {
|
|
||||||
$js = "";
|
|
||||||
|
|
||||||
$items = $this->Items();
|
|
||||||
if($items) foreach($items as $item) {
|
|
||||||
foreach($item->Fields() as $field) {
|
|
||||||
//if the field type has some special specific specification for validation of itself
|
|
||||||
$js .= $field->jsValidation($this->form->class."_".$this->form->Name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Implement custom requiredFields
|
|
||||||
$items = $this->sourceItems();
|
|
||||||
if($items && $this->requiredFields && $items->count()) {
|
|
||||||
foreach ($this->requiredFields as $field) {
|
|
||||||
foreach($items as $item){
|
|
||||||
$cellName = $this->getName().'['.$item->ID.']['.$field.']';
|
|
||||||
$js .= "\n";
|
|
||||||
if($fields->dataFieldByName($cellName)) {
|
|
||||||
$js .= <<<JS
|
|
||||||
if(typeof fromAnOnBlur != 'undefined'){
|
|
||||||
if(fromAnOnBlur.name == '$cellName')
|
|
||||||
require(fromAnOnBlur);
|
|
||||||
}else{
|
|
||||||
require('$cellName');
|
|
||||||
}
|
|
||||||
JS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $js;
|
|
||||||
}
|
|
||||||
|
|
||||||
function php($data) {
|
function php($data) {
|
||||||
$valid = true;
|
$valid = true;
|
||||||
|
|
||||||
|
@ -217,10 +217,6 @@ class TimeField_Readonly extends TimeField {
|
|||||||
return "<span class=\"readonly\" id=\"" . $this->id() . "\">$val</span>";
|
return "<span class=\"readonly\" id=\"" . $this->id() . "\">$val</span>";
|
||||||
}
|
}
|
||||||
|
|
||||||
function jsValidation() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate($validator) {
|
function validate($validator) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -26,60 +26,24 @@ abstract class Validator extends Object {
|
|||||||
protected $errors;
|
protected $errors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static for default value of $this->javascriptValidationHandler.
|
* @deprecated 3.0 Use custom javascript validation instead
|
||||||
* Set with Validator::set_javascript_validation_handler();
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected static $javascript_validation_handler = "prototype";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for javascript validation. Can be "prototype" or "none".
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $javascriptValidationHandler = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call this function to set the javascript validation handler for all valdiation on your site.
|
|
||||||
* This could be called from _config.php to set site-wide javascript validation, or from Controller::init()
|
|
||||||
* to affect only the front-end site.
|
|
||||||
* Use instance method {@link setJavascriptValidationHandler()} to
|
|
||||||
* only set handler for a specific form instance.
|
|
||||||
*
|
|
||||||
* @param $handler A string representing the handler to use: 'prototype' or 'none'.
|
|
||||||
* @todo Add 'jquery' as a handler option.
|
|
||||||
*/
|
*/
|
||||||
public static function set_javascript_validation_handler($handler) {
|
public static function set_javascript_validation_handler($handler) {
|
||||||
if($handler == 'prototype' || $handler == 'none') {
|
Deprecation::notice('3.0', 'Use custom javascript validation instead.');
|
||||||
self::$javascript_validation_handler = $handler;
|
|
||||||
} else {
|
|
||||||
user_error("Validator::setJavascriptValidationHandler() passed bad handler '$handler'", E_USER_WARNING);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns global validation handler used for all forms by default,
|
* @deprecated 3.0 Use custom javascript validation instead
|
||||||
* unless overwritten by {@link setJavascriptValidationHandler()}.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public static function get_javascript_validator_handler() {
|
public static function get_javascript_validator_handler() {
|
||||||
return self::$javascript_validation_handler;
|
Deprecation::notice('3.0', 'Use custom javascript validation instead.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set JavaScript validation for this validator.
|
* @deprecated 3.0 Use custom javascript validation instead
|
||||||
* Use static method {@link set_javascript_validation_handler()}
|
|
||||||
* to set handlers globally.
|
|
||||||
*
|
|
||||||
* @param string $handler
|
|
||||||
*/
|
*/
|
||||||
public function setJavascriptValidationHandler($handler) {
|
public function setJavascriptValidationHandler($handler) {
|
||||||
if($handler == 'prototype' || $handler == 'none') {
|
Deprecation::notice('3.0', 'Use custom javascript validation instead.');
|
||||||
$this->javascriptValidationHandler = $handler;
|
|
||||||
} else {
|
|
||||||
user_error("Validator::setJavascriptValidationHandler() passed bad handler '$handler'", E_USER_WARNING);
|
|
||||||
}
|
|
||||||
return $this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,7 +53,7 @@ abstract class Validator extends Object {
|
|||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getJavascriptValidationHandler() {
|
public function getJavascriptValidationHandler() {
|
||||||
return ($this->javascriptValidationHandler) ? $this->javascriptValidationHandler : self::$javascript_validation_handler;
|
Deprecation::notice('3.0', 'Use custom javascript validation instead.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -106,7 +70,6 @@ abstract class Validator extends Object {
|
|||||||
function validate(){
|
function validate(){
|
||||||
$this->errors = null;
|
$this->errors = null;
|
||||||
$this->php($this->form->getData());
|
$this->php($this->form->getData());
|
||||||
|
|
||||||
return $this->errors;
|
return $this->errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,78 +112,6 @@ abstract class Validator extends Object {
|
|||||||
}else if(!strlen($data[$fieldName])) $this->validationError($fieldName, "$fieldName is required.", "required");
|
}else if(!strlen($data[$fieldName])) $this->validationError($fieldName, "$fieldName is required.", "required");
|
||||||
}
|
}
|
||||||
|
|
||||||
function includeJavascriptValidation() {
|
|
||||||
if($this->getJavascriptValidationHandler() == 'prototype') {
|
|
||||||
Requirements::javascript(SAPPHIRE_DIR . "/thirdparty/prototype/prototype.js");
|
|
||||||
Requirements::javascript(SAPPHIRE_DIR . "/thirdparty/behaviour/behaviour.js");
|
|
||||||
Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang');
|
|
||||||
Requirements::javascript(SAPPHIRE_DIR . "/javascript/Validator.js");
|
|
||||||
|
|
||||||
$code = $this->javascript();
|
|
||||||
$formID = $this->form->FormName();
|
|
||||||
$js = <<<JS
|
|
||||||
Behaviour.register({
|
|
||||||
'#$formID': {
|
|
||||||
validate : function(fromAnOnBlur) {
|
|
||||||
initialiseForm(this, fromAnOnBlur);
|
|
||||||
$code
|
|
||||||
|
|
||||||
var error = hasHadFormError();
|
|
||||||
if(!error && fromAnOnBlur) clearErrorMessage(fromAnOnBlur);
|
|
||||||
if(error && !fromAnOnBlur) focusOnFirstErroredField();
|
|
||||||
|
|
||||||
return !error;
|
|
||||||
},
|
|
||||||
onsubmit : function() {
|
|
||||||
if(typeof this.bypassValidation == 'undefined' || !this.bypassValidation) return this.validate();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'#$formID input' : {
|
|
||||||
initialise: function() {
|
|
||||||
if(!this.old_onblur) this.old_onblur = function() { return true; }
|
|
||||||
if(!this.old_onfocus) this.old_onfocus = function() { return true; }
|
|
||||||
},
|
|
||||||
onblur : function() {
|
|
||||||
if(this.old_onblur()) {
|
|
||||||
// Don't perform instant validation for CalendarDateField fields; it creates usability wierdness.
|
|
||||||
if(this.parentNode.className.indexOf('calendardate') == -1 || this.value) {
|
|
||||||
return $('$formID').validate(this);
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'#$formID textarea' : {
|
|
||||||
initialise: function() {
|
|
||||||
if(!this.old_onblur) this.old_onblur = function() { return true; }
|
|
||||||
if(!this.old_onfocus) this.old_onfocus = function() { return true; }
|
|
||||||
},
|
|
||||||
onblur : function() {
|
|
||||||
if(this.old_onblur()) {
|
|
||||||
return $('$formID').validate(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'#$formID select' : {
|
|
||||||
initialise: function() {
|
|
||||||
if(!this.old_onblur) this.old_onblur = function() { return true; }
|
|
||||||
},
|
|
||||||
onblur : function() {
|
|
||||||
if(this.old_onblur()) {
|
|
||||||
return $('$formID').validate(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
JS;
|
|
||||||
|
|
||||||
Requirements::customScript($js);
|
|
||||||
// HACK Notify the form that the validators client-side validation code has already been included
|
|
||||||
if($this->form) $this->form->jsValidationIncluded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the named field is "required".
|
* Returns true if the named field is "required".
|
||||||
* Used by FormField to return a value for FormField::Required(), to do things like show *s on the form template.
|
* Used by FormField to return a value for FormField::Required(), to do things like show *s on the form template.
|
||||||
@ -230,8 +121,6 @@ JS;
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract function javascript();
|
|
||||||
|
|
||||||
abstract function php($data);
|
abstract function php($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,316 +0,0 @@
|
|||||||
// Shortcut-function (until we update to Prototye v1.5)
|
|
||||||
if(typeof $$ != "Function") $$ = document.getElementsBySelector;
|
|
||||||
|
|
||||||
var _CURRENT_FORM;
|
|
||||||
var _FIRST_ERRORED_FIELD = null;
|
|
||||||
var _VALIDATIONS_REF = new Array();
|
|
||||||
|
|
||||||
function initialiseForm(form, fromAnOnBlur) {
|
|
||||||
_CURRENT_FORM = form;
|
|
||||||
_FIRST_ERRORED_FIELD = null;
|
|
||||||
|
|
||||||
if(fromAnOnBlur) {
|
|
||||||
limitValidationErrorsTo(fromAnOnBlur);
|
|
||||||
} else {
|
|
||||||
clearValidationErrorLimit();
|
|
||||||
}
|
|
||||||
|
|
||||||
_HAS_HAD_FORM_ERROR = false;
|
|
||||||
clearValidationErrorCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
function hasHadFormError() {
|
|
||||||
return _HAS_HAD_FORM_ERROR || !_ERROR_CACHE;
|
|
||||||
}
|
|
||||||
|
|
||||||
function focusOnFirstErroredField() {
|
|
||||||
try {
|
|
||||||
_FIRST_ERRORED_FIELD.focus();
|
|
||||||
} catch(er) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns group with the correct classname
|
|
||||||
*/
|
|
||||||
function findIndexOf(group,index) {
|
|
||||||
var i;
|
|
||||||
for(i = 0; i < group.length; i++) {
|
|
||||||
if(group[i].className.indexOf(index) > -1) {
|
|
||||||
return group[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearErrorMessage(holderDiv){
|
|
||||||
//merged by nlou 23/08/2007, r#40674
|
|
||||||
if(holderDiv.tagName == 'TD'){//for tablefield.
|
|
||||||
$$('span.message', holderDiv).each(function(el){
|
|
||||||
Element.hide(el);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}else{
|
|
||||||
$$('span.message', holderDiv.parentNode).each(function(el) {
|
|
||||||
Element.hide(el);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
$$('div.validationError', holderDiv.parentNode).each(function(el) {
|
|
||||||
Element.removeClassName(el,'validationError');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearAllErrorMessages() {
|
|
||||||
$$('span.message').each(function(el) {
|
|
||||||
Element.hide(el);
|
|
||||||
});
|
|
||||||
$$('div.validationError').each(function(el) {
|
|
||||||
Element.removeClassName(el,'validationError');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function require(fieldName,cachedError) {
|
|
||||||
el = _CURRENT_FORM.elements[fieldName];
|
|
||||||
|
|
||||||
// see if the field is an optionset
|
|
||||||
if(el == null) {
|
|
||||||
|
|
||||||
var descendants = _CURRENT_FORM.getElementsByTagName('*');
|
|
||||||
|
|
||||||
el = document.getElementById(fieldName);
|
|
||||||
|
|
||||||
if(el == null)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if(Element.hasClassName(el, 'optionset')) {
|
|
||||||
el.type = 'optionset';
|
|
||||||
|
|
||||||
var options = el.getElementsByTagName('input');
|
|
||||||
|
|
||||||
for(var i = 0; i < options.length; i++) {
|
|
||||||
if(options[i].checked)
|
|
||||||
if(el.value != null)
|
|
||||||
el.value += ',' + options[i].value;
|
|
||||||
else
|
|
||||||
el.value = options[i].value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(el != null) {
|
|
||||||
// Sets up radio and checkbox validation
|
|
||||||
if(el.type == 'checkbox' || el.type == 'radio') {
|
|
||||||
var set = el.checked;
|
|
||||||
}//merged by nlou 23/08/2007, r#40674
|
|
||||||
else if(el.type == 'select-one'){
|
|
||||||
if(el.value == ''||el.value == '0'){
|
|
||||||
var set = '';
|
|
||||||
}else{
|
|
||||||
var set = el.value;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
var set = el.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
var baseEl;
|
|
||||||
var fieldHolder = el;
|
|
||||||
|
|
||||||
// Sometimes require events are triggered of
|
|
||||||
// associative elements like labels ;-p
|
|
||||||
if(el.type) {
|
|
||||||
if(el.parentNode.className.indexOf('form') != -1) set = true;
|
|
||||||
baseEl = el;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if(_CURRENT_FORM.elements[fieldName]) {
|
|
||||||
//Some elements are nested and need to be "got"
|
|
||||||
var i, hasValue = false;
|
|
||||||
if(_CURRENT_FORM.elements[fieldName].length > 1) {
|
|
||||||
for(i=0; i < el.length; i++) {
|
|
||||||
if(el[i].checked && el[i].value) {
|
|
||||||
hasValue = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hasValue) set = true;
|
|
||||||
else set = "";
|
|
||||||
baseEl = el[0].parentNode.parentNode;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
set = "";
|
|
||||||
baseEl = el.parentNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
set = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This checks to see if the input has a value, and the field is not a readonly.
|
|
||||||
if( ( typeof set == 'undefined' || (typeof(set) == 'string' && set.match(/^\s*$/)) ) ) {
|
|
||||||
//fieldgroup validation
|
|
||||||
var fieldLabel = findParentLabel(baseEl);
|
|
||||||
|
|
||||||
// Some fields do-not have labels, in
|
|
||||||
// which case we need a blank one
|
|
||||||
if(fieldLabel == null || fieldLabel == "") {
|
|
||||||
fieldlabel = "this field";
|
|
||||||
}
|
|
||||||
|
|
||||||
var errorMessage = ss.i18n.sprintf(ss.i18n._t('VALIDATOR.FIELDREQUIRED', 'Please fill out "%s", it is required.'), fieldLabel);
|
|
||||||
if(baseEl.requiredErrorMsg) errorMessage = baseEl.requiredErrorMsg;
|
|
||||||
else if(_CURRENT_FORM.requiredErrorMsg) errorMessage = _CURRENT_FORM.requiredErrorMsg;
|
|
||||||
|
|
||||||
validationError(baseEl, errorMessage.replace('$FieldLabel', fieldLabel),"required",cachedError);
|
|
||||||
return false;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if(!hasHadFormError()) {
|
|
||||||
if(baseEl) fieldHolder = baseEl.parentNode;
|
|
||||||
clearErrorMessage(fieldHolder);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the label of the blockset which contains the classname left
|
|
||||||
*/
|
|
||||||
function findParentLabel(el) {
|
|
||||||
// If the el's type is HTML then were at the uppermost parent, so return
|
|
||||||
// null. its handled by the validator function anyway :-)
|
|
||||||
if(el) {
|
|
||||||
if(el.className == "undefined") {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
if(el.className) {
|
|
||||||
if(el.className.indexOf('field') == 0) {
|
|
||||||
labels = el.getElementsByTagName('label');
|
|
||||||
if(labels){
|
|
||||||
var left = findIndexOf(labels,'left');
|
|
||||||
var right = findIndexOf(labels,'right');
|
|
||||||
if(left) {
|
|
||||||
return strip_tags(left.innerHTML);
|
|
||||||
} else if(right) {
|
|
||||||
return strip_tags(right.innerHTML);
|
|
||||||
} else {
|
|
||||||
return findParentLabel(el.parentNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}//merged by nlou 23/08/2007, r#40674
|
|
||||||
else if(el.className.indexOf('tablecolumn') != -1){
|
|
||||||
return el.className.substring(0, el.className.indexOf('tablecolumn')-1);
|
|
||||||
}else{
|
|
||||||
return findParentLabel(el.parentNode);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Try to find a label with a for value of this field.
|
|
||||||
if(el.id) {
|
|
||||||
var labels = $$('label[for=' + el.id + ']');
|
|
||||||
if(labels && labels.length > 0) return labels[0].innerHTML;
|
|
||||||
}
|
|
||||||
|
|
||||||
return findParentLabel(el.parentNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// backup
|
|
||||||
return "this";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a validation error to an element
|
|
||||||
*/
|
|
||||||
function validationError(field,message, messageClass, cacheError) {
|
|
||||||
if(typeof(field) == 'string') {
|
|
||||||
field = document.getElementById(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(cacheError) {
|
|
||||||
_ERROR_CACHE[_ERROR_CACHE.length] = {
|
|
||||||
"field": field,
|
|
||||||
"message": message,
|
|
||||||
"messageClass": messageClass
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The validation function should only be called if you've just left a field,
|
|
||||||
// or the field is being validated on final submission
|
|
||||||
if(_LIMIT_VALIDATION_ERRORS && _LIMIT_VALIDATION_ERRORS != field) {
|
|
||||||
// clearErrorMessage(field.parentNode);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_HAS_HAD_FORM_ERROR = true;
|
|
||||||
|
|
||||||
// See if the tag has a reference to the validationMessage (quicker than the one below)
|
|
||||||
var validationMessage = (typeof(_VALIDATIONS_REF[field.id]) != 'undefined')? _VALIDATIONS_REF[field.id] : null;
|
|
||||||
|
|
||||||
// Cycle through the elements to see if it has a span
|
|
||||||
// (for a validation or required messages)
|
|
||||||
if(!validationMessage) {
|
|
||||||
|
|
||||||
//Get the parent holder of the element
|
|
||||||
var FieldHolder = field.parentNode;
|
|
||||||
var allSpans = FieldHolder.getElementsByTagName('span');
|
|
||||||
validationMessage = findIndexOf(allSpans,'message');
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we didn't find it, create it
|
|
||||||
if(!validationMessage) {
|
|
||||||
validationMessage = document.createElement('span');
|
|
||||||
FieldHolder.appendChild(validationMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep a reference to it
|
|
||||||
_VALIDATIONS_REF[field.id] = validationMessage;
|
|
||||||
|
|
||||||
// Keep a reference to the first errored field
|
|
||||||
if(field && !_FIRST_ERRORED_FIELD) _FIRST_ERRORED_FIELD = field;
|
|
||||||
|
|
||||||
// Set the attributes
|
|
||||||
validationMessage.className = "message " + messageClass;
|
|
||||||
validationMessage.innerHTML = message;
|
|
||||||
validationMessage.style.display = "block";
|
|
||||||
|
|
||||||
// Set Classname on holder
|
|
||||||
var holder = document.getParentOfElement(field,'div','field');
|
|
||||||
Element.addClassName(holder, 'validationError');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a limitation so that only validation errors for the given element will actually be shown
|
|
||||||
*/
|
|
||||||
|
|
||||||
var _LIMIT_VALIDATION_ERRORS = null;
|
|
||||||
function limitValidationErrorsTo(field) {
|
|
||||||
_LIMIT_VALIDATION_ERRORS = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearValidationErrorLimit() {
|
|
||||||
_LIMIT_VALIDATION_ERRORS = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearValidationErrorCache() {
|
|
||||||
_ERROR_CACHE = new Array();
|
|
||||||
}
|
|
||||||
|
|
||||||
function showCachedValidationErrors() {
|
|
||||||
for(i = 0; i < _ERROR_CACHE.length; i++) {
|
|
||||||
validationError(_ERROR_CACHE[i]["field"],
|
|
||||||
_ERROR_CACHE[i]["message"],
|
|
||||||
_ERROR_CACHE[i]["messageClass"],
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function strip_tags(text) {
|
|
||||||
return text.replace(/<[^>]+>/g,'');
|
|
||||||
}
|
|
@ -1772,27 +1772,4 @@ class Member_Validator extends RequiredFields {
|
|||||||
return $valid;
|
return $valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the submitted member data is valid (client-side)
|
|
||||||
*
|
|
||||||
* @param array $data Submitted data
|
|
||||||
* @return bool Returns TRUE if the submitted data is valid, otherwise
|
|
||||||
* FALSE.
|
|
||||||
*/
|
|
||||||
function javascript() {
|
|
||||||
$js = parent::javascript();
|
|
||||||
|
|
||||||
// Execute the validators on the extensions
|
|
||||||
if($this->extension_instances) {
|
|
||||||
foreach($this->extension_instances as $extension) {
|
|
||||||
if(method_exists($extension, 'hasMethod') && $extension->hasMethod('updateJavascript')) {
|
|
||||||
$extension->updateJavascript($js, $this->form);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $js;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -90,16 +90,13 @@ class MemberLoginForm extends LoginForm {
|
|||||||
parent::__construct($controller, $name, $fields, $actions);
|
parent::__construct($controller, $name, $fields, $actions);
|
||||||
|
|
||||||
// Focus on the email input when the page is loaded
|
// Focus on the email input when the page is loaded
|
||||||
// Only include this if other form JS validation is enabled
|
Requirements::customScript(<<<JS
|
||||||
if($this->getValidator()->getJavascriptValidationHandler() != 'none') {
|
(function() {
|
||||||
Requirements::customScript(<<<JS
|
var el = document.getElementById("MemberLoginForm_LoginForm_Email");
|
||||||
(function() {
|
if(el && el.focus) el.focus();
|
||||||
var el = document.getElementById("MemberLoginForm_LoginForm_Email");
|
})();
|
||||||
if(el && el.focus) el.focus();
|
|
||||||
})();
|
|
||||||
JS
|
JS
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user