From eaec9cfec7dbc4d60bc2c3ec7457e2d7d0e56d06 Mon Sep 17 00:00:00 2001 From: Martin Mastny Date: Wed, 22 Apr 2015 13:35:10 +0800 Subject: [PATCH] MDL-49783 forms: Collapsed form section is opened on error --- .../moodle-form-shortforms-debug.js | 24 +++++++++++++++++-- .../moodle-form-shortforms-min.js | 2 +- .../moodle-form-shortforms.js | 24 +++++++++++++++++-- lib/form/yui/src/shortforms/js/shortforms.js | 22 ++++++++++++++++- .../yui/src/shortforms/meta/shortforms.json | 3 ++- lib/formslib.php | 2 ++ .../moodle-core-event-debug.js | 20 +++++++++++++++- .../moodle-core-event-min.js | 2 +- .../moodle-core-event/moodle-core-event.js | 20 +++++++++++++++- lib/yui/src/event/js/event.js | 20 +++++++++++++++- 10 files changed, 128 insertions(+), 11 deletions(-) diff --git a/lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms-debug.js b/lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms-debug.js index ec41c73bb3c..316e90e609f 100644 --- a/lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms-debug.js +++ b/lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms-debug.js @@ -81,6 +81,9 @@ Y.extend(SHORTFORMS, Y.Base, { form.delegate('click', this.switch_state, SELECTORS.FIELDSETLEGENDLINK, this); form.delegate('key', this.switch_state, 'down:enter,32', SELECTORS.FIELDSETLEGENDLINK, this); + // Handle event, when there's an error in collapsed section. + Y.Global.on(M.core.globalEvents.FORM_ERROR, this.expand_fieldset, this); + // Make the collapse/expand a link. btn = form.one(SELECTORS.COLLAPSEEXPAND); if (btn) { @@ -232,7 +235,24 @@ Y.extend(SHORTFORMS, Y.Base, { } return this; - } + }, + /** + * Expand the fieldset, which contains an error. + * + * @method expand_fieldset + * @param {EventFacade} e + */ + expand_fieldset: function(e) { + e.stopPropagation(); + var formid = e.formid; + if (formid === this.form.getAttribute('id')) { + var errorfieldset = Y.one('#' + e.elementid).ancestor('fieldset'); + if (errorfieldset) { + this.set_state(errorfieldset, false); + } + + } + } }, { NAME: 'moodle-form-shortforms', ATTRS: ATTRS @@ -244,4 +264,4 @@ M.form.shortforms = M.form.shortforms || function(params) { }; -}, '@VERSION@', {"requires": ["node", "base", "selector-css3"]}); +}, '@VERSION@', {"requires": ["node", "base", "selector-css3", "moodle-core-event"]}); diff --git a/lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms-min.js b/lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms-min.js index b7d0861331e..b6075a95e63 100644 --- a/lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms-min.js +++ b/lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms-min.js @@ -1 +1 @@ -YUI.add("moodle-form-shortforms",function(e,t){function n(){n.superclass.constructor.apply(this,arguments)}var r={COLLAPSEEXPAND:".collapsible-actions .collapseexpand",COLLAPSED:".collapsed",FIELDSETCOLLAPSIBLE:"fieldset.collapsible",FIELDSETLEGENDLINK:"fieldset.collapsible .fheader",FHEADER:".fheader",LEGENDFTOGGLER:"legend.ftoggler"},i={COLLAPSEALL:"collapse-all",COLLAPSED:"collapsed",FHEADER:"fheader"},s={};s.formid={value:null},e.extend(n,e.Base,{form:null,initializer:function(){var t=e.one("#"+this.get("formid")),n,i,s,o;if(!t)return;this.form=t,n=t.all(r.FIELDSETCOLLAPSIBLE),n.each(this.process_fieldset,this),t.delegate("click",this.switch_state,r.FIELDSETLEGENDLINK,this),t.delegate("key",this.switch_state,"down:enter,32",r.FIELDSETLEGENDLINK,this),i=t.one(r.COLLAPSEEXPAND),i&&(s=e.Node.create(''),s.setHTML(i.getHTML()),s.setAttribute("class",i.getAttribute("class")),s.setAttribute("role","button"),o=[],t.all(r.FIELDSETLEGENDLINK).each(function(e){o[o.length]=e.generateID()}),s.setAttribute("aria-controls",o.join(" ")),s.on("click",this.set_state_all,this,!0),s.on("key",this.set_state_all,"down:enter,32",this,!0),i.replace(s),this.update_btns(t))},process_fieldset:function(t){var n=t.one(r.LEGENDFTOGGLER),s=e.Node.create('');return s.addClass(i.FHEADER),s.appendChild(n.get("firstChild")),s.setAttribute("role","button"),s.setAttribute("aria-controls",t.generateID()),n.ancestor(r.COLLAPSED)?s.setAttribute("aria-expanded","false"):s.setAttribute("aria-expanded","true"),n.prepend(s),this},set_state:function(e,t){var n=e.one(r.FHEADER);t?(e.addClass(i.COLLAPSED),n&&n.setAttribute("aria-expanded","false")):(e.removeClass(i.COLLAPSED),n&&n.setAttribute("aria-expanded","true"));var s=this.form.one("input[name=mform_isexpanded_"+e.get("id")+"]");return s?(s.set("value",t?0:1),this):this},set_state_all:function(e){e.preventDefault();var t=e.target.hasClass(i.COLLAPSEALL),n=this.form.all(r.FIELDSETCOLLAPSIBLE);n.each(function(e){this.set_state(e,t)},this),this.update_btns()},switch_state:function(e){e.preventDefault();var t=e.target.ancestor(r.FIELDSETCOLLAPSIBLE);this.set_state(t,!t.hasClass(i.COLLAPSED)),this.update_btns()},update_btns:function(){var e,t=0,n=!1,s;return e=this.form.one(r.COLLAPSEEXPAND),e?(s=this.form.all(r.FIELDSETCOLLAPSIBLE),s.each(function(e){e.hasClass(i.COLLAPSED)&&t++}),t!==0&&(n=!0),n?(e.removeClass(i.COLLAPSEALL),e.setHTML(M.util.get_string("expandall","moodle"))):(e.addClass(i.COLLAPSEALL),e.setHTML(M.util.get_string("collapseall","moodle"))),this):this}},{NAME:"moodle-form-shortforms",ATTRS:s}),M.form=M.form||{},M.form.shortforms=M.form.shortforms||function(e){return new n(e)}},"@VERSION@",{requires:["node","base","selector-css3"]}); +YUI.add("moodle-form-shortforms",function(e,t){function n(){n.superclass.constructor.apply(this,arguments)}var r={COLLAPSEEXPAND:".collapsible-actions .collapseexpand",COLLAPSED:".collapsed",FIELDSETCOLLAPSIBLE:"fieldset.collapsible",FIELDSETLEGENDLINK:"fieldset.collapsible .fheader",FHEADER:".fheader",LEGENDFTOGGLER:"legend.ftoggler"},i={COLLAPSEALL:"collapse-all",COLLAPSED:"collapsed",FHEADER:"fheader"},s={};s.formid={value:null},e.extend(n,e.Base,{form:null,initializer:function(){var t=e.one("#"+this.get("formid")),n,i,s,o;if(!t)return;this.form=t,n=t.all(r.FIELDSETCOLLAPSIBLE),n.each(this.process_fieldset,this),t.delegate("click",this.switch_state,r.FIELDSETLEGENDLINK,this),t.delegate("key",this.switch_state,"down:enter,32",r.FIELDSETLEGENDLINK,this),e.Global.on(M.core.globalEvents.FORM_ERROR,this.expand_fieldset,this),i=t.one(r.COLLAPSEEXPAND),i&&(s=e.Node.create(''),s.setHTML(i.getHTML()),s.setAttribute("class",i.getAttribute("class")),s.setAttribute("role","button"),o=[],t.all(r.FIELDSETLEGENDLINK).each(function(e){o[o.length]=e.generateID()}),s.setAttribute("aria-controls",o.join(" ")),s.on("click",this.set_state_all,this,!0),s.on("key",this.set_state_all,"down:enter,32",this,!0),i.replace(s),this.update_btns(t))},process_fieldset:function(t){var n=t.one(r.LEGENDFTOGGLER),s=e.Node.create('');return s.addClass(i.FHEADER),s.appendChild(n.get("firstChild")),s.setAttribute("role","button"),s.setAttribute("aria-controls",t.generateID()),n.ancestor(r.COLLAPSED)?s.setAttribute("aria-expanded","false"):s.setAttribute("aria-expanded","true"),n.prepend(s),this},set_state:function(e,t){var n=e.one(r.FHEADER);t?(e.addClass(i.COLLAPSED),n&&n.setAttribute("aria-expanded","false")):(e.removeClass(i.COLLAPSED),n&&n.setAttribute("aria-expanded","true"));var s=this.form.one("input[name=mform_isexpanded_"+e.get("id")+"]");return s?(s.set("value",t?0:1),this):this},set_state_all:function(e){e.preventDefault();var t=e.target.hasClass(i.COLLAPSEALL),n=this.form.all(r.FIELDSETCOLLAPSIBLE);n.each(function(e){this.set_state(e,t)},this),this.update_btns()},switch_state:function(e){e.preventDefault();var t=e.target.ancestor(r.FIELDSETCOLLAPSIBLE);this.set_state(t,!t.hasClass(i.COLLAPSED)),this.update_btns()},update_btns:function(){var e,t=0,n=!1,s;return e=this.form.one(r.COLLAPSEEXPAND),e?(s=this.form.all(r.FIELDSETCOLLAPSIBLE),s.each(function(e){e.hasClass(i.COLLAPSED)&&t++}),t!==0&&(n=!0),n?(e.removeClass(i.COLLAPSEALL),e.setHTML(M.util.get_string("expandall","moodle"))):(e.addClass(i.COLLAPSEALL),e.setHTML(M.util.get_string("collapseall","moodle"))),this):this},expand_fieldset:function(t){t.stopPropagation();var n=t.formid;if(n===this.form.getAttribute("id")){var r=e.one("#"+t.elementid).ancestor("fieldset");r&&this.set_state(r,!1)}}},{NAME:"moodle-form-shortforms",ATTRS:s}),M.form=M.form||{},M.form.shortforms=M.form.shortforms||function(e){return new n(e)}},"@VERSION@",{requires:["node","base","selector-css3","moodle-core-event"]}); diff --git a/lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms.js b/lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms.js index e7e138f7229..2b8105794f8 100644 --- a/lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms.js +++ b/lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms.js @@ -80,6 +80,9 @@ Y.extend(SHORTFORMS, Y.Base, { form.delegate('click', this.switch_state, SELECTORS.FIELDSETLEGENDLINK, this); form.delegate('key', this.switch_state, 'down:enter,32', SELECTORS.FIELDSETLEGENDLINK, this); + // Handle event, when there's an error in collapsed section. + Y.Global.on(M.core.globalEvents.FORM_ERROR, this.expand_fieldset, this); + // Make the collapse/expand a link. btn = form.one(SELECTORS.COLLAPSEEXPAND); if (btn) { @@ -229,7 +232,24 @@ Y.extend(SHORTFORMS, Y.Base, { } return this; - } + }, + /** + * Expand the fieldset, which contains an error. + * + * @method expand_fieldset + * @param {EventFacade} e + */ + expand_fieldset: function(e) { + e.stopPropagation(); + var formid = e.formid; + if (formid === this.form.getAttribute('id')) { + var errorfieldset = Y.one('#' + e.elementid).ancestor('fieldset'); + if (errorfieldset) { + this.set_state(errorfieldset, false); + } + + } + } }, { NAME: 'moodle-form-shortforms', ATTRS: ATTRS @@ -241,4 +261,4 @@ M.form.shortforms = M.form.shortforms || function(params) { }; -}, '@VERSION@', {"requires": ["node", "base", "selector-css3"]}); +}, '@VERSION@', {"requires": ["node", "base", "selector-css3", "moodle-core-event"]}); diff --git a/lib/form/yui/src/shortforms/js/shortforms.js b/lib/form/yui/src/shortforms/js/shortforms.js index 14181caf187..f532a415485 100644 --- a/lib/form/yui/src/shortforms/js/shortforms.js +++ b/lib/form/yui/src/shortforms/js/shortforms.js @@ -79,6 +79,9 @@ Y.extend(SHORTFORMS, Y.Base, { form.delegate('click', this.switch_state, SELECTORS.FIELDSETLEGENDLINK, this); form.delegate('key', this.switch_state, 'down:enter,32', SELECTORS.FIELDSETLEGENDLINK, this); + // Handle event, when there's an error in collapsed section. + Y.Global.on(M.core.globalEvents.FORM_ERROR, this.expand_fieldset, this); + // Make the collapse/expand a link. btn = form.one(SELECTORS.COLLAPSEEXPAND); if (btn) { @@ -230,7 +233,24 @@ Y.extend(SHORTFORMS, Y.Base, { } return this; - } + }, + /** + * Expand the fieldset, which contains an error. + * + * @method expand_fieldset + * @param {EventFacade} e + */ + expand_fieldset: function(e) { + e.stopPropagation(); + var formid = e.formid; + if (formid === this.form.getAttribute('id')) { + var errorfieldset = Y.one('#' + e.elementid).ancestor('fieldset'); + if (errorfieldset) { + this.set_state(errorfieldset, false); + } + + } + } }, { NAME: 'moodle-form-shortforms', ATTRS: ATTRS diff --git a/lib/form/yui/src/shortforms/meta/shortforms.json b/lib/form/yui/src/shortforms/meta/shortforms.json index 7d6bb01145e..768ab2863a1 100644 --- a/lib/form/yui/src/shortforms/meta/shortforms.json +++ b/lib/form/yui/src/shortforms/meta/shortforms.json @@ -3,7 +3,8 @@ "requires": [ "node", "base", - "selector-css3" + "selector-css3", + "moodle-core-event" ] } } diff --git a/lib/formslib.php b/lib/formslib.php index 88564a784ad..31f32d74441 100644 --- a/lib/formslib.php +++ b/lib/formslib.php @@ -2229,6 +2229,8 @@ function validate_' . $this->_formName . '_' . $escapedElementName . '(element) ret = validate_' . $this->_formName . '_' . $escapedElementName.'(frm.elements[\''.$elementName.'\']) && ret; if (!ret && !first_focus) { first_focus = true; + Y.Global.fire(M.core.globalEvents.FORM_ERROR, {formid: \''. $this->_attributes['id'] .'\', + elementid: \'id_error_'.$elementName.'\'}); document.getElementById(\'id_error_'.$elementName.'\').focus(); } '; diff --git a/lib/yui/build/moodle-core-event/moodle-core-event-debug.js b/lib/yui/build/moodle-core-event/moodle-core-event-debug.js index 9bb34797b66..cbf3e398621 100644 --- a/lib/yui/build/moodle-core-event/moodle-core-event-debug.js +++ b/lib/yui/build/moodle-core-event/moodle-core-event-debug.js @@ -44,6 +44,17 @@ M.core.event = { FILTER_CONTENT_UPDATED: "filter-content-updated" }; +M.core.globalEvents = { + /** + * This event is triggered when form has an error + * + * @event "form_error" + * @param formid {string} Id of form with error. + * @param elementid {string} Id of element with error. + */ + FORM_ERROR: "form_error" +}; + var eventDefaultConfig = { emitFacade: true, @@ -58,6 +69,8 @@ var eventDefaultConfig = { } }; +// Publish events with a custom config here. + // Publish all the events with a standard config. var key; for (key in M.core.event) { @@ -66,7 +79,12 @@ for (key in M.core.event) { } } -// Publish events with a custom config here. +//Publish all the global events. +for (key in M.core.globalEvents) { + if (M.core.globalEvents.hasOwnProperty(key)) { + Y.Global.publish(M.core.globalEvents[key], Y.merge(eventDefaultConfig, {broadcast: 2})); + } +} }, '@VERSION@', {"requires": ["event-custom"]}); diff --git a/lib/yui/build/moodle-core-event/moodle-core-event-min.js b/lib/yui/build/moodle-core-event/moodle-core-event-min.js index b0168680ce5..426af2f01e0 100644 --- a/lib/yui/build/moodle-core-event/moodle-core-event-min.js +++ b/lib/yui/build/moodle-core-event/moodle-core-event-min.js @@ -1 +1 @@ -YUI.add("moodle-core-event",function(e,t){var n="moodle-core-event";M.core=M.core||{},M.core.event={FILTER_CONTENT_UPDATED:"filter-content-updated"};var r={emitFacade:!0,defaultFn:function(e){},preventedFn:function(e){},stoppedFn:function(e){}},i;for(i in M.core.event)M.core.event.hasOwnProperty(i)&&e.publish(M.core.event[i],r)},"@VERSION@",{requires:["event-custom"]}); +YUI.add("moodle-core-event",function(e,t){var n="moodle-core-event";M.core=M.core||{},M.core.event={FILTER_CONTENT_UPDATED:"filter-content-updated"},M.core.globalEvents={FORM_ERROR:"form_error"};var r={emitFacade:!0,defaultFn:function(e){},preventedFn:function(e){},stoppedFn:function(e){}},i;for(i in M.core.event)M.core.event.hasOwnProperty(i)&&e.publish(M.core.event[i],r);for(i in M.core.globalEvents)M.core.globalEvents.hasOwnProperty(i)&&e.Global.publish(M.core.globalEvents[i],e.merge(r,{broadcast:2}))},"@VERSION@",{requires:["event-custom"]}); diff --git a/lib/yui/build/moodle-core-event/moodle-core-event.js b/lib/yui/build/moodle-core-event/moodle-core-event.js index d2c481f2c0e..2a9e77668ce 100644 --- a/lib/yui/build/moodle-core-event/moodle-core-event.js +++ b/lib/yui/build/moodle-core-event/moodle-core-event.js @@ -44,6 +44,17 @@ M.core.event = { FILTER_CONTENT_UPDATED: "filter-content-updated" }; +M.core.globalEvents = { + /** + * This event is triggered when form has an error + * + * @event "form_error" + * @param formid {string} Id of form with error. + * @param elementid {string} Id of element with error. + */ + FORM_ERROR: "form_error" +}; + var eventDefaultConfig = { emitFacade: true, @@ -55,6 +66,8 @@ var eventDefaultConfig = { } }; +// Publish events with a custom config here. + // Publish all the events with a standard config. var key; for (key in M.core.event) { @@ -63,7 +76,12 @@ for (key in M.core.event) { } } -// Publish events with a custom config here. +//Publish all the global events. +for (key in M.core.globalEvents) { + if (M.core.globalEvents.hasOwnProperty(key)) { + Y.Global.publish(M.core.globalEvents[key], Y.merge(eventDefaultConfig, {broadcast: 2})); + } +} }, '@VERSION@', {"requires": ["event-custom"]}); diff --git a/lib/yui/src/event/js/event.js b/lib/yui/src/event/js/event.js index 39fe4f6c862..6f6a28adb9d 100644 --- a/lib/yui/src/event/js/event.js +++ b/lib/yui/src/event/js/event.js @@ -42,6 +42,17 @@ M.core.event = { FILTER_CONTENT_UPDATED: "filter-content-updated" }; +M.core.globalEvents = { + /** + * This event is triggered when form has an error + * + * @event "form_error" + * @param formid {string} Id of form with error. + * @param elementid {string} Id of element with error. + */ + FORM_ERROR: "form_error" +}; + var eventDefaultConfig = { emitFacade: true, @@ -56,6 +67,8 @@ var eventDefaultConfig = { } }; +// Publish events with a custom config here. + // Publish all the events with a standard config. var key; for (key in M.core.event) { @@ -64,4 +77,9 @@ for (key in M.core.event) { } } -// Publish events with a custom config here. +//Publish all the global events. +for (key in M.core.globalEvents) { + if (M.core.globalEvents.hasOwnProperty(key)) { + Y.Global.publish(M.core.globalEvents[key], Y.merge(eventDefaultConfig, {broadcast: 2})); + } +}