Skip to content
Permalink
Browse files

MDL-53048 form: Rewrite passwordunmask

This version:
* should work with the Behat Goutte driver
* should not suffer from password autofill anxiety
* should allow unmasking (and masking) of a password
* should allow editing of passwords in either masked, or unmasked form

AMOS BEGIN
 MOV [revealpassword,core_form],[passwordunmaskrevealhint,core_form]
AMOS END
  • Loading branch information...
andrewnicols committed Aug 21, 2016
1 parent ac157b0 commit ca25005c69a7fd5b947350eb62278eae07b339cb
Showing with 791 additions and 228 deletions.
  1. +29 −34 admin/templates/setting_configpasswordunmask.mustache
  2. +1 −0 lang/en/deprecated.txt
  3. +8 −1 lang/en/form.php
  4. +4 −6 lib/adminlib.php
  5. +4 −0 lib/behat/behat_field_manager.php
  6. +5 −0 lib/behat/classes/partial_named_selector.php
  7. +64 −0 lib/behat/form_field/behat_form_passwordunmask.php
  8. +1 −0 lib/form/amd/build/passwordunmask.min.js
  9. +286 −0 lib/form/amd/src/passwordunmask.js
  10. +8 −18 lib/form/passwordunmask.php
  11. +1 −0 lib/form/templatable_form_element.php
  12. +56 −0 lib/form/templates/element-passwordunmask-fill.mustache
  13. +93 −0 lib/form/templates/element-passwordunmask.mustache
  14. +64 −0 lib/form/templates/element-template.mustache
  15. +4 −40 lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask-debug.js
  16. +1 −1 lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask-min.js
  17. +2 −40 lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask.js
  18. +3 −39 lib/form/yui/src/passwordunmask/js/passwordunmask.js
  19. +1 −4 lib/form/yui/src/passwordunmask/meta/passwordunmask.json
  20. BIN pix/t/passwordunmask-edit.png
  21. +3 −0 pix/t/passwordunmask-edit.svg
  22. BIN pix/t/passwordunmask-reveal.png
  23. +3 −0 pix/t/passwordunmask-reveal.svg
  24. +47 −35 theme/boost/templates/core_admin/setting_configpasswordunmask.mustache
  25. +92 −10 theme/boost/templates/core_form/element-passwordunmask.mustache
  26. +6 −0 theme/bootstrapbase/less/moodle/forms.less
  27. +5 −0 theme/bootstrapbase/style/moodle.css
