From 5e4ef61c00d0dfa2ef827c8060cb568c407433b8 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Wed, 4 Dec 2013 22:24:32 +0800 Subject: [PATCH] MDL-38775 JavaScript: Migrate moodle-form-shortforms to Shifter --- .../moodle-form-shortforms-debug.js | 233 ++++++++++++++++++ .../moodle-form-shortforms-min.js | 1 + .../moodle-form-shortforms.js | 230 +++++++++++++++++ lib/form/yui/shortforms/shortforms.js | 186 -------------- lib/form/yui/src/shortforms/build.json | 10 + lib/form/yui/src/shortforms/js/shortforms.js | 228 +++++++++++++++++ .../yui/src/shortforms/meta/shortforms.json | 9 + 7 files changed, 711 insertions(+), 186 deletions(-) create mode 100644 lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms-debug.js create mode 100644 lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms-min.js create mode 100644 lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms.js delete mode 100644 lib/form/yui/shortforms/shortforms.js create mode 100644 lib/form/yui/src/shortforms/build.json create mode 100644 lib/form/yui/src/shortforms/js/shortforms.js create mode 100644 lib/form/yui/src/shortforms/meta/shortforms.json 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 new file mode 100644 index 00000000000..5da2694cbb9 --- /dev/null +++ b/lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms-debug.js @@ -0,0 +1,233 @@ +YUI.add('moodle-form-shortforms', function (Y, NAME) { + +/** + * Provides the form shortforms class. + * + * @module moodle-form-shortforms + */ + +/** + * A class for a shortforms. + * + * @class M.form.shortforms + * @constructor + * @extends Base + */ +function SHORTFORMS() { + SHORTFORMS.superclass.constructor.apply(this, arguments); +} + +var SELECTORS = { + COLLAPSEEXPAND: '.collapsible-actions .collapseexpand', + FIELDSETCOLLAPSIBLE: 'fieldset.collapsible', + FIELDSETLEGENDLINK: 'fieldset.collapsible .fheader', + LEGENDFTOGGLER: 'legend.ftoggler' + }, + CSS = { + COLLAPSEALL: 'collapse-all', + COLLAPSED: 'collapsed', + FHEADER: 'fheader' + }, + ATTRS = {}; + +/** + * The form ID attribute definition. + * + * @attribute formid + * @type String + * @default '' + * @writeOnce + */ +ATTRS.formid = { + value: null +}; + +Y.extend(SHORTFORMS, Y.Base, { + /** + * A reference to the form. + * + * @property form + * @protected + * @type Node + * @default null + */ + form: null, + + /** + * The initializer for the shortforms instance. + * + * @method initializer + * @protected + */ + initializer: function() { + var form = Y.one('#'+this.get('formid')), + fieldlist, + btn, + link, + idlist; + if (!form) { + Y.log('Could not locate the form', 'warn', 'moodle-form-shortforms'); + return; + } + // Stores the form in the object. + this.form = form; + // Look through collapsible fieldset divs. + fieldlist = form.all(SELECTORS.FIELDSETCOLLAPSIBLE); + fieldlist.each(this.process_fieldset, this); + + // Subscribe collapsible fieldsets and buttons to click events. + form.delegate('click', this.switch_state, SELECTORS.FIELDSETLEGENDLINK, this); + form.delegate('key', this.switch_state, 'down:enter,32', SELECTORS.FIELDSETLEGENDLINK, this); + + // Make the collapse/expand a link. + btn = form.one(SELECTORS.COLLAPSEEXPAND); + if (btn) { + link = Y.Node.create(''); + link.setHTML(btn.getHTML()); + link.setAttribute('class', btn.getAttribute('class')); + link.setAttribute('role', 'button'); + + // Get list of IDs controlled by this button to set the aria-controls attribute. + idlist = []; + form.all(SELECTORS.FIELDSETLEGENDLINK).each(function(node) { + idlist[idlist.length] = node.generateID(); + }); + link.setAttribute('aria-controls', idlist.join(' ')); + + // Placing the button and binding the event. + link.on('click', this.set_state_all, this, true); + link.on('key', this.set_state_all, 'down:enter,32', this, true); + btn.replace(link); + this.update_btns(form); + } + }, + + /** + * Process the supplied fieldset to add appropriate links, and ARIA + * roles. + * + * @method process_fieldset + * @param {Node} fieldset The Node relating to the fieldset to add collapsing to. + * @chainable + */ + process_fieldset: function(fieldset) { + // Get legend element. + var legendelement = fieldset.one(SELECTORS.LEGENDFTOGGLER); + + // Turn headers to links for accessibility. + var headerlink = Y.Node.create(''); + headerlink.addClass(CSS.FHEADER); + headerlink.appendChild(legendelement.get('firstChild')); + headerlink.setAttribute('role', 'button'); + headerlink.setAttribute('aria-controls', fieldset.generateID()); + legendelement.prepend(headerlink); + + return this; + }, + + /** + * Set the collapsed state for the specified fieldset. + * + * @method set_state + * @param {Node} fieldset The Node relating to the fieldset to set state on. + * @param {Boolean} [collapsed] Whether the fieldset is collapsed. + * @chainable + */ + set_state: function(fieldset, collapsed) { + if (collapsed) { + fieldset.addClass(CSS.COLLAPSED); + } else { + fieldset.removeClass(CSS.COLLAPSED); + } + var statuselement = this.form.one('input[name=mform_isexpanded_'+fieldset.get('id')+']'); + if (!statuselement) { + Y.log("M.form.shortforms::switch_state was called on an fieldset without a status field: '" + + fieldset.get('id') + "'", 'debug', 'moodle-form-shortforms'); + return this; + } + statuselement.set('value', collapsed ? 0: 1); + + return this; + }, + + /** + * Set the state for all fieldsets in the form. + * + * @method set_state_all + * @param {EventFacade} e + */ + set_state_all: function(e) { + e.preventDefault(); + var collapsed = e.target.hasClass(CSS.COLLAPSEALL), + fieldlist = this.form.all(SELECTORS.FIELDSETCOLLAPSIBLE); + fieldlist.each(function(node) { + this.set_state(node, collapsed); + }, this); + this.update_btns(); + }, + + /** + * Toggle the state for the fieldset that was clicked. + * + * @method switch_state + * @param {EventFacade} e + */ + switch_state: function(e) { + e.preventDefault(); + var fieldset = e.target.ancestor(SELECTORS.FIELDSETCOLLAPSIBLE); + this.set_state(fieldset, !fieldset.hasClass(CSS.COLLAPSED)); + this.update_btns(); + }, + + /** + * Update the Expand/Collapse all buttons as required. + * + * @method update_btns + * @chainable + */ + update_btns: function() { + var btn, + collapsed = 0, + expandbtn = false, + fieldlist; + + btn = this.form.one(SELECTORS.COLLAPSEEXPAND); + if (!btn) { + return this; + } + + // Counting the number of collapsed sections. + fieldlist = this.form.all(SELECTORS.FIELDSETCOLLAPSIBLE); + fieldlist.each(function(node) { + if (node.hasClass(CSS.COLLAPSED)) { + collapsed++; + } + }); + + if (collapsed !== 0) { + expandbtn = true; + } + + // Updating the button. + if (expandbtn) { + btn.removeClass(CSS.COLLAPSEALL); + btn.setHTML(M.util.get_string('expandall', 'moodle')); + } else { + btn.addClass(CSS.COLLAPSEALL); + btn.setHTML(M.util.get_string('collapseall', 'moodle')); + } + + return this; + } +}, { + NAME: 'moodle-form-shortforms', + ATTRS: ATTRS +}); + +M.form = M.form || {}; +M.form.shortforms = M.form.shortforms || function(params) { + return new SHORTFORMS(params); +}; + + +}, '@VERSION@', {"requires": ["node", "base", "selector-css3"]}); 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 new file mode 100644 index 00000000000..4bdf46b13ea --- /dev/null +++ b/lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms-min.js @@ -0,0 +1 @@ +YUI.add("moodle-form-shortforms",function(e,t){function n(){n.superclass.constructor.apply(this,arguments)}var r={COLLAPSEEXPAND:".collapsible-actions .collapseexpand",FIELDSETCOLLAPSIBLE:"fieldset.collapsible",FIELDSETLEGENDLINK:"fieldset.collapsible .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.prepend(s),this},set_state:function(e,t){t?e.addClass(i.COLLAPSED):e.removeClass(i.COLLAPSED);var n=this.form.one("input[name=mform_isexpanded_"+e.get("id")+"]");return n?(n.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"]}); 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 new file mode 100644 index 00000000000..2691a0da9c5 --- /dev/null +++ b/lib/form/yui/build/moodle-form-shortforms/moodle-form-shortforms.js @@ -0,0 +1,230 @@ +YUI.add('moodle-form-shortforms', function (Y, NAME) { + +/** + * Provides the form shortforms class. + * + * @module moodle-form-shortforms + */ + +/** + * A class for a shortforms. + * + * @class M.form.shortforms + * @constructor + * @extends Base + */ +function SHORTFORMS() { + SHORTFORMS.superclass.constructor.apply(this, arguments); +} + +var SELECTORS = { + COLLAPSEEXPAND: '.collapsible-actions .collapseexpand', + FIELDSETCOLLAPSIBLE: 'fieldset.collapsible', + FIELDSETLEGENDLINK: 'fieldset.collapsible .fheader', + LEGENDFTOGGLER: 'legend.ftoggler' + }, + CSS = { + COLLAPSEALL: 'collapse-all', + COLLAPSED: 'collapsed', + FHEADER: 'fheader' + }, + ATTRS = {}; + +/** + * The form ID attribute definition. + * + * @attribute formid + * @type String + * @default '' + * @writeOnce + */ +ATTRS.formid = { + value: null +}; + +Y.extend(SHORTFORMS, Y.Base, { + /** + * A reference to the form. + * + * @property form + * @protected + * @type Node + * @default null + */ + form: null, + + /** + * The initializer for the shortforms instance. + * + * @method initializer + * @protected + */ + initializer: function() { + var form = Y.one('#'+this.get('formid')), + fieldlist, + btn, + link, + idlist; + if (!form) { + return; + } + // Stores the form in the object. + this.form = form; + // Look through collapsible fieldset divs. + fieldlist = form.all(SELECTORS.FIELDSETCOLLAPSIBLE); + fieldlist.each(this.process_fieldset, this); + + // Subscribe collapsible fieldsets and buttons to click events. + form.delegate('click', this.switch_state, SELECTORS.FIELDSETLEGENDLINK, this); + form.delegate('key', this.switch_state, 'down:enter,32', SELECTORS.FIELDSETLEGENDLINK, this); + + // Make the collapse/expand a link. + btn = form.one(SELECTORS.COLLAPSEEXPAND); + if (btn) { + link = Y.Node.create(''); + link.setHTML(btn.getHTML()); + link.setAttribute('class', btn.getAttribute('class')); + link.setAttribute('role', 'button'); + + // Get list of IDs controlled by this button to set the aria-controls attribute. + idlist = []; + form.all(SELECTORS.FIELDSETLEGENDLINK).each(function(node) { + idlist[idlist.length] = node.generateID(); + }); + link.setAttribute('aria-controls', idlist.join(' ')); + + // Placing the button and binding the event. + link.on('click', this.set_state_all, this, true); + link.on('key', this.set_state_all, 'down:enter,32', this, true); + btn.replace(link); + this.update_btns(form); + } + }, + + /** + * Process the supplied fieldset to add appropriate links, and ARIA + * roles. + * + * @method process_fieldset + * @param {Node} fieldset The Node relating to the fieldset to add collapsing to. + * @chainable + */ + process_fieldset: function(fieldset) { + // Get legend element. + var legendelement = fieldset.one(SELECTORS.LEGENDFTOGGLER); + + // Turn headers to links for accessibility. + var headerlink = Y.Node.create(''); + headerlink.addClass(CSS.FHEADER); + headerlink.appendChild(legendelement.get('firstChild')); + headerlink.setAttribute('role', 'button'); + headerlink.setAttribute('aria-controls', fieldset.generateID()); + legendelement.prepend(headerlink); + + return this; + }, + + /** + * Set the collapsed state for the specified fieldset. + * + * @method set_state + * @param {Node} fieldset The Node relating to the fieldset to set state on. + * @param {Boolean} [collapsed] Whether the fieldset is collapsed. + * @chainable + */ + set_state: function(fieldset, collapsed) { + if (collapsed) { + fieldset.addClass(CSS.COLLAPSED); + } else { + fieldset.removeClass(CSS.COLLAPSED); + } + var statuselement = this.form.one('input[name=mform_isexpanded_'+fieldset.get('id')+']'); + if (!statuselement) { + return this; + } + statuselement.set('value', collapsed ? 0: 1); + + return this; + }, + + /** + * Set the state for all fieldsets in the form. + * + * @method set_state_all + * @param {EventFacade} e + */ + set_state_all: function(e) { + e.preventDefault(); + var collapsed = e.target.hasClass(CSS.COLLAPSEALL), + fieldlist = this.form.all(SELECTORS.FIELDSETCOLLAPSIBLE); + fieldlist.each(function(node) { + this.set_state(node, collapsed); + }, this); + this.update_btns(); + }, + + /** + * Toggle the state for the fieldset that was clicked. + * + * @method switch_state + * @param {EventFacade} e + */ + switch_state: function(e) { + e.preventDefault(); + var fieldset = e.target.ancestor(SELECTORS.FIELDSETCOLLAPSIBLE); + this.set_state(fieldset, !fieldset.hasClass(CSS.COLLAPSED)); + this.update_btns(); + }, + + /** + * Update the Expand/Collapse all buttons as required. + * + * @method update_btns + * @chainable + */ + update_btns: function() { + var btn, + collapsed = 0, + expandbtn = false, + fieldlist; + + btn = this.form.one(SELECTORS.COLLAPSEEXPAND); + if (!btn) { + return this; + } + + // Counting the number of collapsed sections. + fieldlist = this.form.all(SELECTORS.FIELDSETCOLLAPSIBLE); + fieldlist.each(function(node) { + if (node.hasClass(CSS.COLLAPSED)) { + collapsed++; + } + }); + + if (collapsed !== 0) { + expandbtn = true; + } + + // Updating the button. + if (expandbtn) { + btn.removeClass(CSS.COLLAPSEALL); + btn.setHTML(M.util.get_string('expandall', 'moodle')); + } else { + btn.addClass(CSS.COLLAPSEALL); + btn.setHTML(M.util.get_string('collapseall', 'moodle')); + } + + return this; + } +}, { + NAME: 'moodle-form-shortforms', + ATTRS: ATTRS +}); + +M.form = M.form || {}; +M.form.shortforms = M.form.shortforms || function(params) { + return new SHORTFORMS(params); +}; + + +}, '@VERSION@', {"requires": ["node", "base", "selector-css3"]}); diff --git a/lib/form/yui/shortforms/shortforms.js b/lib/form/yui/shortforms/shortforms.js deleted file mode 100644 index 6da2007d12d..00000000000 --- a/lib/form/yui/shortforms/shortforms.js +++ /dev/null @@ -1,186 +0,0 @@ -YUI.add('moodle-form-shortforms', function(Y) { - /** - * Provides the form shortforms class. - * - * @module moodle-form-shortforms - */ - - /** - * A class for a shortforms. - * - * @param {Object} config Object literal specifying shortforms configuration properties. - * @class M.form.shortforms - * @constructor - * @extends Y.Base - */ - function SHORTFORMS(config) { - SHORTFORMS.superclass.constructor.apply(this, [config]); - } - - var SELECTORS = { - COLLAPSEEXPAND : '.collapsible-actions .collapseexpand', - FIELDSETCOLLAPSIBLE : 'fieldset.collapsible', - FIELDSETLEGENDLINK : 'fieldset.collapsible .fheader', - LEGENDFTOGGLER : 'legend.ftoggler' - }, - CSS = { - COLLAPSEALL : 'collapse-all', - COLLAPSED : 'collapsed', - FHEADER : 'fheader' - }, - ATTRS = {}; - - /** - * Static property provides a string to identify the JavaScript class. - * - * @property NAME - * @type String - * @static - */ - SHORTFORMS.NAME = 'moodle-form-shortforms'; - - /** - * Static property used to define the default attribute configuration for the Shortform. - * - * @property ATTRS - * @type String - * @static - */ - SHORTFORMS.ATTRS = ATTRS; - - /** - * The form ID attribute definition. - * - * @attribute formid - * @type String - * @default '' - * @writeOnce - */ - ATTRS.formid = { - value : null - }; - - Y.extend(SHORTFORMS, Y.Base, { - form: null, - initializer : function() { - var form = Y.one('#'+this.get('formid')), - fieldlist, - btn, - link, - idlist; - if (!form) { - Y.log('Could not locate the form', 'debug'); - return; - } - // Stores the form in the object. - this.form = form; - // Look through collapsible fieldset divs. - fieldlist = form.all(SELECTORS.FIELDSETCOLLAPSIBLE); - fieldlist.each(this.process_fieldset, this); - - // Subscribe collapsible fieldsets and buttons to click events. - form.delegate('click', this.switch_state, SELECTORS.FIELDSETLEGENDLINK, this); - form.delegate('key', this.switch_state, 'down:enter,32', SELECTORS.FIELDSETLEGENDLINK, this); - - // Make the collapse/expand a link. - btn = form.one(SELECTORS.COLLAPSEEXPAND); - if (btn) { - link = Y.Node.create(''); - link.setHTML(btn.getHTML()); - link.setAttribute('class', btn.getAttribute('class')); - link.setAttribute('role', 'button'); - - // Get list of IDs controlled by this button to set the aria-controls attribute. - idlist = []; - form.all(SELECTORS.FIELDSETLEGENDLINK).each(function(node) { - idlist[idlist.length] = node.generateID(); - }); - link.setAttribute('aria-controls', idlist.join(' ')); - - // Placing the button and binding the event. - link.on('click', this.set_state_all, this, true); - link.on('key', this.set_state_all, 'down:enter,32', this, true); - btn.replace(link); - this.update_btns(form); - } - }, - process_fieldset : function(fieldset) { - // Get legend element. - var legendelement = fieldset.one(SELECTORS.LEGENDFTOGGLER); - - // Turn headers to links for accessibility. - var headerlink = Y.Node.create(''); - headerlink.addClass(CSS.FHEADER); - headerlink.appendChild(legendelement.get('firstChild')); - headerlink.setAttribute('role', 'button'); - headerlink.setAttribute('aria-controls', fieldset.generateID()); - legendelement.prepend(headerlink); - }, - set_state: function(fieldset, collapsed) { - if (collapsed) { - fieldset.addClass(CSS.COLLAPSED); - } else { - fieldset.removeClass(CSS.COLLAPSED); - } - var statuselement = this.form.one('input[name=mform_isexpanded_'+fieldset.get('id')+']'); - if (!statuselement) { - Y.log("M.form.shortforms::switch_state was called on an fieldset without a status field: '" + - fieldset.get('id') + "'", 'debug'); - return; - } - statuselement.set('value', collapsed ? 0 : 1); - }, - set_state_all: function(e) { - e.preventDefault(); - var collapsed = e.target.hasClass(CSS.COLLAPSEALL), - fieldlist = this.form.all(SELECTORS.FIELDSETCOLLAPSIBLE); - fieldlist.each(function(node) { - this.set_state(node, collapsed); - }, this); - this.update_btns(); - }, - switch_state : function(e) { - e.preventDefault(); - var fieldset = e.target.ancestor(SELECTORS.FIELDSETCOLLAPSIBLE); - this.set_state(fieldset, !fieldset.hasClass(CSS.COLLAPSED)); - this.update_btns(); - }, - update_btns: function() { - var btn, - collapsed = 0, - expandbtn = false, - fieldlist; - - btn = this.form.one(SELECTORS.COLLAPSEEXPAND); - if (!btn) { - return; - } - - // Counting the number of collapsed sections. - fieldlist = this.form.all(SELECTORS.FIELDSETCOLLAPSIBLE); - fieldlist.each(function(node) { - if (node.hasClass(CSS.COLLAPSED)) { - collapsed++; - } - }); - - if (collapsed !== 0) { - expandbtn = true; - } - - // Updating the button. - if (expandbtn) { - btn.removeClass(CSS.COLLAPSEALL); - btn.setHTML(M.util.get_string('expandall', 'moodle')); - } else { - btn.addClass(CSS.COLLAPSEALL); - btn.setHTML(M.util.get_string('collapseall', 'moodle')); - } - } - }); - - M.form = M.form || {}; - M.form.shortforms = M.form.shortforms || function(params) { - return new SHORTFORMS(params); - }; -}, '@VERSION@', {requires:['base', 'node', 'selector-css3']}); diff --git a/lib/form/yui/src/shortforms/build.json b/lib/form/yui/src/shortforms/build.json new file mode 100644 index 00000000000..9f93b6ea057 --- /dev/null +++ b/lib/form/yui/src/shortforms/build.json @@ -0,0 +1,10 @@ +{ + "name": "moodle-form-shortforms", + "builds": { + "moodle-form-shortforms": { + "jsfiles": [ + "shortforms.js" + ] + } + } +} diff --git a/lib/form/yui/src/shortforms/js/shortforms.js b/lib/form/yui/src/shortforms/js/shortforms.js new file mode 100644 index 00000000000..36e6ccf01bc --- /dev/null +++ b/lib/form/yui/src/shortforms/js/shortforms.js @@ -0,0 +1,228 @@ +/** + * Provides the form shortforms class. + * + * @module moodle-form-shortforms + */ + +/** + * A class for a shortforms. + * + * @class M.form.shortforms + * @constructor + * @extends Base + */ +function SHORTFORMS() { + SHORTFORMS.superclass.constructor.apply(this, arguments); +} + +var SELECTORS = { + COLLAPSEEXPAND: '.collapsible-actions .collapseexpand', + FIELDSETCOLLAPSIBLE: 'fieldset.collapsible', + FIELDSETLEGENDLINK: 'fieldset.collapsible .fheader', + LEGENDFTOGGLER: 'legend.ftoggler' + }, + CSS = { + COLLAPSEALL: 'collapse-all', + COLLAPSED: 'collapsed', + FHEADER: 'fheader' + }, + ATTRS = {}; + +/** + * The form ID attribute definition. + * + * @attribute formid + * @type String + * @default '' + * @writeOnce + */ +ATTRS.formid = { + value: null +}; + +Y.extend(SHORTFORMS, Y.Base, { + /** + * A reference to the form. + * + * @property form + * @protected + * @type Node + * @default null + */ + form: null, + + /** + * The initializer for the shortforms instance. + * + * @method initializer + * @protected + */ + initializer: function() { + var form = Y.one('#'+this.get('formid')), + fieldlist, + btn, + link, + idlist; + if (!form) { + Y.log('Could not locate the form', 'warn', 'moodle-form-shortforms'); + return; + } + // Stores the form in the object. + this.form = form; + // Look through collapsible fieldset divs. + fieldlist = form.all(SELECTORS.FIELDSETCOLLAPSIBLE); + fieldlist.each(this.process_fieldset, this); + + // Subscribe collapsible fieldsets and buttons to click events. + form.delegate('click', this.switch_state, SELECTORS.FIELDSETLEGENDLINK, this); + form.delegate('key', this.switch_state, 'down:enter,32', SELECTORS.FIELDSETLEGENDLINK, this); + + // Make the collapse/expand a link. + btn = form.one(SELECTORS.COLLAPSEEXPAND); + if (btn) { + link = Y.Node.create(''); + link.setHTML(btn.getHTML()); + link.setAttribute('class', btn.getAttribute('class')); + link.setAttribute('role', 'button'); + + // Get list of IDs controlled by this button to set the aria-controls attribute. + idlist = []; + form.all(SELECTORS.FIELDSETLEGENDLINK).each(function(node) { + idlist[idlist.length] = node.generateID(); + }); + link.setAttribute('aria-controls', idlist.join(' ')); + + // Placing the button and binding the event. + link.on('click', this.set_state_all, this, true); + link.on('key', this.set_state_all, 'down:enter,32', this, true); + btn.replace(link); + this.update_btns(form); + } + }, + + /** + * Process the supplied fieldset to add appropriate links, and ARIA + * roles. + * + * @method process_fieldset + * @param {Node} fieldset The Node relating to the fieldset to add collapsing to. + * @chainable + */ + process_fieldset: function(fieldset) { + // Get legend element. + var legendelement = fieldset.one(SELECTORS.LEGENDFTOGGLER); + + // Turn headers to links for accessibility. + var headerlink = Y.Node.create(''); + headerlink.addClass(CSS.FHEADER); + headerlink.appendChild(legendelement.get('firstChild')); + headerlink.setAttribute('role', 'button'); + headerlink.setAttribute('aria-controls', fieldset.generateID()); + legendelement.prepend(headerlink); + + return this; + }, + + /** + * Set the collapsed state for the specified fieldset. + * + * @method set_state + * @param {Node} fieldset The Node relating to the fieldset to set state on. + * @param {Boolean} [collapsed] Whether the fieldset is collapsed. + * @chainable + */ + set_state: function(fieldset, collapsed) { + if (collapsed) { + fieldset.addClass(CSS.COLLAPSED); + } else { + fieldset.removeClass(CSS.COLLAPSED); + } + var statuselement = this.form.one('input[name=mform_isexpanded_'+fieldset.get('id')+']'); + if (!statuselement) { + Y.log("M.form.shortforms::switch_state was called on an fieldset without a status field: '" + + fieldset.get('id') + "'", 'debug', 'moodle-form-shortforms'); + return this; + } + statuselement.set('value', collapsed ? 0: 1); + + return this; + }, + + /** + * Set the state for all fieldsets in the form. + * + * @method set_state_all + * @param {EventFacade} e + */ + set_state_all: function(e) { + e.preventDefault(); + var collapsed = e.target.hasClass(CSS.COLLAPSEALL), + fieldlist = this.form.all(SELECTORS.FIELDSETCOLLAPSIBLE); + fieldlist.each(function(node) { + this.set_state(node, collapsed); + }, this); + this.update_btns(); + }, + + /** + * Toggle the state for the fieldset that was clicked. + * + * @method switch_state + * @param {EventFacade} e + */ + switch_state: function(e) { + e.preventDefault(); + var fieldset = e.target.ancestor(SELECTORS.FIELDSETCOLLAPSIBLE); + this.set_state(fieldset, !fieldset.hasClass(CSS.COLLAPSED)); + this.update_btns(); + }, + + /** + * Update the Expand/Collapse all buttons as required. + * + * @method update_btns + * @chainable + */ + update_btns: function() { + var btn, + collapsed = 0, + expandbtn = false, + fieldlist; + + btn = this.form.one(SELECTORS.COLLAPSEEXPAND); + if (!btn) { + return this; + } + + // Counting the number of collapsed sections. + fieldlist = this.form.all(SELECTORS.FIELDSETCOLLAPSIBLE); + fieldlist.each(function(node) { + if (node.hasClass(CSS.COLLAPSED)) { + collapsed++; + } + }); + + if (collapsed !== 0) { + expandbtn = true; + } + + // Updating the button. + if (expandbtn) { + btn.removeClass(CSS.COLLAPSEALL); + btn.setHTML(M.util.get_string('expandall', 'moodle')); + } else { + btn.addClass(CSS.COLLAPSEALL); + btn.setHTML(M.util.get_string('collapseall', 'moodle')); + } + + return this; + } +}, { + NAME: 'moodle-form-shortforms', + ATTRS: ATTRS +}); + +M.form = M.form || {}; +M.form.shortforms = M.form.shortforms || function(params) { + return new SHORTFORMS(params); +}; diff --git a/lib/form/yui/src/shortforms/meta/shortforms.json b/lib/form/yui/src/shortforms/meta/shortforms.json new file mode 100644 index 00000000000..7d6bb01145e --- /dev/null +++ b/lib/form/yui/src/shortforms/meta/shortforms.json @@ -0,0 +1,9 @@ +{ + "moodle-form-shortforms": { + "requires": [ + "node", + "base", + "selector-css3" + ] + } +}