Moodle release 2.5beta
[moodle.git] / lib / form / yui / dateselector / dateselector.js
CommitLineData
e5473854
SH
1YUI.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,
57 yearselectchange : null,
58 monthselect : null,
59 monthselectchange : null,
60 dayselect : null,
61 dayselectchange : null,
62 enablecheckbox : null,
63 initializer : function(config) {
64 var controls = this.get('node').all('select');
65 controls.each(function(node){
66 if (node.get('name').match(/\[year]/)) {
67 this.yearselect = node;
68 } else if (node.get('name').match(/\[month\]/)) {
69 this.monthselect = node;
70 } else if (node.get('name').match(/\[day]/)) {
71 this.dayselect = node;
72 } else {
c7e3e61c 73 node.on('focus', M.form.dateselector.cancel_any_timeout, M.form.dateselector);
e5473854
SH
74 node.on('blur', this.blur_event, this);
75 return;
76 }
e18d7d2f 77 node.on('focus', this.focus_event, this);
4598fb65
SH
78 node.on('click', this.focus_event, this);
79 node.after('change', this.set_date_from_selects, this);
e5473854
SH
80 }, this);
81
82 if (this.yearselect && this.monthselect && this.dayselect) {
83 this.enablecheckbox = this.get('node').one('input');
e5473854
SH
84 }
85 },
86 focus_event : function(e) {
87 M.form.dateselector.cancel_any_timeout();
88 if (this.enablecheckbox == null || this.enablecheckbox.get('checked')) {
89 this.claim_calendar();
90 } else {
91 if (M.form.dateselector.currentowner) {
92 M.form.dateselector.currentowner.release_calendar();
93 }
94 }
95 },
96 blur_event : function(e) {
97 M.form.dateselector.hidetimeout = setTimeout(M.form.dateselector.release_current, 300);
98 },
99 handle_select_change : function(e) {
100 this.set_date_from_selects();
101 },
102 claim_calendar : function() {
103 M.form.dateselector.cancel_any_timeout();
104 if (M.form.dateselector.currentowner == this) {
105 return;
106 }
107 if (M.form.dateselector.currentowner) {
108 M.form.dateselector.currentowner.release_calendar();
109 }
110
111 if (M.form.dateselector.currentowner != this) {
112 this.connect_handlers();
113 this.set_date_from_selects();
114 }
115 M.form.dateselector.currentowner = this;
116 M.form.dateselector.calendar.cfg.setProperty('mindate', new Date(this.yearselect.firstOptionValue(), 0, 1));
117 M.form.dateselector.calendar.cfg.setProperty('maxdate', new Date(this.yearselect.lastOptionValue(), 11, 31));
e5473854
SH
118 M.form.dateselector.panel.show();
119 M.form.dateselector.fix_position();
120 setTimeout(function(){M.form.dateselector.cancel_any_timeout()}, 100);
121 },
122 set_date_from_selects : function() {
123 var year = parseInt(this.yearselect.get('value'));
124 var month = parseInt(this.monthselect.get('value')) - 1;
125 var day = parseInt(this.dayselect.get('value'));
126 M.form.dateselector.calendar.select(new Date(year, month, day));
127 M.form.dateselector.calendar.setMonth(month);
128 M.form.dateselector.calendar.setYear(year);
129 M.form.dateselector.calendar.render();
130 },
131 set_selects_from_date : function(eventtype, args) {
132 var date = args[0][0];
133 var newyear = date[0];
134 var newindex = newyear - this.yearselect.firstOptionValue();
135 this.yearselect.set('selectedIndex', newindex);
136 this.monthselect.set('selectedIndex', date[1] - this.monthselect.firstOptionValue());
137 this.dayselect.set('selectedIndex', date[2] - this.dayselect.firstOptionValue());
b286fcdf 138 M.form.dateselector.release_current();
e5473854
SH
139 },
140 connect_handlers : function() {
141 M.form.dateselector.calendar.selectEvent.subscribe(this.set_selects_from_date, this, true);
142 },
143 release_calendar : function() {
144 M.form.dateselector.panel.hide();
145 M.form.dateselector.currentowner = null;
146 M.form.dateselector.calendar.selectEvent.unsubscribe(this.set_selects_from_date, this);
147 }
d3067516 148 };
e5473854
SH
149 Y.extend(CALENDAR, Y.Base, CALENDAR.prototype, {
150 NAME : 'Date Selector',
151 ATTRS : {
152 firstdayofweek : {
153 validator : Y.Lang.isString
154 },
155 node : {
156 setter : function(node) {
157 return Y.one(node);
158 }
159 }
160 }
161 });
162
163 M.form = M.form || {};
164 M.form.dateselector = {
165 panel : null,
166 calendar : null,
167 currentowner : null,
168 hidetimeout : null,
169 repositiontimeout : null,
170 init_date_selectors : function(config) {
171 if (this.panel === null) {
172 this.initPanel(config);
173 }
174 Y.all('fieldset.fdate_time_selector').each(function(){
175 config.node = this;
176 new CALENDAR(config);
177 });
178 Y.all('fieldset.fdate_selector').each(function(){
179 config.node = this;
180 new CALENDAR(config);
181 });
182 },
183 initPanel : function(config) {
184 this.panel = new Y.Overlay({
185 visible : false,
e5473854
SH
186 bodyContent : Y.Node.create('<div id="dateselector-calendar-content"></div>'),
187 id : 'dateselector-calendar-panel'
188 });
189 this.panel.render(document.body);
190 this.panel.on('heightChange', this.fix_position, this);
191
192 Y.one('#dateselector-calendar-panel').on('click', function(e){e.halt();});
193 Y.one(document.body).on('click', this.document_click, this);
194
6adabe48 195 this.calendar = new Y.YUI2.widget.Calendar(document.getElementById('dateselector-calendar-content'), {
e5473854
SH
196 iframe: false,
197 hide_blank_weeks: true,
a0658f00
FM
198 start_weekday: config.firstdayofweek,
199 locale_weekdays: 'medium',
200 locale_months: 'long',
201 WEEKDAYS_MEDIUM: [
202 config.sun,
203 config.mon,
204 config.tue,
205 config.wed,
206 config.thu,
207 config.fri,
208 config.sat ],
209 MONTHS_LONG: [
210 config.january,
211 config.february,
212 config.march,
213 config.april,
214 config.may,
215 config.june,
216 config.july,
217 config.august,
218 config.september,
219 config.october,
220 config.november,
8f38558b 221 config.december ]
e5473854
SH
222 });
223 this.calendar.changePageEvent.subscribe(function(){
224 this.fix_position();
225 }, this);
226 },
227 cancel_any_timeout : function() {
228 if (this.hidetimeout) {
229 clearTimeout(this.hidetimeout);
230 this.hidetimeout = null;
231 }
232 if (this.repositiontimeout) {
233 clearTimeout(this.repositiontimeout);
234 this.repositiontimeout = null;
235 }
236 },
237 delayed_reposition : function() {
238 if (this.repositiontimeout) {
239 clearTimeout(this.repositiontimeout);
240 this.repositiontimeout = null;
241 }
242 this.repositiontimeout = setTimeout(this.fix_position, 500);
243 },
244 fix_position : function() {
245 if (this.currentowner) {
e5473854
SH
246 this.panel.set('align', {
247 node:this.currentowner.get('node').one('select'),
248 points:[Y.WidgetPositionAlign.BL, Y.WidgetPositionAlign.TL]
249 });
250 }
251 },
252 release_current : function() {
253 if (this.currentowner) {
254 this.currentowner.release_calendar();
255 }
256 },
257 document_click : function(e) {
258 if (this.currentowner) {
259 if (this.currentowner.get('node').ancestor('div').contains(e.target)) {
260 setTimeout(function() {M.form.dateselector.cancel_any_timeout()}, 100);
261 } else {
262 this.currentowner.release_calendar();
263 }
264 }
265 }
266 }
d3067516 267
e5473854 268}, '@VERSION@', {requires:['base','node','overlay', 'yui2-calendar', 'moodle-form-dateselector-skin']});