| 1 | efrain | 1 | YUI.add('moodle-form-dateselector', function (Y, NAME) {
 | 
        
           |  |  | 2 |   | 
        
           |  |  | 3 | var CALENDAR;
 | 
        
           |  |  | 4 | var MOODLECALENDAR;
 | 
        
           |  |  | 5 | var DIALOGUE_SELECTOR = ' [role=dialog]',
 | 
        
           |  |  | 6 |     MENUBAR_SELECTOR = '[role=menubar]',
 | 
        
           |  |  | 7 |     DOT = '.',
 | 
        
           |  |  | 8 |     HAS_ZINDEX = 'moodle-has-zindex';
 | 
        
           |  |  | 9 |   | 
        
           |  |  | 10 | /**
 | 
        
           |  |  | 11 |  * Add some custom methods to the node class to make our lives a little
 | 
        
           |  |  | 12 |  * easier within this module.
 | 
        
           |  |  | 13 |  */
 | 
        
           |  |  | 14 | Y.mix(Y.Node.prototype, {
 | 
        
           |  |  | 15 |     /**
 | 
        
           |  |  | 16 |      * Gets the value of the first option in the select box
 | 
        
           |  |  | 17 |      */
 | 
        
           |  |  | 18 |     firstOptionValue: function() {
 | 
        
           |  |  | 19 |         if (this.get('nodeName').toLowerCase() !== 'select') {
 | 
        
           |  |  | 20 |             return false;
 | 
        
           |  |  | 21 |         }
 | 
        
           |  |  | 22 |         return this.one('option').get('value');
 | 
        
           |  |  | 23 |     },
 | 
        
           |  |  | 24 |     /**
 | 
        
           |  |  | 25 |      * Gets the value of the last option in the select box
 | 
        
           |  |  | 26 |      */
 | 
        
           |  |  | 27 |     lastOptionValue: function() {
 | 
        
           |  |  | 28 |         if (this.get('nodeName').toLowerCase() !== 'select') {
 | 
        
           |  |  | 29 |             return false;
 | 
        
           |  |  | 30 |         }
 | 
        
           |  |  | 31 |         return this.all('option').item(this.optionSize() - 1).get('value');
 | 
        
           |  |  | 32 |     },
 | 
        
           |  |  | 33 |     /**
 | 
        
           |  |  | 34 |      * Gets the number of options in the select box
 | 
        
           |  |  | 35 |      */
 | 
        
           |  |  | 36 |     optionSize: function() {
 | 
        
           |  |  | 37 |         if (this.get('nodeName').toLowerCase() !== 'select') {
 | 
        
           |  |  | 38 |             return false;
 | 
        
           |  |  | 39 |         }
 | 
        
           |  |  | 40 |         return parseInt(this.all('option').size(), 10);
 | 
        
           |  |  | 41 |     },
 | 
        
           |  |  | 42 |     /**
 | 
        
           |  |  | 43 |      * Gets the value of the selected option in the select box
 | 
        
           |  |  | 44 |      */
 | 
        
           |  |  | 45 |     selectedOptionValue: function() {
 | 
        
           |  |  | 46 |         if (this.get('nodeName').toLowerCase() !== 'select') {
 | 
        
           |  |  | 47 |             return false;
 | 
        
           |  |  | 48 |         }
 | 
        
           |  |  | 49 |         return this.all('option').item(this.get('selectedIndex')).get('value');
 | 
        
           |  |  | 50 |     }
 | 
        
           |  |  | 51 | });
 | 
        
           |  |  | 52 |   | 
        
           |  |  | 53 | M.form = M.form || {};
 | 
        
           |  |  | 54 | M.form.dateselector = {
 | 
        
           |  |  | 55 |     panel: null,
 | 
        
           |  |  | 56 |     calendar: null,
 | 
        
           |  |  | 57 |     currentowner: null,
 | 
        
           |  |  | 58 |     hidetimeout: null,
 | 
        
           |  |  | 59 |     repositiontimeout: null,
 | 
        
           |  |  | 60 |     init_date_selectors: function(config) {
 | 
        
           |  |  | 61 |         if (this.panel === null) {
 | 
        
           |  |  | 62 |             this.initPanel(config);
 | 
        
           |  |  | 63 |         }
 | 
        
           |  |  | 64 |         Y.all('.fdate_time_selector').each(function() {
 | 
        
           |  |  | 65 |             config.node = this;
 | 
        
           |  |  | 66 |             new CALENDAR(config);
 | 
        
           |  |  | 67 |         });
 | 
        
           |  |  | 68 |         Y.all('.fdate_selector').each(function() {
 | 
        
           |  |  | 69 |             config.node = this;
 | 
        
           |  |  | 70 |             new CALENDAR(config);
 | 
        
           |  |  | 71 |         });
 | 
        
           |  |  | 72 |     },
 | 
        
           |  |  | 73 |     initPanel: function(config) {
 | 
        
           |  |  | 74 |         this.panel = new Y.Overlay({
 | 
        
           |  |  | 75 |             visible: false,
 | 
        
           |  |  | 76 |             bodyContent: Y.Node.create('<div id="dateselector-calendar-content"></div>'),
 | 
        
           |  |  | 77 |             id: 'dateselector-calendar-panel',
 | 
        
           |  |  | 78 |             constrain: true // constrain panel to viewport.
 | 
        
           |  |  | 79 |         });
 | 
        
           |  |  | 80 |         this.panel.render(document.body);
 | 
        
           |  |  | 81 |   | 
        
           |  |  | 82 |         // Determine the correct zindex by looking at all existing dialogs and menubars in the page.
 | 
        
           |  |  | 83 |         this.panel.on('focus', function() {
 | 
        
           |  |  | 84 |             var highestzindex = 0;
 | 
        
           |  |  | 85 |             Y.all(DIALOGUE_SELECTOR + ', ' + MENUBAR_SELECTOR + ', ' + DOT + HAS_ZINDEX).each(function(node) {
 | 
        
           |  |  | 86 |                 var zindex = this.findZIndex(node);
 | 
        
           |  |  | 87 |                 if (zindex > highestzindex) {
 | 
        
           |  |  | 88 |                     highestzindex = zindex;
 | 
        
           |  |  | 89 |                 }
 | 
        
           |  |  | 90 |             }, this);
 | 
        
           |  |  | 91 |             // Only set the zindex if we found a wrapper.
 | 
        
           |  |  | 92 |             var zindexvalue = (highestzindex + 1).toString();
 | 
        
           |  |  | 93 |             Y.one('#dateselector-calendar-panel').setStyle('zIndex', zindexvalue);
 | 
        
           |  |  | 94 |         }, this);
 | 
        
           |  |  | 95 |   | 
        
           |  |  | 96 |         this.panel.on('heightChange', this.fix_position, this);
 | 
        
           |  |  | 97 |   | 
        
           |  |  | 98 |         Y.one('#dateselector-calendar-panel').on('click', function(e) {
 | 
        
           |  |  | 99 |             e.halt();
 | 
        
           |  |  | 100 |         });
 | 
        
           |  |  | 101 |         Y.one(document.body).on('click', this.document_click, this);
 | 
        
           |  |  | 102 |   | 
        
           |  |  | 103 |         this.calendar = new MOODLECALENDAR({
 | 
        
           |  |  | 104 |             contentBox: "#dateselector-calendar-content",
 | 
        
           |  |  | 105 |             width: "300px",
 | 
        
           |  |  | 106 |             showPrevMonth: true,
 | 
        
           |  |  | 107 |             showNextMonth: true,
 | 
        
           |  |  | 108 |             firstdayofweek: parseInt(config.firstdayofweek, 10),
 | 
        
           |  |  | 109 |             WEEKDAYS_MEDIUM: [
 | 
        
           |  |  | 110 |                 config.sun,
 | 
        
           |  |  | 111 |                 config.mon,
 | 
        
           |  |  | 112 |                 config.tue,
 | 
        
           |  |  | 113 |                 config.wed,
 | 
        
           |  |  | 114 |                 config.thu,
 | 
        
           |  |  | 115 |                 config.fri,
 | 
        
           |  |  | 116 |                 config.sat]
 | 
        
           |  |  | 117 |         });
 | 
        
           |  |  | 118 |     },
 | 
        
           |  |  | 119 |     findZIndex: function(node) {
 | 
        
           |  |  | 120 |         // In most cases the zindex is set on the parent of the dialog.
 | 
        
           |  |  | 121 |         var zindex = node.getStyle('zIndex') || node.ancestor().getStyle('zIndex');
 | 
        
           |  |  | 122 |         if (zindex) {
 | 
        
           |  |  | 123 |             return parseInt(zindex, 10);
 | 
        
           |  |  | 124 |         }
 | 
        
           |  |  | 125 |         return 0;
 | 
        
           |  |  | 126 |     },
 | 
        
           |  |  | 127 |     cancel_any_timeout: function() {
 | 
        
           |  |  | 128 |         if (this.hidetimeout) {
 | 
        
           |  |  | 129 |             clearTimeout(this.hidetimeout);
 | 
        
           |  |  | 130 |             this.hidetimeout = null;
 | 
        
           |  |  | 131 |         }
 | 
        
           |  |  | 132 |         if (this.repositiontimeout) {
 | 
        
           |  |  | 133 |             clearTimeout(this.repositiontimeout);
 | 
        
           |  |  | 134 |             this.repositiontimeout = null;
 | 
        
           |  |  | 135 |         }
 | 
        
           |  |  | 136 |     },
 | 
        
           |  |  | 137 |     delayed_reposition: function() {
 | 
        
           |  |  | 138 |         if (this.repositiontimeout) {
 | 
        
           |  |  | 139 |             clearTimeout(this.repositiontimeout);
 | 
        
           |  |  | 140 |             this.repositiontimeout = null;
 | 
        
           |  |  | 141 |         }
 | 
        
           |  |  | 142 |         this.repositiontimeout = setTimeout(this.fix_position, 500);
 | 
        
           |  |  | 143 |     },
 | 
        
           |  |  | 144 |     fix_position: function() {
 | 
        
           |  |  | 145 |         if (this.currentowner) {
 | 
        
           |  |  | 146 |             var alignpoints = [
 | 
        
           |  |  | 147 |                 Y.WidgetPositionAlign.BL,
 | 
        
           |  |  | 148 |                 Y.WidgetPositionAlign.TL
 | 
        
           |  |  | 149 |             ];
 | 
        
           |  |  | 150 |   | 
        
           |  |  | 151 |             // Change the alignment if this is an RTL language.
 | 
        
           |  |  | 152 |             if (window.right_to_left()) {
 | 
        
           |  |  | 153 |                 alignpoints = [
 | 
        
           |  |  | 154 |                     Y.WidgetPositionAlign.BR,
 | 
        
           |  |  | 155 |                     Y.WidgetPositionAlign.TR
 | 
        
           |  |  | 156 |                 ];
 | 
        
           |  |  | 157 |             }
 | 
        
           |  |  | 158 |   | 
        
           |  |  | 159 |             this.panel.set('align', {
 | 
        
           |  |  | 160 |                 node: this.currentowner.get('node').one('select'),
 | 
        
           |  |  | 161 |                 points: alignpoints
 | 
        
           |  |  | 162 |             });
 | 
        
           |  |  | 163 |         }
 | 
        
           |  |  | 164 |     },
 | 
        
           |  |  | 165 |     document_click: function(e) {
 | 
        
           |  |  | 166 |         if (this.currentowner) {
 | 
        
           |  |  | 167 |             if (this.currentowner.get('node').ancestor('div').contains(e.target)) {
 | 
        
           |  |  | 168 |                 setTimeout(function() {
 | 
        
           |  |  | 169 |                     M.form.dateselector.cancel_any_timeout();
 | 
        
           |  |  | 170 |                 }, 100);
 | 
        
           |  |  | 171 |             } else {
 | 
        
           |  |  | 172 |                 this.currentowner.release_calendar(e);
 | 
        
           |  |  | 173 |             }
 | 
        
           |  |  | 174 |         }
 | 
        
           |  |  | 175 |     }
 | 
        
           |  |  | 176 | };
 | 
        
           |  |  | 177 | /**
 | 
        
           |  |  | 178 |  * Provides the Moodle Calendar class.
 | 
        
           |  |  | 179 |  *
 | 
        
           |  |  | 180 |  * @module moodle-form-dateselector
 | 
        
           |  |  | 181 |  */
 | 
        
           |  |  | 182 |   | 
        
           |  |  | 183 | /**
 | 
        
           |  |  | 184 |  * A class to overwrite the YUI3 Calendar in order to change the strings..
 | 
        
           |  |  | 185 |  *
 | 
        
           |  |  | 186 |  * @class M.form_moodlecalendar
 | 
        
           |  |  | 187 |  * @constructor
 | 
        
           |  |  | 188 |  * @extends Calendar
 | 
        
           |  |  | 189 |  */
 | 
        
           |  |  | 190 | MOODLECALENDAR = function() {
 | 
        
           |  |  | 191 |     MOODLECALENDAR.superclass.constructor.apply(this, arguments);
 | 
        
           |  |  | 192 | };
 | 
        
           |  |  | 193 |   | 
        
           |  |  | 194 | Y.extend(MOODLECALENDAR, Y.Calendar, {
 | 
        
           |  |  | 195 |         initializer: function(cfg) {
 | 
        
           |  |  | 196 |             this.set("strings.very_short_weekdays", cfg.WEEKDAYS_MEDIUM);
 | 
        
           |  |  | 197 |             this.set("strings.first_weekday", cfg.firstdayofweek);
 | 
        
           |  |  | 198 |         }
 | 
        
           |  |  | 199 |     }, {
 | 
        
           |  |  | 200 |         NAME: 'Calendar',
 | 
        
           |  |  | 201 |         ATTRS: {}
 | 
        
           |  |  | 202 |     }
 | 
        
           |  |  | 203 | );
 | 
        
           |  |  | 204 |   | 
        
           |  |  | 205 | M.form_moodlecalendar = M.form_moodlecalendar || {};
 | 
        
           |  |  | 206 | M.form_moodlecalendar.initializer = function(params) {
 | 
        
           |  |  | 207 |     return new MOODLECALENDAR(params);
 | 
        
           |  |  | 208 | };
 | 
        
           |  |  | 209 | /**
 | 
        
           |  |  | 210 |  * Provides the Calendar class.
 | 
        
           |  |  | 211 |  *
 | 
        
           |  |  | 212 |  * @module moodle-form-dateselector
 | 
        
           |  |  | 213 |  */
 | 
        
           |  |  | 214 |   | 
        
           |  |  | 215 | /**
 | 
        
           |  |  | 216 |  * Calendar class
 | 
        
           |  |  | 217 |  */
 | 
        
           |  |  | 218 | CALENDAR = function() {
 | 
        
           |  |  | 219 |     CALENDAR.superclass.constructor.apply(this, arguments);
 | 
        
           |  |  | 220 | };
 | 
        
           |  |  | 221 | CALENDAR.prototype = {
 | 
        
           |  |  | 222 |     panel: null,
 | 
        
           |  |  | 223 |     yearselect: null,
 | 
        
           |  |  | 224 |     monthselect: null,
 | 
        
           |  |  | 225 |     dayselect: null,
 | 
        
           |  |  | 226 |     calendarimage: null,
 | 
        
           |  |  | 227 |     enablecheckbox: null,
 | 
        
           |  |  | 228 |     closepopup: true,
 | 
        
           |  |  | 229 |     initializer: function() {
 | 
        
           |  |  | 230 |         var controls = this.get('node').all('select');
 | 
        
           |  |  | 231 |         controls.each(function(node) {
 | 
        
           |  |  | 232 |             if (node.get('name').match(/\[year\]/)) {
 | 
        
           |  |  | 233 |                 this.yearselect = node;
 | 
        
           |  |  | 234 |             } else if (node.get('name').match(/\[month\]/)) {
 | 
        
           |  |  | 235 |                 this.monthselect = node;
 | 
        
           |  |  | 236 |             } else if (node.get('name').match(/\[day\]/)) {
 | 
        
           |  |  | 237 |                 this.dayselect = node;
 | 
        
           |  |  | 238 |             }
 | 
        
           |  |  | 239 |             node.after('change', this.handle_select_change, this);
 | 
        
           |  |  | 240 |         }, this);
 | 
        
           |  |  | 241 |   | 
        
           |  |  | 242 |         // Loop through the input fields.
 | 
        
           | 1441 | ariadna | 243 |         var inputs = this.get('node').all('input, button');
 | 
        
           | 1 | efrain | 244 |         inputs.each(function(node) {
 | 
        
           |  |  | 245 |             // Check if the current node is a calendar image field.
 | 
        
           |  |  | 246 |             if (node.get('name').match(/\[calendar\]/)) {
 | 
        
           |  |  | 247 |                 // Set it so that when the image is clicked the pop-up displays.
 | 
        
           |  |  | 248 |                 node.on('click', this.focus_event, this);
 | 
        
           |  |  | 249 |                 // Set the node to the calendarimage variable.
 | 
        
           |  |  | 250 |                 this.calendarimage = node;
 | 
        
           |  |  | 251 |             } else { // Must be the enabled checkbox field.
 | 
        
           |  |  | 252 |                 // If the enable checkbox is clicked we want to either disable/enable the calendar image.
 | 
        
           |  |  | 253 |                 node.on('click', this.toggle_calendar_image, this);
 | 
        
           |  |  | 254 |                 // Set the node to the enablecheckbox variable.
 | 
        
           |  |  | 255 |                 this.enablecheckbox = node;
 | 
        
           |  |  | 256 |             }
 | 
        
           |  |  | 257 |             // Ensure that the calendarimage and enablecheckbox values have been set.
 | 
        
           |  |  | 258 |             if (this.calendarimage && this.enablecheckbox) {
 | 
        
           |  |  | 259 |                 // Set the calendar icon status depending on the value of the checkbox.
 | 
        
           |  |  | 260 |                 this.toggle_calendar_image();
 | 
        
           |  |  | 261 |             }
 | 
        
           |  |  | 262 |         }, this);
 | 
        
           |  |  | 263 |   | 
        
           |  |  | 264 |         // Get the calendarimage element by its ID and check if any of its parents have the modal-dialog class to
 | 
        
           |  |  | 265 |         // know if the link is inside a modal, if so, set the aria-hidden and tabindex properties to the indicated values.
 | 
        
           |  |  | 266 |         var calendarimageelement = document.getElementById(this.calendarimage.get('id'));
 | 
        
           |  |  | 267 |         if (calendarimageelement.closest('.modal-dialog')) {
 | 
        
           |  |  | 268 |             this.calendarimage.set('aria-hidden', true);
 | 
        
           |  |  | 269 |             this.calendarimage.set('tabIndex', '-1');
 | 
        
           |  |  | 270 |         }
 | 
        
           |  |  | 271 |     },
 | 
        
           |  |  | 272 |     focus_event: function(e) {
 | 
        
           |  |  | 273 |         M.form.dateselector.cancel_any_timeout();
 | 
        
           |  |  | 274 |         // If the current owner is set, then the pop-up is currently being displayed, so hide it.
 | 
        
           |  |  | 275 |         if (M.form.dateselector.currentowner === this) {
 | 
        
           |  |  | 276 |             this.release_calendar();
 | 
        
           |  |  | 277 |         } else if ((this.enablecheckbox === null)
 | 
        
           |  |  | 278 |             || (this.enablecheckbox.get('checked'))) { // Must be hidden. If the field is enabled display the pop-up.
 | 
        
           |  |  | 279 |             this.claim_calendar();
 | 
        
           |  |  | 280 |         }
 | 
        
           |  |  | 281 |         // Stop the input image field from submitting the form.
 | 
        
           |  |  | 282 |         e.preventDefault();
 | 
        
           |  |  | 283 |     },
 | 
        
           |  |  | 284 |     handle_select_change: function() {
 | 
        
           |  |  | 285 |         // It may seem as if the following variable is not used, however any call to set_date_from_selects will trigger a
 | 
        
           |  |  | 286 |         // call to set_selects_from_date if the calendar is open as the date has changed. Whenever the calendar is displayed
 | 
        
           |  |  | 287 |         // the set_selects_from_date function is set to trigger on any date change (see function connect_handlers).
 | 
        
           |  |  | 288 |         this.closepopup = false;
 | 
        
           |  |  | 289 |         this.set_date_from_selects();
 | 
        
           |  |  | 290 |         this.closepopup = true;
 | 
        
           |  |  | 291 |     },
 | 
        
           |  |  | 292 |     claim_calendar: function() {
 | 
        
           |  |  | 293 |         M.form.dateselector.cancel_any_timeout();
 | 
        
           |  |  | 294 |         if (M.form.dateselector.currentowner === this) {
 | 
        
           |  |  | 295 |             return;
 | 
        
           |  |  | 296 |         }
 | 
        
           |  |  | 297 |         if (M.form.dateselector.currentowner) {
 | 
        
           |  |  | 298 |             M.form.dateselector.currentowner.release_calendar();
 | 
        
           |  |  | 299 |         }
 | 
        
           |  |  | 300 |         if (M.form.dateselector.currentowner !== this) {
 | 
        
           |  |  | 301 |             this.connect_handlers();
 | 
        
           |  |  | 302 |             this.set_date_from_selects();
 | 
        
           |  |  | 303 |         }
 | 
        
           |  |  | 304 |         M.form.dateselector.currentowner = this;
 | 
        
           |  |  | 305 |         M.form.dateselector.calendar.set('minimumDate', new Date(this.yearselect.firstOptionValue(), 0, 1));
 | 
        
           |  |  | 306 |         M.form.dateselector.calendar.set('maximumDate', new Date(this.yearselect.lastOptionValue(), 11, 31));
 | 
        
           |  |  | 307 |         M.form.dateselector.panel.show();
 | 
        
           |  |  | 308 |         M.form.dateselector.calendar.show();
 | 
        
           |  |  | 309 |         M.form.dateselector.fix_position();
 | 
        
           |  |  | 310 |         setTimeout(function() {
 | 
        
           |  |  | 311 |             M.form.dateselector.cancel_any_timeout();
 | 
        
           |  |  | 312 |         }, 100);
 | 
        
           |  |  | 313 |   | 
        
           |  |  | 314 |         // Focus on the calendar.
 | 
        
           |  |  | 315 |         M.form.dateselector.calendar.focus();
 | 
        
           |  |  | 316 |   | 
        
           |  |  | 317 |         // When the user tab out the calendar, close it.
 | 
        
           |  |  | 318 |         Y.one(document.body).on('keyup', function(e) {
 | 
        
           |  |  | 319 |             // If the calendar is open and we try to access it by pressing tab, we check if it is inside a Bootstrap dropdown-menu,
 | 
        
           |  |  | 320 |             // if so, we keep the dropdown open while navigation takes place in the calendar.
 | 
        
           |  |  | 321 |             if (M.form.dateselector.currentowner && e.keyCode === 9) {
 | 
        
           |  |  | 322 |                 e.stopPropagation();
 | 
        
           |  |  | 323 |                 var calendarimageelement = document.getElementById(M.form.dateselector.currentowner.calendarimage.get('id'));
 | 
        
           |  |  | 324 |                 if (M.form.dateselector.calendar.get('focused') && calendarimageelement.closest('.dropdown-menu') &&
 | 
        
           |  |  | 325 |                     !calendarimageelement.closest('.dropdown-menu').classList.contains("show")) {
 | 
        
           |  |  | 326 |                     calendarimageelement.closest('.dropdown-menu').classList.add('show');
 | 
        
           |  |  | 327 |                 }
 | 
        
           |  |  | 328 |             }
 | 
        
           |  |  | 329 |   | 
        
           |  |  | 330 |             // hide the calendar if we press a key and the calendar is not focussed, or if we press ESC in the calendar.
 | 
        
           |  |  | 331 |             if ((M.form.dateselector.currentowner === this && !M.form.dateselector.calendar.get('focused')) ||
 | 
        
           |  |  | 332 |                 ((e.keyCode === 27) && M.form.dateselector.calendar.get('focused'))) {
 | 
        
           |  |  | 333 |                 // Focus back on the calendar button.
 | 
        
           |  |  | 334 |                 this.calendarimage.focus();
 | 
        
           |  |  | 335 |                 this.release_calendar();
 | 
        
           |  |  | 336 |             }
 | 
        
           |  |  | 337 |         }, this);
 | 
        
           |  |  | 338 |   | 
        
           |  |  | 339 |     },
 | 
        
           |  |  | 340 |     set_date_from_selects: function() {
 | 
        
           |  |  | 341 |         var year = parseInt(this.yearselect.get('value'), 10);
 | 
        
           |  |  | 342 |         var month = parseInt(this.monthselect.get('value'), 10) - 1;
 | 
        
           |  |  | 343 |         var day = parseInt(this.dayselect.get('value'), 10);
 | 
        
           |  |  | 344 |         var date = new Date(year, month, day);
 | 
        
           |  |  | 345 |         M.form.dateselector.calendar.deselectDates();
 | 
        
           |  |  | 346 |         M.form.dateselector.calendar.selectDates([date]);
 | 
        
           |  |  | 347 |         M.form.dateselector.calendar.set("date", date);
 | 
        
           |  |  | 348 |         M.form.dateselector.calendar.render();
 | 
        
           |  |  | 349 |         if (date.getDate() !== day) {
 | 
        
           |  |  | 350 |             // Must've selected the 29 to 31st of a month that doesn't have such dates.
 | 
        
           |  |  | 351 |             this.dayselect.set('value', date.getDate());
 | 
        
           |  |  | 352 |             this.monthselect.set('value', date.getMonth() + 1);
 | 
        
           |  |  | 353 |         }
 | 
        
           |  |  | 354 |     },
 | 
        
           |  |  | 355 |     set_selects_from_date: function(ev) {
 | 
        
           |  |  | 356 |         var date = ev.newSelection[0];
 | 
        
           |  |  | 357 |         var newyear = Y.DataType.Date.format(date, {format: "%Y"});
 | 
        
           |  |  | 358 |         var newindex = newyear - this.yearselect.firstOptionValue();
 | 
        
           |  |  | 359 |         this.yearselect.set('selectedIndex', newindex);
 | 
        
           |  |  | 360 |         this.monthselect.set('selectedIndex', Y.DataType.Date.format(date, {format: "%m"}) - this.monthselect.firstOptionValue());
 | 
        
           |  |  | 361 |         this.dayselect.set('selectedIndex', Y.DataType.Date.format(date, {format: "%d"}) - this.dayselect.firstOptionValue());
 | 
        
           |  |  | 362 |         if (M.form.dateselector.currentowner && this.closepopup) {
 | 
        
           |  |  | 363 |             this.release_calendar();
 | 
        
           |  |  | 364 |         }
 | 
        
           |  |  | 365 |     },
 | 
        
           |  |  | 366 |     connect_handlers: function() {
 | 
        
           |  |  | 367 |         M.form.dateselector.calendar.on('selectionChange', this.set_selects_from_date, this, true);
 | 
        
           |  |  | 368 |     },
 | 
        
           |  |  | 369 |     release_calendar: function(e) {
 | 
        
           |  |  | 370 |         var wasOwner = M.form.dateselector.currentowner === this;
 | 
        
           |  |  | 371 |         M.form.dateselector.panel.hide();
 | 
        
           |  |  | 372 |         M.form.dateselector.calendar.detach('selectionChange', this.set_selects_from_date);
 | 
        
           |  |  | 373 |         M.form.dateselector.calendar.hide();
 | 
        
           |  |  | 374 |         M.form.dateselector.currentowner = null;
 | 
        
           |  |  | 375 |   | 
        
           |  |  | 376 |         // Put the focus back to the image calendar that we clicked, only if it was visible.
 | 
        
           |  |  | 377 |         if (wasOwner && (e === null || typeof e === "undefined" || e.type !== "click")) {
 | 
        
           |  |  | 378 |             this.calendarimage.focus();
 | 
        
           |  |  | 379 |         }
 | 
        
           |  |  | 380 |     },
 | 
        
           |  |  | 381 |     toggle_calendar_image: function() {
 | 
        
           |  |  | 382 |         // If the enable checkbox is not checked, disable the calendar image and prevent focus.
 | 
        
           |  |  | 383 |         if (!this.enablecheckbox.get('checked')) {
 | 
        
           | 1441 | ariadna | 384 |             this.calendarimage.setAttribute('disabled');
 | 
        
           | 1 | efrain | 385 |             this.release_calendar();
 | 
        
           |  |  | 386 |         } else {
 | 
        
           | 1441 | ariadna | 387 |             this.calendarimage.removeAttribute('disabled');
 | 
        
           | 1 | efrain | 388 |         }
 | 
        
           |  |  | 389 |     }
 | 
        
           |  |  | 390 | };
 | 
        
           |  |  | 391 | Y.extend(CALENDAR, Y.Base, CALENDAR.prototype, {
 | 
        
           |  |  | 392 |     NAME: 'Date Selector',
 | 
        
           |  |  | 393 |     ATTRS: {
 | 
        
           |  |  | 394 |         firstdayofweek: {
 | 
        
           |  |  | 395 |             validator: Y.Lang.isString
 | 
        
           |  |  | 396 |         },
 | 
        
           |  |  | 397 |         node: {
 | 
        
           |  |  | 398 |             setter: function(node) {
 | 
        
           |  |  | 399 |                 return Y.one(node);
 | 
        
           |  |  | 400 |             }
 | 
        
           |  |  | 401 |         }
 | 
        
           |  |  | 402 |     }
 | 
        
           |  |  | 403 | });
 | 
        
           |  |  | 404 |   | 
        
           |  |  | 405 |   | 
        
           |  |  | 406 | }, '@VERSION@', {"requires": ["base", "node", "overlay", "calendar"]});
 |