Commit | Line | Data |
---|---|---|
e5473854 SH |
1 | YUI.add('moodle-form-dateselector', function(Y) { |
2 | ||
3 | /** | |
4 | * Add some custom methods to the node class to make our lives a little | |
5 | * easier within this module. | |
6 | */ | |
7 | Y.mix(Y.Node.prototype, { | |
8 | /** | |
9 | * Gets the value of the first option in the select box | |
10 | */ | |
11 | firstOptionValue : function() { | |
12 | if (this.get('nodeName').toLowerCase() != 'select') { | |
13 | return false; | |
14 | } | |
15 | return this.one('option').get('value'); | |
16 | }, | |
17 | /** | |
18 | * Gets the value of the last option in the select box | |
19 | */ | |
20 | lastOptionValue : function() { | |
21 | if (this.get('nodeName').toLowerCase() != 'select') { | |
22 | return false; | |
23 | } | |
24 | return this.all('option').item(this.optionSize()-1).get('value'); | |
25 | }, | |
26 | /** | |
27 | * Gets the number of options in the select box | |
28 | */ | |
29 | optionSize : function() { | |
30 | if (this.get('nodeName').toLowerCase() != 'select') { | |
31 | return false; | |
32 | } | |
33 | return parseInt(this.all('option').size()); | |
34 | }, | |
35 | /** | |
36 | * Gets the value of the selected option in the select box | |
37 | */ | |
38 | selectedOptionValue : function() { | |
39 | if (this.get('nodeName').toLowerCase() != 'select') { | |
40 | return false; | |
41 | } | |
42 | return this.all('option').item(this.get('selectedIndex')).get('value'); | |
43 | } | |
44 | }); | |
45 | ||
e5473854 SH |
46 | /** |
47 | * Calendar class | |
48 | * | |
49 | * This is our main class | |
50 | */ | |
51 | var CALENDAR = function(config) { | |
52 | CALENDAR.superclass.constructor.apply(this, arguments); | |
d3067516 | 53 | }; |
e5473854 SH |
54 | CALENDAR.prototype = { |
55 | panel : null, | |
56 | yearselect : null, | |
e5473854 | 57 | monthselect : null, |
e5473854 | 58 | dayselect : null, |
f40df210 | 59 | calendarimage : null, |
e5473854 | 60 | enablecheckbox : null, |
f40df210 | 61 | closepopup : true, |
e5473854 SH |
62 | initializer : function(config) { |
63 | var controls = this.get('node').all('select'); | |
64 | controls.each(function(node){ | |
65 | if (node.get('name').match(/\[year]/)) { | |
66 | this.yearselect = node; | |
67 | } else if (node.get('name').match(/\[month\]/)) { | |
68 | this.monthselect = node; | |
69 | } else if (node.get('name').match(/\[day]/)) { | |
70 | this.dayselect = node; | |
e5473854 | 71 | } |
f40df210 | 72 | node.after('change', this.handle_select_change, this); |
e5473854 SH |
73 | }, this); |
74 | ||
f40df210 MN |
75 | // Loop through the input fields. |
76 | var inputs = this.get('node').all('input'); | |
77 | inputs.each(function(node) { | |
78 | // Check if the current node is a calendar image field. | |
79 | if (node.get('name').match(/\[calendar]/)) { | |
80 | // Set it so that when the image is clicked the pop-up displays. | |
81 | node.on('click', this.focus_event, this); | |
82 | // Set the node to the calendarimage variable. | |
83 | this.calendarimage = node; | |
84 | } else { // Must be the enabled checkbox field. | |
85 | // If the enable checkbox is clicked we want to either disable/enable the calendar image. | |
86 | node.on('click', this.toggle_calendar_image, this); | |
87 | // Set the node to the enablecheckbox variable. | |
88 | this.enablecheckbox = node; | |
89 | // Set the calendar icon status depending on the value of the checkbox. | |
668aaeb8 EL |
90 | // QUICK HACK to keep JS working. MDL-26649. FIXME! |
91 | // this.toggle_calendar_image(); | |
f40df210 MN |
92 | } |
93 | }, this); | |
e5473854 SH |
94 | }, |
95 | focus_event : function(e) { | |
96 | M.form.dateselector.cancel_any_timeout(); | |
f40df210 MN |
97 | // If the current owner is set, then the pop-up is currently being displayed, so hide it. |
98 | if (M.form.dateselector.currentowner) { | |
99 | this.release_calendar(); | |
100 | } else if ((this.enablecheckbox == null) | |
101 | || (this.enablecheckbox.get('checked'))) { // Must be hidden. If the field is enabled display the pop-up. | |
e5473854 | 102 | this.claim_calendar(); |
e5473854 | 103 | } |
f40df210 MN |
104 | // Stop the input image field from submitting the form. |
105 | e.preventDefault(); | |
e5473854 SH |
106 | }, |
107 | handle_select_change : function(e) { | |
f40df210 MN |
108 | // It may seem as if the following variable is not used, however any call to set_date_from_selects will trigger a |
109 | // call to set_selects_from_date if the calendar is open as the date has changed. Whenever the calendar is displayed | |
110 | // the set_selects_from_date function is set to trigger on any date change (see function connect_handlers). | |
111 | this.closepopup = false; | |
e5473854 | 112 | this.set_date_from_selects(); |
f40df210 | 113 | this.closepopup = true; |
e5473854 SH |
114 | }, |
115 | claim_calendar : function() { | |
116 | M.form.dateselector.cancel_any_timeout(); | |
f40df210 MN |
117 | this.connect_handlers(); |
118 | this.set_date_from_selects(); | |
e5473854 SH |
119 | M.form.dateselector.currentowner = this; |
120 | M.form.dateselector.calendar.cfg.setProperty('mindate', new Date(this.yearselect.firstOptionValue(), 0, 1)); | |
121 | M.form.dateselector.calendar.cfg.setProperty('maxdate', new Date(this.yearselect.lastOptionValue(), 11, 31)); | |
e5473854 SH |
122 | M.form.dateselector.panel.show(); |
123 | M.form.dateselector.fix_position(); | |
124 | setTimeout(function(){M.form.dateselector.cancel_any_timeout()}, 100); | |
125 | }, | |
126 | set_date_from_selects : function() { | |
127 | var year = parseInt(this.yearselect.get('value')); | |
128 | var month = parseInt(this.monthselect.get('value')) - 1; | |
129 | var day = parseInt(this.dayselect.get('value')); | |
130 | M.form.dateselector.calendar.select(new Date(year, month, day)); | |
131 | M.form.dateselector.calendar.setMonth(month); | |
132 | M.form.dateselector.calendar.setYear(year); | |
133 | M.form.dateselector.calendar.render(); | |
134 | }, | |
135 | set_selects_from_date : function(eventtype, args) { | |
136 | var date = args[0][0]; | |
137 | var newyear = date[0]; | |
138 | var newindex = newyear - this.yearselect.firstOptionValue(); | |
139 | this.yearselect.set('selectedIndex', newindex); | |
140 | this.monthselect.set('selectedIndex', date[1] - this.monthselect.firstOptionValue()); | |
141 | this.dayselect.set('selectedIndex', date[2] - this.dayselect.firstOptionValue()); | |
f40df210 MN |
142 | if (M.form.dateselector.currentowner && this.closepopup) { |
143 | this.release_calendar(); | |
144 | } | |
e5473854 SH |
145 | }, |
146 | connect_handlers : function() { | |
147 | M.form.dateselector.calendar.selectEvent.subscribe(this.set_selects_from_date, this, true); | |
148 | }, | |
149 | release_calendar : function() { | |
150 | M.form.dateselector.panel.hide(); | |
151 | M.form.dateselector.currentowner = null; | |
152 | M.form.dateselector.calendar.selectEvent.unsubscribe(this.set_selects_from_date, this); | |
f40df210 MN |
153 | }, |
154 | toggle_calendar_image : function() { | |
155 | // If the enable checkbox is not checked, disable the image. | |
156 | if (!this.enablecheckbox.get('checked')) { | |
157 | this.calendarimage.set('disabled', 'disabled'); | |
158 | this.calendarimage.setStyle('cursor', 'default'); | |
159 | } else { | |
160 | this.calendarimage.set('disabled', false); | |
161 | this.calendarimage.setStyle('cursor', 'auto'); | |
162 | } | |
e5473854 | 163 | } |
d3067516 | 164 | }; |
e5473854 SH |
165 | Y.extend(CALENDAR, Y.Base, CALENDAR.prototype, { |
166 | NAME : 'Date Selector', | |
167 | ATTRS : { | |
168 | firstdayofweek : { | |
169 | validator : Y.Lang.isString | |
170 | }, | |
171 | node : { | |
172 | setter : function(node) { | |
173 | return Y.one(node); | |
174 | } | |
175 | } | |
176 | } | |
177 | }); | |
178 | ||
179 | M.form = M.form || {}; | |
180 | M.form.dateselector = { | |
181 | panel : null, | |
182 | calendar : null, | |
183 | currentowner : null, | |
184 | hidetimeout : null, | |
185 | repositiontimeout : null, | |
186 | init_date_selectors : function(config) { | |
187 | if (this.panel === null) { | |
188 | this.initPanel(config); | |
189 | } | |
190 | Y.all('fieldset.fdate_time_selector').each(function(){ | |
191 | config.node = this; | |
192 | new CALENDAR(config); | |
193 | }); | |
194 | Y.all('fieldset.fdate_selector').each(function(){ | |
195 | config.node = this; | |
196 | new CALENDAR(config); | |
197 | }); | |
198 | }, | |
199 | initPanel : function(config) { | |
200 | this.panel = new Y.Overlay({ | |
201 | visible : false, | |
e5473854 SH |
202 | bodyContent : Y.Node.create('<div id="dateselector-calendar-content"></div>'), |
203 | id : 'dateselector-calendar-panel' | |
204 | }); | |
205 | this.panel.render(document.body); | |
206 | this.panel.on('heightChange', this.fix_position, this); | |
207 | ||
208 | Y.one('#dateselector-calendar-panel').on('click', function(e){e.halt();}); | |
209 | Y.one(document.body).on('click', this.document_click, this); | |
210 | ||
6adabe48 | 211 | this.calendar = new Y.YUI2.widget.Calendar(document.getElementById('dateselector-calendar-content'), { |
e5473854 SH |
212 | iframe: false, |
213 | hide_blank_weeks: true, | |
a0658f00 FM |
214 | start_weekday: config.firstdayofweek, |
215 | locale_weekdays: 'medium', | |
216 | locale_months: 'long', | |
217 | WEEKDAYS_MEDIUM: [ | |
218 | config.sun, | |
219 | config.mon, | |
220 | config.tue, | |
221 | config.wed, | |
222 | config.thu, | |
223 | config.fri, | |
224 | config.sat ], | |
225 | MONTHS_LONG: [ | |
226 | config.january, | |
227 | config.february, | |
228 | config.march, | |
229 | config.april, | |
230 | config.may, | |
231 | config.june, | |
232 | config.july, | |
233 | config.august, | |
234 | config.september, | |
235 | config.october, | |
236 | config.november, | |
8f38558b | 237 | config.december ] |
e5473854 SH |
238 | }); |
239 | this.calendar.changePageEvent.subscribe(function(){ | |
240 | this.fix_position(); | |
241 | }, this); | |
242 | }, | |
243 | cancel_any_timeout : function() { | |
244 | if (this.hidetimeout) { | |
245 | clearTimeout(this.hidetimeout); | |
246 | this.hidetimeout = null; | |
247 | } | |
248 | if (this.repositiontimeout) { | |
249 | clearTimeout(this.repositiontimeout); | |
250 | this.repositiontimeout = null; | |
251 | } | |
252 | }, | |
253 | delayed_reposition : function() { | |
254 | if (this.repositiontimeout) { | |
255 | clearTimeout(this.repositiontimeout); | |
256 | this.repositiontimeout = null; | |
257 | } | |
258 | this.repositiontimeout = setTimeout(this.fix_position, 500); | |
259 | }, | |
260 | fix_position : function() { | |
261 | if (this.currentowner) { | |
e5473854 SH |
262 | this.panel.set('align', { |
263 | node:this.currentowner.get('node').one('select'), | |
264 | points:[Y.WidgetPositionAlign.BL, Y.WidgetPositionAlign.TL] | |
265 | }); | |
266 | } | |
267 | }, | |
e5473854 SH |
268 | document_click : function(e) { |
269 | if (this.currentowner) { | |
270 | if (this.currentowner.get('node').ancestor('div').contains(e.target)) { | |
271 | setTimeout(function() {M.form.dateselector.cancel_any_timeout()}, 100); | |
272 | } else { | |
273 | this.currentowner.release_calendar(); | |
274 | } | |
275 | } | |
276 | } | |
277 | } | |
d3067516 | 278 | |
668aaeb8 | 279 | }, '@VERSION@', {requires:['base','node','overlay', 'yui2-calendar', 'moodle-form-dateselector-skin']}); |