weekly release 2.4dev
[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));
118 M.form.dateselector.panel.set('constrain', this.get('node').ancestor('form'));
119 M.form.dateselector.panel.show();
120 M.form.dateselector.fix_position();
121 setTimeout(function(){M.form.dateselector.cancel_any_timeout()}, 100);
122 },
123 set_date_from_selects : function() {
124 var year = parseInt(this.yearselect.get('value'));
125 var month = parseInt(this.monthselect.get('value')) - 1;
126 var day = parseInt(this.dayselect.get('value'));
127 M.form.dateselector.calendar.select(new Date(year, month, day));
128 M.form.dateselector.calendar.setMonth(month);
129 M.form.dateselector.calendar.setYear(year);
130 M.form.dateselector.calendar.render();
131 },
132 set_selects_from_date : function(eventtype, args) {
133 var date = args[0][0];
134 var newyear = date[0];
135 var newindex = newyear - this.yearselect.firstOptionValue();
136 this.yearselect.set('selectedIndex', newindex);
137 this.monthselect.set('selectedIndex', date[1] - this.monthselect.firstOptionValue());
138 this.dayselect.set('selectedIndex', date[2] - this.dayselect.firstOptionValue());
b286fcdf 139 M.form.dateselector.release_current();
e5473854
SH
140 },
141 connect_handlers : function() {
142 M.form.dateselector.calendar.selectEvent.subscribe(this.set_selects_from_date, this, true);
143 },
144 release_calendar : function() {
145 M.form.dateselector.panel.hide();
146 M.form.dateselector.currentowner = null;
147 M.form.dateselector.calendar.selectEvent.unsubscribe(this.set_selects_from_date, this);
148 }
d3067516 149 };
e5473854
SH
150 Y.extend(CALENDAR, Y.Base, CALENDAR.prototype, {
151 NAME : 'Date Selector',
152 ATTRS : {
153 firstdayofweek : {
154 validator : Y.Lang.isString
155 },
156 node : {
157 setter : function(node) {
158 return Y.one(node);
159 }
160 }
161 }
162 });
163
164 M.form = M.form || {};
165 M.form.dateselector = {
166 panel : null,
167 calendar : null,
168 currentowner : null,
169 hidetimeout : null,
170 repositiontimeout : null,
171 init_date_selectors : function(config) {
172 if (this.panel === null) {
173 this.initPanel(config);
174 }
175 Y.all('fieldset.fdate_time_selector').each(function(){
176 config.node = this;
177 new CALENDAR(config);
178 });
179 Y.all('fieldset.fdate_selector').each(function(){
180 config.node = this;
181 new CALENDAR(config);
182 });
183 },
184 initPanel : function(config) {
185 this.panel = new Y.Overlay({
186 visible : false,
187 constrain : true,
188 bodyContent : Y.Node.create('<div id="dateselector-calendar-content"></div>'),
189 id : 'dateselector-calendar-panel'
190 });
191 this.panel.render(document.body);
192 this.panel.on('heightChange', this.fix_position, this);
193
194 Y.one('#dateselector-calendar-panel').on('click', function(e){e.halt();});
195 Y.one(document.body).on('click', this.document_click, this);
196
197 this.calendar = new YAHOO.widget.Calendar(document.getElementById('dateselector-calendar-content'), {
198 iframe: false,
199 hide_blank_weeks: true,
200 start_weekday: config.firstdayofweek
201 });
202 this.calendar.changePageEvent.subscribe(function(){
203 this.fix_position();
204 }, this);
205 },
206 cancel_any_timeout : function() {
207 if (this.hidetimeout) {
208 clearTimeout(this.hidetimeout);
209 this.hidetimeout = null;
210 }
211 if (this.repositiontimeout) {
212 clearTimeout(this.repositiontimeout);
213 this.repositiontimeout = null;
214 }
215 },
216 delayed_reposition : function() {
217 if (this.repositiontimeout) {
218 clearTimeout(this.repositiontimeout);
219 this.repositiontimeout = null;
220 }
221 this.repositiontimeout = setTimeout(this.fix_position, 500);
222 },
223 fix_position : function() {
224 if (this.currentowner) {
7b38412d 225 this.panel.set('constrain', Y.one(document.body));
e5473854
SH
226 this.panel.set('align', {
227 node:this.currentowner.get('node').one('select'),
228 points:[Y.WidgetPositionAlign.BL, Y.WidgetPositionAlign.TL]
229 });
230 }
231 },
232 release_current : function() {
233 if (this.currentowner) {
234 this.currentowner.release_calendar();
235 }
236 },
237 document_click : function(e) {
238 if (this.currentowner) {
239 if (this.currentowner.get('node').ancestor('div').contains(e.target)) {
240 setTimeout(function() {M.form.dateselector.cancel_any_timeout()}, 100);
241 } else {
242 this.currentowner.release_calendar();
243 }
244 }
245 }
246 }
d3067516 247
e5473854 248}, '@VERSION@', {requires:['base','node','overlay', 'yui2-calendar', 'moodle-form-dateselector-skin']});