Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merged revisions 47323 via svnmerge from

svn://svn.silverstripe.com/silverstripe/modules/sapphire/branches/2.2.0-mesq

........
  r47323 | ischommer | 2007-12-19 14:33:29 +1300 (Wed, 19 Dec 2007) | 1 line
  
  documentation, added show-on-click functionality, fixed validation for canBeEmpty
........


git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@47322 467b73ca-7a2a-4603-9d3b-597d59a354a9
  • Loading branch information...
commit ce5becdcfdc5bf1807e0021f754c05df88693c30 1 parent 19da8d0
@chillu chillu authored
Showing with 147 additions and 19 deletions.
  1. +121 −19 forms/ConfirmedPasswordField.php
  2. +26 −0 javascript/ConfirmedPasswordField.js
View
140 forms/ConfirmedPasswordField.php
@@ -1,38 +1,102 @@
<?php
/**
* Shows two password-fields, and checks for matching passwords.
- *
- * TODO readonlytransformation
+ * Optionally hides the fields by default and shows
+ * a link to toggle their visibility.
*/
class ConfirmedPasswordField extends FormField {
+ /**
+ * Minimum character length of the password.
+ *
+ * @var int
+ */
public $minLength = 6;
+ /**
+ * Maximum character length of the password.
+ *
+ * @var int
+ */
public $maxLength = 20;
- public $excludeChars = '\s';
-
+ /**
+ * Enforces at least one digit and one alphanumeric
+ * character (in addition to {$minLength} and {$maxLength}
+ *
+ * @var boolean
+ */
public $requireStrongPassword = false;
+ /**
+ * Allow empty fields in serverside validation
+ *
+ * @var boolean
+ */
public $canBeEmpty = false;
- function __construct($name, $title = null, $value = "", $form = null) {
- // we have labels for the subfields
- $title = false;
-
+ /**
+ * Hide the two password fields by default,
+ * and provide a link instead that toggles them.
+ *
+ * @var boolean
+ */
+ protected $showOnClick = false;
+
+ /**
+ * Title for the link that triggers
+ * the visibility of password fields.
+ *
+ * @var string
+ */
+ public $showOnClickTitle = 'Change Password';
+
+ /**
+ * @param string $name
+ * @param string $title
+ * @param mixed $value
+ * @param Form $form
+ * @param boolean $showOnClick
+ */
+ function __construct($name, $title = null, $value = "", $form = null, $showOnClick = false) {
// naming with underscores to prevent values from actually being saved somewhere
$this->children = new FieldSet(
new PasswordField("{$name}[_Password]", _t('Member.PASSWORD')),
new PasswordField("{$name}[_ConfirmPassword]",_t('Member.CONFIRMPASSWORD', 'Confirm Password'))
);
+
+ $this->showOnClick = $showOnClick;
+ if($this->showOnClick) {
+ $this->children->push(new HiddenField("{$name}[_PasswordFieldVisible]"));
+ }
+
+ // we have labels for the subfields
+ $title = false;
parent::__construct($name, $title, $value, $form);
}
function Field() {
+ Requirements::javascript('jsparty/prototype.js');
+ Requirements::javascript('jsparty/behaviour.js');
+ Requirements::javascript('sapphire/javascript/ConfirmedPasswordField.js');
+
$content = '';
+
+ if($this->showOnClick) {
+
+ $content .= "<div class=\"showOnClick\">\n";
+ $content .= "<a href=\"#\">{$this->showOnClickTitle}</a>\n";
+ $content .= "<div class=\"showOnClickContainer\">";
+ }
+
foreach($this->children as $field) {
- $content.= $field->FieldHolder();
+ $content .= $field->FieldHolder();
+ }
+
+ if($this->showOnClick) {
+ $content .= "</div>\n";
+ $content .= "</div>\n";
}
return $content;
@@ -69,11 +133,21 @@ function setValue($value) {
}
- function jsValidation()
- {
+ 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;
+ }
+ ";
- $jsTests = "
+ $jsTests .= "
if(passEl.value != confEl.value) {
validationError(confEl, \"Passwords have to match.\", \"error\");
return false;
@@ -89,7 +163,7 @@ function jsValidation()
";
}
- if(($this->minLength || $this->maxLength) && !$this->canBeEmpty) {
+ if(($this->minLength || $this->maxLength)) {
if($this->minLength && $this->maxLength) {
$limit = "{$this->minLength},{$this->maxLength}";
$errorMsg = "Passwords must be {$this->minLength} to {$this->maxLength} characters long.";
@@ -102,7 +176,7 @@ function jsValidation()
}
$limitRegex = '/^.{' . $limit . '}$/';
$jsTests .= "
- if(!passEl.value.match({$limitRegex})) {
+ if(passEl.value && !passEl.value.match({$limitRegex})) {
validationError(confEl, \"{$errorMsg}\", \"error\");
return false;
}
@@ -147,29 +221,48 @@ function jsValidation()
JS;
}
+ /**
+ * Determines if the field was actually
+ * shown on the clientside - if not,
+ * we don't validate or save it.
+ *
+ * @return bool
+ */
+ function isSaveable() {
+ $isVisible = $this->children->fieldByName($this->Name() . '[_PasswordFieldVisible]');
+ return (!$this->showOnClick || ($this->showOnClick && $isVisible && $isVisible->Value()));
+ }
+
function validate() {
$validator = $this->form->getValidator();
$name = $this->name;
+
+ // if field isn't visible, don't validate
+ if(!$this->isSaveable()) return true;
+
$passwordField = $this->children->fieldByName($name.'[_Password]');
$passwordConfirmField = $this->children->fieldByName($name.'[_ConfirmPassword]');
$passwordField->setValue($_POST[$name]['_Password']);
$passwordConfirmField->setValue($_POST[$name]['_ConfirmPassword']);
+
+ $value = $passwordField->Value();
+
// both password-fields should be the same
- if($passwordField->Value() != $passwordConfirmField->Value()) {
+ if($value != $passwordConfirmField->Value()) {
$validator->validationError($name, _t('Form.VALIDATIONPASSWORDSDONTMATCH',"Passwords don't match"), "validation", false);
return false;
}
if(!$this->canBeEmpty) {
// both password-fields shouldn't be empty
- if(!$passwordField->Value() || !$passwordConfirmField->Value()) {
+ if(!$$value || !$passwordConfirmField->Value()) {
$validator->validationError($name, _t('Form.VALIDATIONPASSWORDSNOTEMPTY', "Passwords can't be empty"), "validation", false);
return false;
}
}
// lengths
- if(($this->minLength || $this->maxLength) && !$this->canBeEmpty) {
+ if(($this->minLength || $this->maxLength)) {
if($this->minLength && $this->maxLength) {
$limit = "{$this->minLength},{$this->maxLength}";
$errorMsg = "Passwords must be {$this->minLength} to {$this->maxLength} characters long.";
@@ -181,7 +274,7 @@ function validate() {
$errorMsg = "Passwords must be at most {$this->maxLength} characters long.";
}
$limitRegex = '/^.{' . $limit . '}$/';
- if(!preg_match($limitRegex,$passwordField->Value())) {
+ if(!empty($value) && !preg_match($limitRegex,$value)) {
$validator->validationError('Password', $errorMsg,
"validation",
false
@@ -190,7 +283,7 @@ function validate() {
}
if($this->requireStrongPassword) {
- if(!preg_match('/^(([a-zA-Z]+\d+)|(\d+[a-zA-Z]+))[a-zA-Z0-9]*$/',$passwordField->Value())) {
+ if(!preg_match('/^(([a-zA-Z]+\d+)|(\d+[a-zA-Z]+))[a-zA-Z0-9]*$/',$value)) {
$validator->validationError(
'Password',
_t('Form.VALIDATIONSTRONGPASSWORD', "Passwords must have at least one digit and one alphanumeric character."),
@@ -203,7 +296,16 @@ function validate() {
return true;
}
+ /**
+ * Only save if field was shown on the client,
+ * and is not empty.
+ *
+ * @param DataObject $record
+ * @return bool
+ */
function saveInto(DataObject $record) {
+ if(!$this->isSaveable()) return false;
+
if(!($this->canBeEmpty && !$this->value)) {
parent::saveInto($record);
}
View
26 javascript/ConfirmedPasswordField.js
@@ -0,0 +1,26 @@
+Behaviour.register({
+ 'div.confirmedpassword' : {
+ initialize: function() {
+ var rules = {};
+ rules['#'+this.id+' .showOnClick a'] = {onclick: function(e) {
+ this.toggle();
+ Event.stop(e);
+ }.bind(this)};
+
+ Behaviour.register(rules);
+
+ this.toggle();
+ },
+
+ toggle: function() {
+ var containers = $$('.showOnClickContainer', this);
+ if(!containers.length) return false;
+
+ var container = containers[0];
+ Element.toggle(container);
+ var hiddenField = $$('input.hidden', this)[0];
+ hiddenField.value = (Element.visible(container));
+ }
+
+ }
+});
Please sign in to comment.
Something went wrong with that request. Please try again.