diff --git a/lang/en/form.php b/lang/en/form.php index d5f2c6c6b2a..e1db4bc058f 100644 --- a/lang/en/form.php +++ b/lang/en/form.php @@ -58,6 +58,8 @@ $string['security'] = 'Security'; $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'; diff --git a/lib/form/form.js b/lib/form/form.js index 1f7856b7c24..e9f9490cf34 100644 --- a/lib/form/form.js +++ b/lib/form/form.js @@ -6,58 +6,6 @@ // Namespace for the form bits and bobs 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. */ diff --git a/lib/form/yui/showadvanced/showadvanced.js b/lib/form/yui/showadvanced/showadvanced.js new file mode 100644 index 00000000000..1c6dd828010 --- /dev/null +++ b/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(''); + 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']}); \ No newline at end of file diff --git a/lib/formslib.php b/lib/formslib.php index 430045aea7e..87c5f8ae50a 100644 --- a/lib/formslib.php +++ b/lib/formslib.php @@ -1225,11 +1225,7 @@ abstract class moodleform { 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 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { } 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); - } } /** @@ -1401,6 +1383,29 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { $this->_collapsibleElements[$headerName] = !$expanded; } + /** + * Use this method to add show more/less status element required for passing + * over the advanced elements visibility status on the form submission. + * + * @param string $headerName header element name + * @param boolean $showmore default false sets the advanced elements to be hidden. + */ + 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); + } + } + /** * Use this method to indicate that the form will not be using shortforms. * @@ -1410,53 +1415,6 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { $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. - * - * @param bool $showadvancedNow if true will show adavance elements. - */ - 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)); - } - } - //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 - * - * @return bool - */ - function getShowAdvanced(){ - return $this->_showAdvanced; - } - /** * Call this method if you don't want the formchangechecker JavaScript to be * automatically initialised for this form. @@ -1496,6 +1454,7 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { $lastHeader = null; $lastHeaderAdvanced = false; $anyAdvanced = false; + $anyError = false; foreach (array_keys($this->_elements) as $elementIndex){ $element =& $this->_elements[$elementIndex]; @@ -1503,6 +1462,7 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { 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 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { 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\n\t\t