Skip to content
Browse files

MDL-30637 Refactor Advanced fileds functionality

The displaying of advanced items has been refactored. The changes are:

* The Advanced button is replaced by the Show Less/More link
* The Show less/more link controls advanced elements only within the section
  it is located at
* The Show less/more state of sections is preserved between form submissions
* When javascript is off, all advanced elements will be displayed by default,
  no show/hide controls will exists on the page
  • Loading branch information...
1 parent a4f1834 commit ac5e6ca4d1c7f33eb72dcc2953feb02db0657090 @kabalin kabalin committed Jan 24, 2013
Showing with 146 additions and 155 deletions.
  1. +2 −0 lang/en/form.php
  2. +0 −52 lib/form/form.js
  3. +104 −0 lib/form/yui/showadvanced/showadvanced.js
  4. +40 −100 lib/formslib.php
  5. +0 −3 user/filters/user_filter_forms.php
View
2 lang/en/form.php
@@ -58,6 +58,8 @@
$string['selectallornone'] = 'Select all/none';
$string['selected'] = 'Selected';
$string['showadvanced'] = 'Show advanced';
+$string['showless'] = 'Show less...';
+$string['showmore'] = 'Show more...';
$string['showeditortoolbar'] = 'Show editing tools';
$string['somefieldsrequired'] = 'There are required fields in this form marked {$a}.';
$string['time'] = 'Time';
View
52 lib/form/form.js
@@ -7,58 +7,6 @@
M.form = M.form || {};
/**
- * Initialises the show advanced functionality and events.
- * This should only ever happen ONCE per page.
- *
- * @param {YUI} Y
- * @param {object} config
- */
-M.form.initShowAdvanced = function(Y, config) {
- if (M.form.showAdvanced) {
- return M.form.showAdvanced;
- }
- var showAdvanced = function(config) {
- showAdvanced.superclass.constructor.apply(this, arguments);
- };
- showAdvanced.prototype = {
- _advButtons : [],
- _advAreas : [],
- _stateInput : null,
- initializer : function() {
- this._advAreas = Y.all('form .advanced');
- this._advButtons = Y.all('.showadvancedbtn');
- if (this._advButtons.size() > 0) {
- this._stateInput = new Y.NodeList(document.getElementsByName('mform_showadvanced_last'));
- this._advButtons.on('click', this.switchState, this);
- this._advButtons.set('type', 'button');
- }
- },
- /**
- * Toggles between showing advanced items and hiding them.
- * Should be fired by an event.
- */
- switchState : function(e) {
- e.preventDefault();
- if (this._stateInput.get('value')=='1') {
- this._stateInput.set('value', '0');
- this._advButtons.setAttribute('value', M.str.form.showadvanced);
- this._advAreas.addClass('hide');
- } else {
- this._stateInput.set('value', '1');
- this._advButtons.setAttribute('value', M.str.form.hideadvanced);
- this._advAreas.removeClass('hide');
- }
- }
- };
- // Extend it with the YUI widget fw.
- Y.extend(showAdvanced, Y.Base, showAdvanced.prototype, {
- NAME : 'mform-showAdvanced'
- });
- M.form.showAdvanced = new showAdvanced(config);
- return M.form.showAdvanced;
-};
-
-/**
* Stores a list of the dependencyManager for each form on the page.
*/
M.form.dependencyManagers = {};
View
104 lib/form/yui/showadvanced/showadvanced.js
@@ -0,0 +1,104 @@
+YUI.add('moodle-form-showadvanced', function(Y) {
+ /**
+ * Provides the form showadvanced class
+ *
+ * @module moodle-form-showadvanced
+ */
+
+ /**
+ * A class for a showadvanced
+ *
+ * @param {Object} config Object literal specifying showadvanced configuration properties.
+ * @class M.form.showadvanced
+ * @constructor
+ * @extends Y.Base
+ */
+ function SHOWADVANCED(config) {
+ SHOWADVANCED.superclass.constructor.apply(this, [config]);
+ }
+
+ var SELECTORS = {
+ FIELDSETCONTAINSADVANCED : 'fieldset.containsadvancedelements',
+ DIVFITEMADVANCED : 'div.fitem.advanced',
+ DIVFCONTAINER : 'div.fcontainer'
+ },
+ CSS = {
+ HIDE : 'hide',
+ MORELESSTOGGLER : 'morelesstoggler'
+ },
+ ATTRS = {};
+
+ /**
+ * Static property provides a string to identify the JavaScript class.
+ *
+ * @property NAME
+ * @type String
+ * @static
+ */
+ SHOWADVANCED.NAME = 'moodle-form-showadvanced';
+
+ /**
+ * Static property used to define the default attribute configuration for the Showadvanced.
+ *
+ * @property ATTRS
+ * @type String
+ * @static
+ */
+ SHOWADVANCED.ATTRS = ATTRS;
+
+ /**
+ * The form ID attribute definition
+ *
+ * @attribute formid
+ * @type String
+ * @default ''
+ * @writeOnce
+ */
+ ATTRS.formid = {
+ value : null
+ };
+
+ Y.extend(SHOWADVANCED, Y.Base, {
+ initializer : function() {
+ var fieldlist = Y.Node.all('#'+this.get('formid')+' '+SELECTORS.FIELDSETCONTAINSADVANCED);
+ // Look through fieldset divs that contain advanced elements
+ fieldlist.each(this.process_fieldset, this);
+ // Subscribe more/less links to click event
+ Y.one('#'+this.get('formid')).delegate('click', this.switch_state, SELECTORS.FIELDSETCONTAINSADVANCED+' .'+CSS.MORELESSTOGGLER);
+ },
+ process_fieldset : function(fieldset) {
+ var statuselement = new Y.one('input[name=mform_showmore_'+fieldset.get('id')+']');
+ var morelesslink = Y.Node.create('<a href="#"></a>');
+ morelesslink.addClass(CSS.MORELESSTOGGLER);
+ if (statuselement.get('value') === '0') {
+ morelesslink.setHTML(M.str.form.showmore);
+ // hide advanced stuff initially
+ fieldset.all(SELECTORS.DIVFITEMADVANCED).addClass(CSS.HIDE);
+ } else {
+ morelesslink.setHTML(M.str.form.showless);
+ }
+ fieldset.one(SELECTORS.DIVFCONTAINER).append(morelesslink);
+ },
+ switch_state : function(e) {
+ e.preventDefault();
+ var fieldset = this.ancestor(SELECTORS.FIELDSETCONTAINSADVANCED);
+ // toggle collapsed class
+ fieldset.all(SELECTORS.DIVFITEMADVANCED).toggleClass(CSS.HIDE);
+ // get corresponding hidden variable
+ var statuselement = new Y.one('input[name=mform_showmore_'+fieldset.get('id')+']');
+ // invert it and change the link text
+ if (statuselement.get('value') === '0') {
+ statuselement.set('value', 1);
+ this.setHTML(M.util.get_string('showless', 'form'));
+ } else {
+ statuselement.set('value', 0);
+ this.setHTML(M.util.get_string('showmore', 'form'));
+ }
+ }
+ });
+
+ M.form = M.form || {};
+ M.form.showadvanced = M.form.showadvanced || function(params) {
+ return new SHOWADVANCED(params);
+ };
+}, '@VERSION@', {requires:['base', 'node', 'selector-css3']});
View
140 lib/formslib.php
@@ -1225,11 +1225,7 @@ public static function get_js_module() {
return array(
'name' => 'mform',
'fullpath' => '/lib/form/form.js',
- 'requires' => array('base', 'node'),
- 'strings' => array(
- array('showadvanced', 'form'),
- array('hideadvanced', 'form')
- )
+ 'requires' => array('base', 'node')
);
}
}
@@ -1277,13 +1273,6 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless {
*/
var $_disableShortforms = false;
- /**
- * Whether to display advanced elements (on page load)
- *
- * @var boolean
- */
- var $_showAdvanced = null;
-
/** @var bool whether to automatically initialise M.formchangechecker for this form. */
protected $_use_form_change_checker = true;
@@ -1369,13 +1358,6 @@ function setAdvanced($elementName, $advanced=true){
} elseif (isset($this->_advancedElements[$elementName])) {
unset($this->_advancedElements[$elementName]);
}
- if ($advanced && $this->getElementType('mform_showadvanced_last')===false){
- $this->setShowAdvanced();
- $this->registerNoSubmitButton('mform_showadvanced');
-
- $this->addElement('hidden', 'mform_showadvanced_last');
- $this->setType('mform_showadvanced_last', PARAM_INT);
- }
}
/**
@@ -1402,59 +1384,35 @@ function setExpanded($headerName, $expanded=true){
}
/**
- * Use this method to indicate that the form will not be using shortforms.
- *
- * @param boolean $disable default true, controls if the shortforms are disabled.
- */
- function setDisableShortforms ($disable = true) {
- $this->_disableShortforms = $disable;
- }
-
- /**
- * Set whether to show advanced elements in the form on first displaying form. Default is not to
- * display advanced elements in the form until 'Show Advanced' is pressed.
- *
- * You can get the last state of the form and possibly save it for this user by using
- * value 'mform_showadvanced_last' in submitted data.
+ * Use this method to add show more/less status element required for passing
+ * over the advanced elements visibility status on the form submission.
*
- * @param bool $showadvancedNow if true will show adavance elements.
+ * @param string $headerName header element name
+ * @param boolean $showmore default false sets the advanced elements to be hidden.
*/
- function setShowAdvanced($showadvancedNow = null){
- if ($showadvancedNow === null){
- if ($this->_showAdvanced !== null){
- return;
- } else { //if setShowAdvanced is called without any preference
- //make the default to not show advanced elements.
- $showadvancedNow = get_user_preferences(
- textlib::strtolower($this->_formName.'_showadvanced', 0));
+ function addAdvancedStatusElement($headerName, $showmore=false){
+ // Add extra hidden element to store advanced items state for each section
+ if ($this->getElementType('mform_showmore_' . $headerName) === false) {
+ // see if we the form has been submitted already
+ $formshowmore = optional_param('mform_showmore_' . $headerName, -1, PARAM_INT);
+ if (!$showmore && $formshowmore != -1) {
+ // override showmore state with the form variable
+ $showmore = $formshowmore;
}
+ // create the form element for storing advanced items state
+ $this->addElement('hidden', 'mform_showmore_' . $headerName);
+ $this->setType('mform_showmore_' . $headerName, PARAM_INT);
+ $this->setConstant('mform_showmore_' . $headerName, (int)$showmore);
}
- //value of hidden element
- $hiddenLast = optional_param('mform_showadvanced_last', -1, PARAM_INT);
- //value of button
- $buttonPressed = optional_param('mform_showadvanced', 0, PARAM_RAW);
- //toggle if button pressed or else stay the same
- if ($hiddenLast == -1) {
- $next = $showadvancedNow;
- } elseif ($buttonPressed) { //toggle on button press
- $next = !$hiddenLast;
- } else {
- $next = $hiddenLast;
- }
- $this->_showAdvanced = $next;
- if ($showadvancedNow != $next){
- set_user_preference($this->_formName.'_showadvanced', $next);
- }
- $this->setConstants(array('mform_showadvanced_last'=>$next));
}
/**
- * Gets show advance value, if advance elements are visible it will return true else false
+ * Use this method to indicate that the form will not be using shortforms.
*
- * @return bool
+ * @param boolean $disable default true, controls if the shortforms are disabled.
*/
- function getShowAdvanced(){
- return $this->_showAdvanced;
+ function setDisableShortforms ($disable = true) {
+ $this->_disableShortforms = $disable;
}
/**
@@ -1496,13 +1454,15 @@ function accept(&$renderer) {
$lastHeader = null;
$lastHeaderAdvanced = false;
$anyAdvanced = false;
+ $anyError = false;
foreach (array_keys($this->_elements) as $elementIndex){
$element =& $this->_elements[$elementIndex];
// if closing header and any contained element was advanced then mark it as advanced
if ($element->getType()=='header' || in_array($element->getName(), $stopFields)){
if ($anyAdvanced && !is_null($lastHeader)){
$this->setAdvanced($lastHeader->getName());
+ $this->addAdvancedStatusElement($lastHeader->getName(), $anyError);
}
$lastHeaderAdvanced = false;
unset($lastHeader);
@@ -1514,14 +1474,19 @@ function accept(&$renderer) {
if ($element->getType()=='header'){
$lastHeader =& $element;
$anyAdvanced = false;
+ $anyError = false;
$lastHeaderAdvanced = isset($this->_advancedElements[$element->getName()]);
} elseif (isset($this->_advancedElements[$element->getName()])){
$anyAdvanced = true;
+ if (isset($this->_errors[$element->getName()])) {
+ $anyError = true;
+ }
}
}
// the last header may not be closed yet...
if ($anyAdvanced && !is_null($lastHeader)){
$this->setAdvanced($lastHeader->getName());
+ $this->addAdvancedStatusElement($lastHeader->getName(), $anyError);
}
$renderer->setAdvancedElements($this->_advancedElements);
}
@@ -2338,7 +2303,7 @@ class MoodleQuickForm_Renderer extends HTML_QuickForm_Renderer_Tableless{
/** @var string Header Template string */
var $_headerTemplate =
- "\n\t\t<legend class=\"ftoggler\">{header}</legend>\n\t\t<div class=\"advancedbutton\">{advancedimg}{button}</div><div class=\"fcontainer clearfix\">\n\t\t";
+ "\n\t\t<legend class=\"ftoggler\">{header}</legend>\n\t\t<div class=\"fcontainer clearfix\">\n\t\t";
/** @var string Template used when opening a fieldset */
var $_openFieldsetTemplate = "\n\t<fieldset class=\"{classes}\" {id}>";
@@ -2364,13 +2329,6 @@ class MoodleQuickForm_Renderer extends HTML_QuickForm_Renderer_Tableless{
var $_collapsibleElements = array();
/**
- * Whether to display advanced elements (on page load)
- *
- * @var integer 1 means show 0 means hide
- */
- var $_showAdvanced;
-
- /**
* Constructor
*/
function MoodleQuickForm_Renderer(){
@@ -2419,7 +2377,6 @@ function startForm(&$form){
$this->_reqHTML = $form->getReqHTML();
$this->_elementTemplates = str_replace('{req}', $this->_reqHTML, $this->_elementTemplates);
$this->_advancedHTML = $form->getAdvancedHTML();
- $this->_showAdvanced = $form->getShowAdvanced();
$formid = $form->getAttribute('id');
parent::startForm($form);
if ($form->isFrozen()){
@@ -2441,6 +2398,10 @@ function startForm(&$form){
if (count($this->_collapsibleElements)) {
$PAGE->requires->yui_module('moodle-form-shortforms', 'M.form.shortforms', array(array('formid' => $formid)));
}
+ if (count($this->_advancedElements)){
+ $PAGE->requires->strings_for_js(array('showmore', 'showless'), 'form');
+ $PAGE->requires->yui_module('moodle-form-showadvanced', 'M.form.showadvanced', array(array('formid' => $formid)));
+ }
}
/**
@@ -2460,13 +2421,9 @@ function startGroup(&$group, $required, $error){
$html = $this->_elementTemplates['default'];
}
- if ($this->_showAdvanced){
- $advclass = ' advanced';
- } else {
- $advclass = ' advanced hide';
- }
+
if (isset($this->_advancedElements[$group->getName()])){
- $html =str_replace(' {advanced}', $advclass, $html);
+ $html =str_replace(' {advanced}', ' advanced', $html);
$html =str_replace('{advancedimg}', $this->_advancedHTML, $html);
} else {
$html =str_replace(' {advanced}', '', $html);
@@ -2515,13 +2472,8 @@ function renderElement(&$element, $required, $error){
}else{
$html = $this->_elementTemplates['default'];
}
- if ($this->_showAdvanced){
- $advclass = ' advanced';
- } else {
- $advclass = ' advanced hide';
- }
if (isset($this->_advancedElements[$element->getName()])){
- $html =str_replace(' {advanced}', $advclass, $html);
+ $html =str_replace(' {advanced}', ' advanced', $html);
} else {
$html =str_replace(' {advanced}', '', $html);
}
@@ -2590,22 +2542,6 @@ function renderHeader(&$header) {
$header_html = str_replace('{header}', $header->toHtml(), $this->_headerTemplate);
}
- if (isset($this->_advancedElements[$name])){
- $header_html =str_replace('{advancedimg}', $this->_advancedHTML, $header_html);
- $elementName='mform_showadvanced';
- if ($this->_showAdvanced==0){
- $buttonlabel = get_string('showadvanced', 'form');
- } else {
- $buttonlabel = get_string('hideadvanced', 'form');
- }
- $button = '<input name="'.$elementName.'" class="showadvancedbtn" value="'.$buttonlabel.'" type="submit" />';
- $PAGE->requires->js_init_call('M.form.initShowAdvanced', array(), false, moodleform::get_js_module());
- $header_html = str_replace('{button}', $button, $header_html);
- } else {
- $header_html =str_replace('{advancedimg}', '', $header_html);
- $header_html = str_replace('{button}', '', $header_html);
- }
-
if ($this->_fieldsetsOpen > 0) {
$this->_html .= $this->_closeFieldsetTemplate;
$this->_fieldsetsOpen--;
@@ -2620,6 +2556,10 @@ function renderHeader(&$header) {
}
}
+ if (isset($this->_advancedElements[$name])){
+ $fieldsetclasses[] = 'containsadvancedelements';
+ }
+
$openFieldsetTemplate = str_replace('{id}', $id, $this->_openFieldsetTemplate);
$openFieldsetTemplate = str_replace('{classes}', join(' ', $fieldsetclasses), $openFieldsetTemplate);
View
3 user/filters/user_filter_forms.php
@@ -25,9 +25,6 @@ function definition() {
// Add button
$mform->addElement('submit', 'addfilter', get_string('addfilter','filters'));
-
- // Don't use last advanced state
- $mform->setShowAdvanced(false);
}
}

0 comments on commit ac5e6ca

Please sign in to comment.
Something went wrong with that request. Please try again.