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