Skip to content

Commit

Permalink
API CHANGE Removed built-in behaviour.js client-side form validation.
Browse files Browse the repository at this point in the history
This is no longer supported. Please use custom client-side validation instead. (see 3.0.0 changelog
for more information)
  • Loading branch information
Sean Harvey committed Mar 8, 2012
1 parent f86e53b commit 9f3344b
Show file tree
Hide file tree
Showing 23 changed files with 66 additions and 1,107 deletions.
7 changes: 0 additions & 7 deletions admin/code/LeftAndMain.php
Expand Up @@ -195,11 +195,6 @@ function init() {
// Audit logging hook
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
HtmlEditorConfig::set_active(Member::currentUser()->getHtmlEditorConfigForCMS());

Expand Down Expand Up @@ -264,7 +259,6 @@ function init() {
SAPPHIRE_DIR . '/javascript/DateField.js',
SAPPHIRE_DIR . '/javascript/HtmlEditorField.js',
SAPPHIRE_DIR . '/javascript/TabSet.js',
SAPPHIRE_DIR . '/javascript/Validator.js',
SAPPHIRE_DIR . '/javascript/i18n.js',
SAPPHIRE_ADMIN_DIR . '/javascript/ssui.core.js',
SAPPHIRE_DIR . '/javascript/GridField.js',
Expand Down Expand Up @@ -913,7 +907,6 @@ public function getEditForm($id = null, $fields = null) {
// The clientside (mainly LeftAndMain*.js) rely on ajax responses
// which can be evaluated as javascript, hence we need
// to override any global changes to the validation handler.
$validator->setJavascriptValidationHandler('prototype');
$form->setValidator($validator);
} else {
$form->unsetValidator();
Expand Down
19 changes: 4 additions & 15 deletions admin/code/ModelAdmin.php
Expand Up @@ -396,16 +396,13 @@ public function SearchForm() {
$fields = $context->getSearchFields();
$columnSelectionField = $this->ColumnSelectionField();
$fields->push($columnSelectionField);
$validator = new RequiredFields();
$validator->setJavascriptValidationHandler('none');


$form = new Form($this, "SearchForm",
$fields,
new FieldList(
new FormAction('search', _t('MemberTableField.SEARCH', 'Search')),
$clearAction = new ResetFormAction('clearsearch', _t('ModelAdmin.CLEAR_SEARCH','Clear Search'))
),
$validator
)
);
//$form->setFormAction(Controller::join_links($this->Link(), "search"));
$form->setFormMethod('get');
Expand Down Expand Up @@ -437,11 +434,9 @@ public function CreateForm() {
new FieldList(
$createButton = FormAction::create('add', $buttonLabel)
->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'accept')
),
$validator = new RequiredFields()
)
);
$createButton->dontEscape = true;
$validator->setJavascriptValidationHandler('none');
$form->setHTMLID("Form_CreateForm_" . $this->modelClass);
return $form;
}
Expand Down Expand Up @@ -498,15 +493,11 @@ public function ImportForm() {
new FormAction('import', _t('ModelAdmin.IMPORT', 'Import from CSV'))
);

$validator = new RequiredFields();
$validator->setJavascriptValidationHandler('none');

$form = new Form(
$this,
"ImportForm",
$fields,
$actions,
$validator
$actions
);
$form->setHTMLID("Form_ImportForm_" . $this->modelClass);
return $form;
Expand Down Expand Up @@ -804,7 +795,6 @@ public function AddForm() {

$validator = ($newRecord->hasMethod('getCMSValidator')) ? $newRecord->getCMSValidator() : null;
if(!$validator) $validator = new RequiredFields();
$validator->setJavascriptValidationHandler('none');

$actions = new FieldList (
FormAction::create("doCreate", _t('ModelAdmin.ADDBUTTON', "Add"))
Expand Down Expand Up @@ -922,7 +912,6 @@ public function EditForm() {
}

$validator = ($this->currentRecord->hasMethod('getCMSValidator')) ? $this->currentRecord->getCMSValidator() : new RequiredFields();
$validator->setJavascriptValidationHandler('none');

$actions = $this->currentRecord->getCMSActions();
if($this->currentRecord->canEdit(Member::currentUser())){
Expand Down
34 changes: 34 additions & 0 deletions docs/en/changelogs/3.0.0.md
Expand Up @@ -73,6 +73,40 @@ 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,
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 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 ###

The [api:FormField] API has been refactored to use SilverStripe templates
Expand Down
58 changes: 0 additions & 58 deletions forms/AjaxUniqueTextField.php
Expand Up @@ -34,8 +34,6 @@ function Field() {
Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang');
Requirements::javascript(SAPPHIRE_DIR . "/javascript/UniqueFields.js");

$this->jsValidation();

$url = Convert::raw2att( $this->validateURL );

if($this->restrictedRegex)
Expand All @@ -54,63 +52,7 @@ function Field() {
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 ) {

$result = DB::query(sprintf(
"SELECT COUNT(*) FROM \"%s\" WHERE \"%s\" = '%s'",
$this->restrictedTable,
Expand Down
91 changes: 0 additions & 91 deletions forms/ConfirmedPasswordField.php
Expand Up @@ -203,97 +203,6 @@ function setValue($value) {

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
Expand Down
56 changes: 0 additions & 56 deletions forms/CreditCardField.php
Expand Up @@ -35,62 +35,6 @@ function dataValue() {
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){
// If the field is empty then don't return an invalidation message
if(!trim(implode("", $this->value))) return true;
Expand Down

0 comments on commit 9f3344b

Please sign in to comment.