From 4a521e6596918279fd0cdeb47d06e7906bc004cc Mon Sep 17 00:00:00 2001 From: Jerome Mouneyrac Date: Fri, 28 Feb 2014 15:05:43 +0800 Subject: [PATCH] MDL-32917 port YUI2 Moodle calendar into a shifted YUI3 Calendar --- .../moodle-form-dateselector-debug.js | Bin 0 -> 12874 bytes .../moodle-form-dateselector-min.js | Bin 0 -> 6667 bytes .../moodle-form-dateselector.js | Bin 0 -> 12874 bytes .../assets/skins/sam/dateselector.css | 4 - lib/form/yui/dateselector/dateselector.js | 300 ------------------ lib/form/yui/src/dateselector/build.json | 12 + lib/form/yui/src/dateselector/js/calendar.js | 177 +++++++++++ .../yui/src/dateselector/js/dateselector.js | 133 ++++++++ .../yui/src/dateselector/js/moodlecalendar.js | 34 ++ .../src/dateselector/meta/dateselector.json | 10 + 10 files changed, 366 insertions(+), 304 deletions(-) create mode 100644 lib/form/yui/build/moodle-form-dateselector/moodle-form-dateselector-debug.js create mode 100644 lib/form/yui/build/moodle-form-dateselector/moodle-form-dateselector-min.js create mode 100644 lib/form/yui/build/moodle-form-dateselector/moodle-form-dateselector.js delete mode 100644 lib/form/yui/dateselector/assets/skins/sam/dateselector.css delete mode 100644 lib/form/yui/dateselector/dateselector.js create mode 100644 lib/form/yui/src/dateselector/build.json create mode 100644 lib/form/yui/src/dateselector/js/calendar.js create mode 100644 lib/form/yui/src/dateselector/js/dateselector.js create mode 100644 lib/form/yui/src/dateselector/js/moodlecalendar.js create mode 100644 lib/form/yui/src/dateselector/meta/dateselector.json diff --git a/lib/form/yui/build/moodle-form-dateselector/moodle-form-dateselector-debug.js b/lib/form/yui/build/moodle-form-dateselector/moodle-form-dateselector-debug.js new file mode 100644 index 0000000000000000000000000000000000000000..296abc15c698161b11bf6a6158d085b9e314e206 GIT binary patch literal 12874 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 FzX7Gm6&L^j literal 0 HcmV?d00001 diff --git a/lib/form/yui/build/moodle-form-dateselector/moodle-form-dateselector-min.js b/lib/form/yui/build/moodle-form-dateselector/moodle-form-dateselector-min.js new file mode 100644 index 0000000000000000000000000000000000000000..3617fdbe3a6f54f5f1f7959583e220ac9a7f856f GIT binary patch literal 6667 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 FzX7Gm6&L^j literal 0 HcmV?d00001 diff --git a/lib/form/yui/dateselector/assets/skins/sam/dateselector.css b/lib/form/yui/dateselector/assets/skins/sam/dateselector.css deleted file mode 100644 index d8abda4d431..00000000000 --- a/lib/form/yui/dateselector/assets/skins/sam/dateselector.css +++ /dev/null @@ -1,4 +0,0 @@ -#dateselector-calendar-panel {background-color:#999;border-bottom:3px solid #999;border-right:3px solid #999;} -#dateselector-calendar-content {border:1px solid #666;margin-top:-3px;margin-left:-3px;} -#dateselector-calendar-content_t th.calweekdaycell {padding-left:3px; padding-right:3px;} -body.ie #dateselector-calendar-panel.yui3-overlay-hidden table {display:none;} \ No newline at end of file diff --git a/lib/form/yui/dateselector/dateselector.js b/lib/form/yui/dateselector/dateselector.js deleted file mode 100644 index 3f4545f0855..00000000000 --- a/lib/form/yui/dateselector/dateselector.js +++ /dev/null @@ -1,300 +0,0 @@ -YUI.add('moodle-form-dateselector', function(Y) { - - /** - * Add some custom methods to the node class to make our lives a little - * easier within this module. - */ - Y.mix(Y.Node.prototype, { - /** - * Gets the value of the first option in the select box - */ - firstOptionValue : function() { - if (this.get('nodeName').toLowerCase() != 'select') { - return false; - } - return this.one('option').get('value'); - }, - /** - * Gets the value of the last option in the select box - */ - lastOptionValue : function() { - if (this.get('nodeName').toLowerCase() != 'select') { - return false; - } - return this.all('option').item(this.optionSize()-1).get('value'); - }, - /** - * Gets the number of options in the select box - */ - optionSize : function() { - if (this.get('nodeName').toLowerCase() != 'select') { - return false; - } - return parseInt(this.all('option').size()); - }, - /** - * Gets the value of the selected option in the select box - */ - selectedOptionValue : function() { - if (this.get('nodeName').toLowerCase() != 'select') { - return false; - } - return this.all('option').item(this.get('selectedIndex')).get('value'); - } - }); - - /** - * Calendar class - * - * This is our main class - */ - var CALENDAR = function(config) { - CALENDAR.superclass.constructor.apply(this, arguments); - }; - CALENDAR.prototype = { - panel : null, - yearselect : null, - monthselect : null, - dayselect : null, - calendarimage : null, - enablecheckbox : null, - closepopup : true, - initializer : function(config) { - var controls = this.get('node').all('select'); - controls.each(function(node){ - if (node.get('name').match(/\[year]/)) { - this.yearselect = node; - } else if (node.get('name').match(/\[month\]/)) { - this.monthselect = node; - } else if (node.get('name').match(/\[day]/)) { - this.dayselect = node; - } - node.after('change', this.handle_select_change, this); - }, this); - - // Loop through the input fields. - var inputs = this.get('node').all('input, a'); - inputs.each(function(node) { - // Check if the current node is a calendar image field. - if (node.get('name').match(/\[calendar]/)) { - // Set it so that when the image is clicked the pop-up displays. - node.on('click', this.focus_event, this); - // Set the node to the calendarimage variable. - this.calendarimage = node; - } else { // Must be the enabled checkbox field. - // If the enable checkbox is clicked we want to either disable/enable the calendar image. - node.on('click', this.toggle_calendar_image, this); - // Set the node to the enablecheckbox variable. - this.enablecheckbox = node; - } - // Ensure that the calendarimage and enablecheckbox values have been set. - if (this.calendarimage && this.enablecheckbox) { - // Set the calendar icon status depending on the value of the checkbox. - this.toggle_calendar_image(); - } - }, this); - }, - focus_event : function(e) { - M.form.dateselector.cancel_any_timeout(); - // If the current owner is set, then the pop-up is currently being displayed, so hide it. - if (M.form.dateselector.currentowner == this) { - this.release_calendar(); - } else if ((this.enablecheckbox == null) - || (this.enablecheckbox.get('checked'))) { // Must be hidden. If the field is enabled display the pop-up. - this.claim_calendar(); - } - // Stop the input image field from submitting the form. - e.preventDefault(); - }, - handle_select_change : function(e) { - // It may seem as if the following variable is not used, however any call to set_date_from_selects will trigger a - // call to set_selects_from_date if the calendar is open as the date has changed. Whenever the calendar is displayed - // the set_selects_from_date function is set to trigger on any date change (see function connect_handlers). - this.closepopup = false; - this.set_date_from_selects(); - this.closepopup = true; - }, - claim_calendar : function() { - M.form.dateselector.cancel_any_timeout(); - if (M.form.dateselector.currentowner == this) { - return; - } - if (M.form.dateselector.currentowner) { - M.form.dateselector.currentowner.release_calendar(); - } - if (M.form.dateselector.currentowner != this) { - this.connect_handlers(); - this.set_date_from_selects(); - } - M.form.dateselector.currentowner = this; - M.form.dateselector.calendar.cfg.setProperty('mindate', new Date(this.yearselect.firstOptionValue(), 0, 1)); - M.form.dateselector.calendar.cfg.setProperty('maxdate', new Date(this.yearselect.lastOptionValue(), 11, 31)); - M.form.dateselector.panel.show(); - M.form.dateselector.fix_position(); - setTimeout(function(){M.form.dateselector.cancel_any_timeout()}, 100); - }, - set_date_from_selects : function() { - var year = parseInt(this.yearselect.get('value')); - var month = parseInt(this.monthselect.get('value')) - 1; - var day = parseInt(this.dayselect.get('value')); - var date = new Date(year, month, day); - M.form.dateselector.calendar.select(date); - M.form.dateselector.calendar.setMonth(month); - M.form.dateselector.calendar.setYear(year); - M.form.dateselector.calendar.render(); - if (date.getDate() != day) { - // Must've selected the 29 to 31st of a month that doesn't have such dates. - this.dayselect.set('value', date.getDate()); - this.monthselect.set('value', date.getMonth() + 1); - } - }, - set_selects_from_date : function(eventtype, args) { - var date = args[0][0]; - var newyear = date[0]; - var newindex = newyear - this.yearselect.firstOptionValue(); - this.yearselect.set('selectedIndex', newindex); - this.monthselect.set('selectedIndex', date[1] - this.monthselect.firstOptionValue()); - this.dayselect.set('selectedIndex', date[2] - this.dayselect.firstOptionValue()); - if (M.form.dateselector.currentowner && this.closepopup) { - this.release_calendar(); - } - }, - connect_handlers : function() { - M.form.dateselector.calendar.selectEvent.subscribe(this.set_selects_from_date, this, true); - }, - release_calendar : function() { - M.form.dateselector.panel.hide(); - M.form.dateselector.currentowner = null; - M.form.dateselector.calendar.selectEvent.unsubscribe(this.set_selects_from_date, this); - }, - toggle_calendar_image : function() { - // If the enable checkbox is not checked, disable the image. - if (!this.enablecheckbox.get('checked')) { - this.calendarimage.set('disabled', 'disabled'); - this.calendarimage.setStyle('cursor', 'default'); - this.release_calendar(); - } else { - this.calendarimage.set('disabled', false); - this.calendarimage.setStyle('cursor', null); - } - } - }; - Y.extend(CALENDAR, Y.Base, CALENDAR.prototype, { - NAME : 'Date Selector', - ATTRS : { - firstdayofweek : { - validator : Y.Lang.isString - }, - node : { - setter : function(node) { - return Y.one(node); - } - } - } - }); - - M.form = M.form || {}; - M.form.dateselector = { - panel : null, - calendar : null, - currentowner : null, - hidetimeout : null, - repositiontimeout : null, - init_date_selectors : function(config) { - if (this.panel === null) { - this.initPanel(config); - } - Y.all('.fdate_time_selector').each(function() { - config.node = this; - new CALENDAR(config); - }); - Y.all('.fdate_selector').each(function() { - config.node = this; - new CALENDAR(config); - }); - }, - initPanel : function(config) { - this.panel = new Y.Overlay({ - visible : false, - bodyContent : Y.Node.create('
'), - id : 'dateselector-calendar-panel' - }); - this.panel.render(document.body); - // zIndex is added by panel.render() and is set to 0. - // Remove zIndex from panel, as this should be set by CSS. This can be done by removeAttr but - // ie8 fails and there is know issue for it. - Y.one('#dateselector-calendar-panel').setStyle('zIndex', null); - this.panel.on('heightChange', this.fix_position, this); - - Y.one('#dateselector-calendar-panel').on('click', function(e){e.halt();}); - Y.one(document.body).on('click', this.document_click, this); - - this.calendar = new Y.YUI2.widget.Calendar(document.getElementById('dateselector-calendar-content'), { - iframe: false, - hide_blank_weeks: true, - start_weekday: config.firstdayofweek, - locale_weekdays: 'medium', - locale_months: 'long', - WEEKDAYS_MEDIUM: [ - config.sun, - config.mon, - config.tue, - config.wed, - config.thu, - config.fri, - config.sat ], - MONTHS_LONG: [ - config.january, - config.february, - config.march, - config.april, - config.may, - config.june, - config.july, - config.august, - config.september, - config.october, - config.november, - config.december ] - }); - this.calendar.changePageEvent.subscribe(function(){ - this.fix_position(); - }, this); - }, - cancel_any_timeout : function() { - if (this.hidetimeout) { - clearTimeout(this.hidetimeout); - this.hidetimeout = null; - } - if (this.repositiontimeout) { - clearTimeout(this.repositiontimeout); - this.repositiontimeout = null; - } - }, - delayed_reposition : function() { - if (this.repositiontimeout) { - clearTimeout(this.repositiontimeout); - this.repositiontimeout = null; - } - this.repositiontimeout = setTimeout(this.fix_position, 500); - }, - fix_position : function() { - if (this.currentowner) { - this.panel.set('align', { - node:this.currentowner.get('node').one('select'), - points:[Y.WidgetPositionAlign.BL, Y.WidgetPositionAlign.TL] - }); - } - }, - document_click : function(e) { - if (this.currentowner) { - if (this.currentowner.get('node').ancestor('div').contains(e.target)) { - setTimeout(function() {M.form.dateselector.cancel_any_timeout()}, 100); - } else { - this.currentowner.release_calendar(); - } - } - } - } - -}, '@VERSION@', {requires:['base','node','overlay', 'yui2-calendar', 'moodle-form-dateselector-skin']}); diff --git a/lib/form/yui/src/dateselector/build.json b/lib/form/yui/src/dateselector/build.json new file mode 100644 index 00000000000..333aa1a32aa --- /dev/null +++ b/lib/form/yui/src/dateselector/build.json @@ -0,0 +1,12 @@ +{ + "name": "moodle-form-dateselector", + "builds": { + "moodle-form-dateselector": { + "jsfiles": [ + "dateselector.js", + "moodlecalendar.js", + "calendar.js" + ] + } + } +} diff --git a/lib/form/yui/src/dateselector/js/calendar.js b/lib/form/yui/src/dateselector/js/calendar.js new file mode 100644 index 00000000000..5452c292131 --- /dev/null +++ b/lib/form/yui/src/dateselector/js/calendar.js @@ -0,0 +1,177 @@ +/** + * Provides the Calendar class. + * + * @module moodle-form-dateselector + */ + +/** + * Calendar class + */ +var CALENDAR = function() { + CALENDAR.superclass.constructor.apply(this, arguments); +}; +CALENDAR.prototype = { + panel : null, + yearselect : null, + monthselect : null, + dayselect : null, + calendarimage : null, + enablecheckbox : null, + closepopup : true, + initializer : function() { + var controls = this.get('node').all('select'); + controls.each(function(node){ + if (node.get('name').match(/\[year\]/)) { + this.yearselect = node; + } else if (node.get('name').match(/\[month\]/)) { + this.monthselect = node; + } else if (node.get('name').match(/\[day\]/)) { + this.dayselect = node; + } + node.after('change', this.handle_select_change, this); + }, this); + + // Loop through the input fields. + var inputs = this.get('node').all('input, a'); + inputs.each(function(node) { + // Check if the current node is a calendar image field. + if (node.get('name').match(/\[calendar\]/)) { + // Set it so that when the image is clicked the pop-up displays. + node.on('click', this.focus_event, this); + // Set the node to the calendarimage variable. + this.calendarimage = node; + } else { // Must be the enabled checkbox field. + // If the enable checkbox is clicked we want to either disable/enable the calendar image. + node.on('click', this.toggle_calendar_image, this); + // Set the node to the enablecheckbox variable. + this.enablecheckbox = node; + } + // Ensure that the calendarimage and enablecheckbox values have been set. + if (this.calendarimage && this.enablecheckbox) { + // Set the calendar icon status depending on the value of the checkbox. + this.toggle_calendar_image(); + } + }, this); + }, + focus_event : function(e) { + M.form.dateselector.cancel_any_timeout(); + // If the current owner is set, then the pop-up is currently being displayed, so hide it. + if (M.form.dateselector.currentowner === this) { + this.release_calendar(); + } else if ((this.enablecheckbox === null) + || (this.enablecheckbox.get('checked'))) { // Must be hidden. If the field is enabled display the pop-up. + this.claim_calendar(); + } + // Stop the input image field from submitting the form. + e.preventDefault(); + }, + handle_select_change : function() { + // It may seem as if the following variable is not used, however any call to set_date_from_selects will trigger a + // call to set_selects_from_date if the calendar is open as the date has changed. Whenever the calendar is displayed + // the set_selects_from_date function is set to trigger on any date change (see function connect_handlers). + this.closepopup = false; + this.set_date_from_selects(); + this.closepopup = true; + }, + claim_calendar : function() { + M.form.dateselector.cancel_any_timeout(); + if (M.form.dateselector.currentowner === this) { + return; + } + if (M.form.dateselector.currentowner) { + M.form.dateselector.currentowner.release_calendar(); + } + if (M.form.dateselector.currentowner !== this) { + this.connect_handlers(); + this.set_date_from_selects(); + } + M.form.dateselector.currentowner = this; + M.form.dateselector.calendar.set('mindate', new Date(this.yearselect.firstOptionValue(), 0, 1)); + M.form.dateselector.calendar.set('maxdate', new Date(this.yearselect.lastOptionValue(), 11, 31)); + M.form.dateselector.panel.show(); + M.form.dateselector.calendar.show(); + M.form.dateselector.fix_position(); + setTimeout(function() { + M.form.dateselector.cancel_any_timeout(); + }, 100); + + // Focus on the calendar. + M.form.dateselector.calendar.focus(); + + // When the user tab out the calendar, close it. + Y.one(document.body).on('keyup', function(e) { + // hide the calendar if we press a key and the calendar is not focussed, or if we press ESC in the calendar. + if ((M.form.dateselector.currentowner === this && !M.form.dateselector.calendar.get('focused')) || + ((e.keyCode === 27) && M.form.dateselector.calendar.get('focused'))) { + // Focus back on the calendar button. + this.calendarimage.focus(); + this.release_calendar(); + } + }, this); + + }, + set_date_from_selects : function() { + var year = parseInt(this.yearselect.get('value'), 10); + var month = parseInt(this.monthselect.get('value'), 10) - 1; + var day = parseInt(this.dayselect.get('value'), 10); + var date = new Date(year, month, day); + M.form.dateselector.calendar.selectDates([date]); + M.form.dateselector.calendar.set("month", month); + M.form.dateselector.calendar.set("year", year); + M.form.dateselector.calendar.render(); + if (date.getDate() !== day) { + // Must've selected the 29 to 31st of a month that doesn't have such dates. + this.dayselect.set('value', date.getDate()); + this.monthselect.set('value', date.getMonth() + 1); + } + }, + set_selects_from_date : function(ev) { + var date = ev.newSelection[0]; + var newyear = Y.DataType.Date.format(date, {format: "%Y"}); + var newindex = newyear - this.yearselect.firstOptionValue(); + this.yearselect.set('selectedIndex', newindex); + this.monthselect.set('selectedIndex', Y.DataType.Date.format(date, {format: "%m"}) - this.monthselect.firstOptionValue()); + this.dayselect.set('selectedIndex', Y.DataType.Date.format(date, {format: "%d"}) - this.dayselect.firstOptionValue()); + if (M.form.dateselector.currentowner && this.closepopup) { + this.release_calendar(); + } + }, + connect_handlers : function() { + M.form.dateselector.calendar.on('selectionChange', this.set_selects_from_date, this, true); + }, + release_calendar : function(e) { + M.form.dateselector.panel.hide(); + M.form.dateselector.calendar.detach('selectionChange', this.set_selects_from_date); + M.form.dateselector.calendar.hide(); + M.form.dateselector.currentowner = null; + + // Put the focus back to the image calendar that we clicked. + if (e === null || typeof e === "undefined" || e.type !== "click") { + this.calendarimage.focus(); + } + }, + toggle_calendar_image : function() { + // If the enable checkbox is det checked, disable the image. + if (!this.enablecheckbox.get('checked')) { + this.calendarimage.set('disabled', 'disabled'); + this.calendarimage.setStyle('cursor', 'default'); + this.release_calendar(); + } else { + this.calendarimage.set('disabled', false); + this.calendarimage.setStyle('cursor', null); + } + } +}; +Y.extend(CALENDAR, Y.Base, CALENDAR.prototype, { + NAME : 'Date Selector', + ATTRS : { + firstdayofweek : { + validator : Y.Lang.isString + }, + node : { + setter : function(node) { + return Y.one(node); + } + } + } +}); \ No newline at end of file diff --git a/lib/form/yui/src/dateselector/js/dateselector.js b/lib/form/yui/src/dateselector/js/dateselector.js new file mode 100644 index 00000000000..cfbe091bb1d --- /dev/null +++ b/lib/form/yui/src/dateselector/js/dateselector.js @@ -0,0 +1,133 @@ + +/** + * Add some custom methods to the node class to make our lives a little + * easier within this module. + */ +Y.mix(Y.Node.prototype, { + /** + * Gets the value of the first option in the select box + */ + firstOptionValue : function() { + if (this.get('nodeName').toLowerCase() !== 'select') { + return false; + } + return this.one('option').get('value'); + }, + /** + * Gets the value of the last option in the select box + */ + lastOptionValue : function() { + if (this.get('nodeName').toLowerCase() !== 'select') { + return false; + } + return this.all('option').item(this.optionSize()-1).get('value'); + }, + /** + * Gets the number of options in the select box + */ + optionSize : function() { + if (this.get('nodeName').toLowerCase() !== 'select') { + return false; + } + return parseInt(this.all('option').size(), 10); + }, + /** + * Gets the value of the selected option in the select box + */ + selectedOptionValue : function() { + if (this.get('nodeName').toLowerCase() !== 'select') { + return false; + } + return this.all('option').item(this.get('selectedIndex')).get('value'); + } +}); + +M.form = M.form || {}; +M.form.dateselector = { + panel : null, + calendar : null, + currentowner : null, + hidetimeout : null, + repositiontimeout : null, + init_date_selectors : function(config) { + if (this.panel === null) { + this.initPanel(config); + } + Y.all('.fdate_time_selector').each(function() { + config.node = this; + new CALENDAR(config); + }); + Y.all('.fdate_selector').each(function() { + config.node = this; + new CALENDAR(config); + }); + }, + initPanel : function(config) { + this.panel = new Y.Overlay({ + visible : false, + bodyContent : Y.Node.create('
'), + id : 'dateselector-calendar-panel' + }); + this.panel.render(document.body); + // zIndex is added by panel.render() and is set to 0. + // Remove zIndex from panel, as this should be set by CSS. This can be done by removeAttr but + // ie8 fails and there is know issue for it. + Y.one('#dateselector-calendar-panel').setStyle('zIndex', null); + this.panel.on('heightChange', this.fix_position, this); + + Y.one('#dateselector-calendar-panel').on('click', function(e){e.halt();}); + Y.one(document.body).on('click', this.document_click, this); + + this.calendar = new MOODLECALENDAR({ + contentBox: "#dateselector-calendar-content", + width: "300px", + showPrevMonth: true, + showNextMonth: true, + firstdayofweek: config.firstdayofweek, + WEEKDAYS_MEDIUM: [ + config.sun, + config.mon, + config.tue, + config.wed, + config.thu, + config.fri, + config.sat ] + }); + }, + cancel_any_timeout : function() { + if (this.hidetimeout) { + clearTimeout(this.hidetimeout); + this.hidetimeout = null; + } + if (this.repositiontimeout) { + clearTimeout(this.repositiontimeout); + this.repositiontimeout = null; + } + }, + delayed_reposition : function() { + if (this.repositiontimeout) { + clearTimeout(this.repositiontimeout); + this.repositiontimeout = null; + } + this.repositiontimeout = setTimeout(this.fix_position, 500); + }, + fix_position : function() { + if (this.currentowner) { + this.panel.set('align', { + node:this.currentowner.get('node').one('select'), + points:[Y.WidgetPositionAlign.BL, Y.WidgetPositionAlign.TL] + }); + } + }, + document_click : function(e) { + if (this.currentowner) { + if (this.currentowner.get('node').ancestor('div').contains(e.target)) { + setTimeout(function() { + M.form.dateselector.cancel_any_timeout(); + }, 100); + } else { + this.currentowner.release_calendar(e); + } + } + } +}; diff --git a/lib/form/yui/src/dateselector/js/moodlecalendar.js b/lib/form/yui/src/dateselector/js/moodlecalendar.js new file mode 100644 index 00000000000..d4076ce898f --- /dev/null +++ b/lib/form/yui/src/dateselector/js/moodlecalendar.js @@ -0,0 +1,34 @@ +/** + * Provides the Moodle Calendar class. + * + * @module moodle-form-dateselector + */ + +/** + * A class to overwrite the YUI3 Calendar in order to change the strings.. + * + * @class M.form.dateselector + * @constructor + * @extends Calendar + */ +var MOODLECALENDAR = function() { + MOODLECALENDAR.superclass.constructor.apply(this, arguments); +}; + +Y.extend(MOODLECALENDAR, Y.Calendar, + { + initializer: function(cfg) { + this.set("strings.very_short_weekdays", cfg.WEEKDAYS_MEDIUM); + this.set("strings.first_weekday ", cfg.firstdayofweek); + } + }, + { + NAME : 'Calendar', + ATTRS : {} + } +); + +M.form_moodlecalendar = M.form_moodlecalendar || {}; +M.form_moodlecalendar.initializer = function(params) { + return new MOODLECALENDAR(params); +}; diff --git a/lib/form/yui/src/dateselector/meta/dateselector.json b/lib/form/yui/src/dateselector/meta/dateselector.json new file mode 100644 index 00000000000..9ad3e1d034b --- /dev/null +++ b/lib/form/yui/src/dateselector/meta/dateselector.json @@ -0,0 +1,10 @@ +{ + "moodle-form-dateselector": { + "requires": [ + "base", + "node", + "overlay", + "calendar" + ] + } +} -- 2.43.0