Merge pull request #1868 from wilr/pen-6245

FIX: Disable autocomplete on ConfirmedPasswordField instances.
This commit is contained in:
Ingo Schommer 2013-05-10 02:41:16 -07:00
commit 3b72432c40
2 changed files with 106 additions and 38 deletions

View File

@ -1,8 +1,10 @@
<?php <?php
/** /**
* Two masked input fields, checks for matching passwords. * Two masked input fields, checks for matching passwords.
* Optionally hides the fields by default and shows *
* a link to toggle their visibility. * Optionally hides the fields by default and shows a link to toggle their
* visibility.
* *
* @package forms * @package forms
* @subpackage fields-formattedinput * @subpackage fields-formattedinput
@ -39,11 +41,12 @@ class ConfirmedPasswordField extends FormField {
public $canBeEmpty = false; public $canBeEmpty = false;
/** /**
* If set to TRUE, the "password" and "confirm password" * If set to TRUE, the "password" and "confirm password" form fields will
* formfields will be hidden via CSS and JavaScript by default, * be hidden via CSS and JavaScript by default, and triggered by a link.
* and triggered by a link. An additional hidden field *
* determines if showing the fields has been triggered, * An additional hidden field determines if showing the fields has been
* and just validates/saves the input in this case. * triggered and just validates/saves the input in this case.
*
* This behaviour works unobtrusively, without JavaScript enabled * This behaviour works unobtrusively, without JavaScript enabled
* the fields show, validate and save by default. * the fields show, validate and save by default.
* *
@ -52,8 +55,7 @@ class ConfirmedPasswordField extends FormField {
protected $showOnClick = false; protected $showOnClick = false;
/** /**
* Title for the link that triggers * Title for the link that triggers the visibility of password fields.
* the visibility of password fields.
* *
* @var string * @var string
*/ */
@ -93,6 +95,12 @@ class ConfirmedPasswordField extends FormField {
if($showOnClick) { if($showOnClick) {
$this->children->push(new HiddenField("{$name}[_PasswordFieldVisible]")); $this->children->push(new HiddenField("{$name}[_PasswordFieldVisible]"));
} }
// disable auto complete
foreach($this->children as $child) {
$child->setAttribute('autocomplete', 'off');
}
$this->showOnClick = $showOnClick; $this->showOnClick = $showOnClick;
// we have labels for the subfields // we have labels for the subfields
@ -102,6 +110,11 @@ class ConfirmedPasswordField extends FormField {
$this->setValue($value); $this->setValue($value);
} }
/**
* @param array $properties
*
* @return string
*/
public function Field($properties = array()) { public function Field($properties = array()) {
Requirements::javascript(FRAMEWORK_DIR . '/thirdparty/jquery/jquery.js'); Requirements::javascript(FRAMEWORK_DIR . '/thirdparty/jquery/jquery.js');
Requirements::javascript(FRAMEWORK_DIR . '/javascript/ConfirmedPasswordField.js'); Requirements::javascript(FRAMEWORK_DIR . '/javascript/ConfirmedPasswordField.js');
@ -129,11 +142,13 @@ class ConfirmedPasswordField extends FormField {
foreach($this->children as $field) { foreach($this->children as $field) {
$field->setDisabled($this->isDisabled()); $field->setDisabled($this->isDisabled());
$field->setReadonly($this->isReadonly()); $field->setReadonly($this->isReadonly());
if(count($this->attributes)) { if(count($this->attributes)) {
foreach($this->attributes as $name => $value) { foreach($this->attributes as $name => $value) {
$field->setAttribute($name, $value); $field->setAttribute($name, $value);
} }
} }
$content .= $field->FieldHolder(); $content .= $field->FieldHolder();
} }
@ -147,63 +162,89 @@ class ConfirmedPasswordField extends FormField {
/** /**
* Can be empty is a flag that turns on / off empty field checking. * Can be empty is a flag that turns on / off empty field checking.
*
* For example, set this to false (the default) when creating a user account, * For example, set this to false (the default) when creating a user account,
* and true * and true when displaying on an edit form.
*
* @param boolean $value
*
* @return ConfirmedPasswordField
*/ */
public function setCanBeEmpty($value) { public function setCanBeEmpty($value) {
$this->canBeEmpty = (bool)$value; $this->canBeEmpty = (bool)$value;
return $this; return $this;
} }
/** /**
* The title on the link which triggers display of the * The title on the link which triggers display of the "password" and
* "password" and "confirm password" formfields. * "confirm password" formfields. Only used if {@link setShowOnClick()}
* Only used if {@link setShowOnClick()} is set to TRUE. * is set to TRUE.
* *
* @param $title * @param string $title
*
* @return ConfirmedPasswordField
*/ */
public function setShowOnClickTitle($title) { public function setShowOnClickTitle($title) {
$this->showOnClickTitle = $title; $this->showOnClickTitle = $title;
return $this; return $this;
} }
/** /**
* @return string * @return string $title
*/ */
public function getShowOnClickTitle() { public function getShowOnClickTitle() {
return $this->showOnClickTitle; return $this->showOnClickTitle;
} }
/**
* @param string $title
*
* @return ConfirmedPasswordField
*/
public function setRightTitle($title) { public function setRightTitle($title) {
foreach($this->children as $field) { foreach($this->children as $field) {
$field->setRightTitle($title); $field->setRightTitle($title);
} }
return $this; return $this;
} }
/** /**
* @param array: 2 entrie array with the customised title for each of the 2 children. * @param array $titles 2 entry array with the customized title for each
* of the 2 children.
*
* @return ConfirmedPasswordField
*/ */
public function setChildrenTitles($titles) { public function setChildrenTitles($titles) {
if(is_array($titles) && count($titles) == 2) { if(is_array($titles) && count($titles) == 2) {
foreach($this->children as $field) { foreach($this->children as $field) {
if(isset($titles[0])) { if(isset($titles[0])) {
$field->setTitle($titles[0]); $field->setTitle($titles[0]);
array_shift($titles); array_shift($titles);
} }
} }
} }
return $this; return $this;
} }
/** /**
* Value is sometimes an array, and sometimes a single value, so we need to handle both cases * Value is sometimes an array, and sometimes a single value, so we need
* to handle both cases.
*
* @param mixed $value
*
* @return ConfirmedPasswordField
*/ */
public function setValue($value) { public function setValue($value) {
if(is_array($value)) { if(is_array($value)) {
if($value['_Password'] || (!$value['_Password'] && !$this->canBeEmpty)) { if($value['_Password'] || (!$value['_Password'] && !$this->canBeEmpty)) {
$this->value = $value['_Password']; $this->value = $value['_Password'];
} }
if($this->showOnClick && isset($value['_PasswordFieldVisible'])) { if($this->showOnClick && isset($value['_PasswordFieldVisible'])) {
$this->children->fieldByName($this->getName() . '[_PasswordFieldVisible]') $this->children->fieldByName($this->getName() . '[_PasswordFieldVisible]')
->setValue($value['_PasswordFieldVisible']); ->setValue($value['_PasswordFieldVisible']);
@ -213,29 +254,40 @@ class ConfirmedPasswordField extends FormField {
$this->value = $value; $this->value = $value;
} }
} }
$this->children->fieldByName($this->getName() . '[_Password]')->setValue($this->value);
$this->children->fieldByName($this->getName() . '[_ConfirmPassword]')->setValue($this->value); $this->children->fieldByName($this->getName() . '[_Password]')
->setValue($this->value);
$this->children->fieldByName($this->getName() . '[_ConfirmPassword]')
->setValue($this->value);
return $this; return $this;
} }
/** /**
* Determines if the field was actually * Determines if the field was actually shown on the client side - if not,
* shown on the clientside - if not,
* we don't validate or save it. * we don't validate or save it.
* *
* @return bool * @return boolean
*/ */
public function isSaveable() { public function isSaveable() {
$isVisible = $this->children->fieldByName($this->getName() . '[_PasswordFieldVisible]'); $isVisible = $this->children->fieldByName($this->getName() . '[_PasswordFieldVisible]');
return (!$this->showOnClick || ($this->showOnClick && $isVisible && $isVisible->Value())); return (!$this->showOnClick || ($this->showOnClick && $isVisible && $isVisible->Value()));
} }
/**
* @param Validator $validator
*
* @return boolean
*/
public function validate($validator) { public function validate($validator) {
$name = $this->name; $name = $this->name;
// if field isn't visible, don't validate // if field isn't visible, don't validate
if(!$this->isSaveable()) return true; if(!$this->isSaveable()) {
return true;
}
$passwordField = $this->children->fieldByName($name.'[_Password]'); $passwordField = $this->children->fieldByName($name.'[_Password]');
$passwordConfirmField = $this->children->fieldByName($name.'[_ConfirmPassword]'); $passwordConfirmField = $this->children->fieldByName($name.'[_ConfirmPassword]');
@ -246,16 +298,26 @@ class ConfirmedPasswordField extends FormField {
// both password-fields should be the same // both password-fields should be the same
if($value != $passwordConfirmField->Value()) { if($value != $passwordConfirmField->Value()) {
$validator->validationError($name, _t('Form.VALIDATIONPASSWORDSDONTMATCH',"Passwords don't match"), $validator->validationError(
"validation", false); $name,
_t('Form.VALIDATIONPASSWORDSDONTMATCH',"Passwords don't match"),
"validation",
false
);
return false; return false;
} }
if(!$this->canBeEmpty) { if(!$this->canBeEmpty) {
// both password-fields shouldn't be empty // both password-fields shouldn't be empty
if(!$value || !$passwordConfirmField->Value()) { if(!$value || !$passwordConfirmField->Value()) {
$validator->validationError($name, _t('Form.VALIDATIONPASSWORDSNOTEMPTY', "Passwords can't be empty"), $validator->validationError(
"validation", false); $name,
_t('Form.VALIDATIONPASSWORDSNOTEMPTY', "Passwords can't be empty"),
"validation",
false
);
return false; return false;
} }
} }
@ -302,21 +364,25 @@ class ConfirmedPasswordField extends FormField {
"validation", "validation",
false false
); );
return false; return false;
} }
} }
return true; return true;
} }
/** /**
* Only save if field was shown on the client, * Only save if field was shown on the client, and is not empty.
* and is not empty.
* *
* @param DataObject $record * @param DataObjectInterface $record
* @return bool *
* @return boolean
*/ */
public function saveInto(DataObjectInterface $record) { public function saveInto(DataObjectInterface $record) {
if(!$this->isSaveable()) return false; if(!$this->isSaveable()) {
return false;
}
if(!($this->canBeEmpty && !$this->value)) { if(!($this->canBeEmpty && !$this->value)) {
parent::saveInto($record); parent::saveInto($record);
@ -324,7 +390,9 @@ class ConfirmedPasswordField extends FormField {
} }
/** /**
* Makes a pretty readonly field with some stars in it * Makes a read only field with some stars in it to replace the password
*
* @return ReadonlyField
*/ */
public function performReadonlyTransformation() { public function performReadonlyTransformation() {
$field = $this->castedCopy('ReadonlyField') $field = $this->castedCopy('ReadonlyField')

View File

@ -1,5 +1,5 @@
(function ($) { (function ($) {
$('.confirmedpassword .showOnClick a').live('click', function () { $(document).on('click', '.confirmedpassword .showOnClick a', function () {
var $container = $('.showOnClickContainer', $(this).parent()); var $container = $('.showOnClickContainer', $(this).parent());
$container.toggle('fast', function() { $container.toggle('fast', function() {