@@ -34,40 +34,35 @@
}
}}
<div class="form-password">
<input type="password" name="{{name}}" size="{{size}}" id="{{id}}" value="{{value}}">
<div class="unmask" id="{{id}}unmaskdiv"></div>
<span data-passwordunmask="wrapper" data-passwordunmaskid="{{ id }}">
<noscript>
<!-- Backwards compatability for Behat -->
<input type="password"
name="{{ name }}"
id="{{ id }}"
value="{{ value }}"
size="{{ size }}"
>
</noscript>
<span class="visibleifjs">
<span data-passwordunmask="editor">
<!-- The input in the noscript will be moved here as part of the page load -->
</span>
<a href="#" data-passwordunmask="edit" title="{{ edithint }}">
<span data-passwordunmask="displayvalue">{{> core_form/element-passwordunmask-fill }}</span>
{{# pix }} t/passwordunmask-edit, core, {{# str }} passwordunmaskedithint, form {{/ str }}{{/ pix }}
</a>
<a href="#" data-passwordunmask="unmask" title="{{ unmaskhint }}">
{{# pix }} t/passwordunmask-reveal, core, {{# str }} passwordunmaskrevealhint, form {{/ str }}{{/ pix }}
</a>
<span data-passwordunmask="instructions" class="form-text text-muted" style="display: none;">
{{# str }} passwordunmaskinstructions, form {{/ str }}
</span>
</span>
</span>
</div>
{{#js}}
(function() {
var id = '{{id}}';
var unmaskid = id + 'unmask';
var unmaskdivid = id + 'unmaskdiv';
var unmaskstr = {{#quote}}{{#str}}unmaskpassword, form{{/str}}{{/quote}};
var is_ie = (navigator.userAgent.toLowerCase().indexOf("msie") != -1);

document.getElementById(id).setAttribute("autocomplete", "off");

var unmaskdiv = document.getElementById(unmaskdivid);

var unmaskchb = document.createElement("input");
unmaskchb.setAttribute("type", "checkbox");
unmaskchb.setAttribute("id", unmaskid);
unmaskchb.onchange = function() {unmaskPassword(id);};
unmaskdiv.appendChild(unmaskchb);

var unmasklbl = document.createElement("label");
unmasklbl.innerHTML = unmaskstr;
if (is_ie) {
unmasklbl.setAttribute("htmlFor", unmaskid);
} else {
unmasklbl.setAttribute("for", unmaskid);
}
unmaskdiv.appendChild(unmasklbl);

if (is_ie) {
// Ugly hack to work around the famous onchange IE bug.
unmaskchb.onclick = function() {this.blur();};
unmaskdiv.onclick = function() {this.blur();};
}
})()
require(['core_form/passwordunmask'], function(PasswordUnmask) {
new PasswordUnmask("{{ id }}");
});
{{/js}}
@@ -34,3 +34,4 @@ downloadoptions,core_table
downloadtsv,core_table
downloadxhtml,core_table
invalidpersistent,core_competency
revealpassword,core_form
@@ -51,10 +51,14 @@
$string['nonexistentformelements'] = 'Trying to add help buttons to non-existent form elements : {$a}';
$string['noselection'] = 'No selection';
$string['nosuggestions'] = 'No suggestions';
$string['novalue'] = 'Nothing entered';
$string['novalueclicktoset'] = 'Click to enter text';
$string['optional'] = 'Optional';
$string['othersettings'] = 'Other settings';
$string['passwordunmaskedithint'] = 'Edit password';
$string['passwordunmaskrevealhint'] = 'Reveal';
$string['passwordunmaskinstructions'] = 'Press enter to save changes';
$string['requiredelement'] = 'Required field';
$string['revealpassword'] = 'Reveal';
$string['security'] = 'Security';
$string['selectallornone'] = 'Select all/none';
$string['selected'] = 'Selected';
@@ -68,3 +72,6 @@
$string['timing'] = 'Timing';
$string['unmaskpassword'] = 'Unmask';
$string['year'] = 'Year';
// Deprecated since 3.2.
$string['revealpassword'] = 'Reveal';
@@ -2406,13 +2406,11 @@ protected function add_to_config_log($name, $oldvalue, $value) {
}
/**
* Returns XHTML for the field
* Writes Javascript into the HTML below right before the last div
* Returns HTML for the field.
*
* @todo Make javascript available through newer methods if possible
* @param string $data Value for the field
* @param string $query Passed as final argument for format_admin_setting
* @return string XHTML field
* @param string $data Value for the field
* @param string $query Passed as final argument for format_admin_setting
* @return string Rendered HTML
*/
public function output_html($data, $query='') {
global $OUTPUT;
@@ -228,6 +228,10 @@ protected static function get_field_node_type(NodeElement $fieldnode, Session $s
return $type;
}
if (!empty($fieldnode->find('xpath', '/ancestor::*[@data-passwordunmaskid]'))) {
return 'passwordunmask';
}
// We look for a parent node with 'felement' class.
if ($class = $fieldnode->getParent()->getAttribute('class')) {
@@ -186,6 +186,11 @@ public function __construct() {
'filemanager' => <<<XPATH
.//*[@data-fieldtype = 'filemanager' or @data-fieldtype = 'filepicker']
/descendant::input[@id = //label[contains(normalize-space(string(.)), %locator%)]/@for]
XPATH
,
'passwordunmask' => <<<XPATH
.//*[@data-passwordunmask='wrapper']
/descendant::input[@id = //label[contains(normalize-space(string(.)), %locator%)]/@for]
XPATH
],
];
@@ -0,0 +1,64 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Silly behat_form_select extension.
*
* @package core_form
* @category test
* @copyright 2013 David Monllaó
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/behat_form_text.php');
/**
* Allows interaction with passwordunmask form fields.
*
* Plain behat_form_select extension as it is the same
* kind of field.
*
* @package core_form
* @category test
* @copyright 2013 David Monllaó
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_form_passwordunmask extends behat_form_text {
/**
* Sets the value to a field.
*
* @param string $value
* @return void
*/
public function set_value($value) {
if ($this->running_javascript()) {
$id = $this->field->getAttribute('id');
$js = <<<JS
require(["jquery"], function($) {
var wrapper = $(document.getElementById("{$id}")).closest('[data-passwordunmask="wrapper"]');
wrapper.find('[data-passwordunmask="edit"]').trigger("click");
});
JS;
$this->session->executeScript($js);
}
$this->field->setValue($value);
}
}

Some generated files are not rendered by default. Learn more.

0 comments on commit ca25005

Please sign in to comment.
You can’t perform that action at this time.