c12dde28aa83150f3f9cd8299e7a68c5a1133e0b
[ais.git] / www / DateTimeShortcuts.js
1 // Inserts shortcut buttons after all of the following:
2 //     <input type="text" class="vDateField">
3 //     <input type="text" class="vTimeField">
4
5 var DateTimeShortcuts = {
6     calendars: [],
7     calendarInputs: [],
8     clockInputs: [],
9     calendarDivName1: 'calendarbox', // name of calendar <div> that gets toggled
10     calendarDivName2: 'calendarin',  // name of <div> that contains calendar
11     calendarLinkName: 'calendarlink',// name of the link that is used to toggle
12     clockDivName: 'clockbox',        // name of clock <div> that gets toggled
13     clockLinkName: 'clocklink',      // name of the link that is used to toggle
14     admin_media_prefix: '',
15     init: function() {
16         // Deduce admin_media_prefix by looking at the <script>s in the
17         // current document and finding the URL of *this* module.
18         var scripts = document.getElementsByTagName('script');
19         for (var i=0; i<scripts.length; i++) {
20             if (scripts[i].src.match(/DateTimeShortcuts/)) {
21                 //var idx = scripts[i].src.indexOf('js/admin/DateTimeShortcuts');
22                 var idx = scripts[i].src.indexOf('DateTimeShortcuts');
23                 DateTimeShortcuts.admin_media_prefix = scripts[i].src.substring(0, idx);
24                 // NIRGAL WAS HERE:
25                 DateTimeShortcuts.admin_media_prefix += 'media/'
26                 break;
27             }
28         }
29
30         var inputs = document.getElementsByTagName('input');
31         for (i=0; i<inputs.length; i++) {
32             var inp = inputs[i];
33             if (inp.getAttribute('type') == 'text' && inp.className.match(/vTimeField/)) {
34                 DateTimeShortcuts.addClock(inp);
35             }
36             else if (inp.getAttribute('type') == 'text' && inp.className.match(/vDateField/)) {
37                 DateTimeShortcuts.addCalendar(inp);
38             }
39         }
40     },
41     // Add clock widget to a given field
42     addClock: function(inp) {
43         var num = DateTimeShortcuts.clockInputs.length;
44         DateTimeShortcuts.clockInputs[num] = inp;
45
46         // Shortcut links (clock icon and "Now" link)
47         var shortcuts_span = document.createElement('span');
48         inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
49         var now_link = document.createElement('a');
50         now_link.setAttribute('href', "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().getHourMinuteSecond());");
51         now_link.appendChild(document.createTextNode(gettext('Now')));
52         var clock_link = document.createElement('a');
53         clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');');
54         clock_link.id = DateTimeShortcuts.clockLinkName + num;
55         quickElement('img', clock_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_clock.gif', 'alt', gettext('Clock'));
56         shortcuts_span.appendChild(document.createTextNode('\240'));
57         shortcuts_span.appendChild(now_link);
58         shortcuts_span.appendChild(document.createTextNode('\240|\240'));
59         shortcuts_span.appendChild(clock_link);
60
61         // Create clock link div
62         //
63         // Markup looks like:
64         // <div id="clockbox1" class="clockbox module">
65         //     <h2>Choose a time</h2>
66         //     <ul class="timelist">
67         //         <li><a href="#">Now</a></li>
68         //         <li><a href="#">Midnight</a></li>
69         //         <li><a href="#">6 a.m.</a></li>
70         //         <li><a href="#">Noon</a></li>
71         //     </ul>
72         //     <p class="calendar-cancel"><a href="#">Cancel</a></p>
73         // </div>
74
75         var clock_box = document.createElement('div');
76         clock_box.style.display = 'none';
77         clock_box.style.position = 'absolute';
78         clock_box.className = 'clockbox module';
79         clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
80         document.body.appendChild(clock_box);
81         addEvent(clock_box, 'click', DateTimeShortcuts.cancelEventPropagation);
82
83         quickElement('h2', clock_box, gettext('Choose a time'));
84         time_list = quickElement('ul', clock_box, '');
85         time_list.className = 'timelist';
86         quickElement("a", quickElement("li", time_list, ""), gettext("Now"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().getHourMinuteSecond());")
87         quickElement("a", quickElement("li", time_list, ""), gettext("Midnight"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '00:00:00');")
88         quickElement("a", quickElement("li", time_list, ""), gettext("6 a.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '06:00:00');")
89         quickElement("a", quickElement("li", time_list, ""), gettext("Noon"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '12:00:00');")
90
91         cancel_p = quickElement('p', clock_box, '');
92         cancel_p.className = 'calendar-cancel';
93         quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');');
94     },
95     openClock: function(num) {
96         var clock_box = document.getElementById(DateTimeShortcuts.clockDivName+num)
97         var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName+num)
98     
99         // Recalculate the clockbox position
100         // is it left-to-right or right-to-left layout ?
101         if (getStyle(document.body,'direction')!='rtl') {
102             clock_box.style.left = findPosX(clock_link) + 17 + 'px';
103         }
104         else {
105             // since style's width is in em, it'd be tough to calculate
106             // px value of it. let's use an estimated px for now
107             // TODO: IE returns wrong value for findPosX when in rtl mode
108             //       (it returns as it was left aligned), needs to be fixed.
109             clock_box.style.left = findPosX(clock_link) - 110 + 'px';
110         }
111         clock_box.style.top = findPosY(clock_link) - 30 + 'px';
112     
113         // Show the clock box
114         clock_box.style.display = 'block';
115         addEvent(window, 'click', function() { DateTimeShortcuts.dismissClock(num); return true; });
116     },
117     dismissClock: function(num) {
118        document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'none';
119        window.onclick = null;
120     },
121     handleClockQuicklink: function(num, val) {
122        DateTimeShortcuts.clockInputs[num].value = val;
123        DateTimeShortcuts.dismissClock(num);
124     },
125     // Add calendar widget to a given field.
126     addCalendar: function(inp) {
127         var num = DateTimeShortcuts.calendars.length;
128
129         DateTimeShortcuts.calendarInputs[num] = inp;
130
131         // Shortcut links (calendar icon and "Today" link)
132         var shortcuts_span = document.createElement('span');
133         inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
134         var today_link = document.createElement('a');
135         today_link.setAttribute('href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
136         today_link.appendChild(document.createTextNode(gettext('Today')));
137         var cal_link = document.createElement('a');
138         cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');');
139         cal_link.id = DateTimeShortcuts.calendarLinkName + num;
140         quickElement('img', cal_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_calendar.gif', 'alt', gettext('Calendar'));
141         shortcuts_span.appendChild(document.createTextNode('\240'));
142         shortcuts_span.appendChild(today_link);
143         shortcuts_span.appendChild(document.createTextNode('\240|\240'));
144         shortcuts_span.appendChild(cal_link);
145
146         // Create calendarbox div.
147         //
148         // Markup looks like:
149         //
150         // <div id="calendarbox3" class="calendarbox module">
151         //     <h2>
152         //           <a href="#" class="link-previous">&lsaquo;</a>
153         //           <a href="#" class="link-next">&rsaquo;</a> February 2003
154         //     </h2>
155         //     <div class="calendar" id="calendarin3">
156         //         <!-- (cal) -->
157         //     </div>
158         //     <div class="calendar-shortcuts">
159         //          <a href="#">Yesterday</a> | <a href="#">Today</a> | <a href="#">Tomorrow</a>
160         //     </div>
161         //     <p class="calendar-cancel"><a href="#">Cancel</a></p>
162         // </div>
163         var cal_box = document.createElement('div');
164         cal_box.style.display = 'none';
165         cal_box.style.position = 'absolute';
166         cal_box.className = 'calendarbox module';
167         cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
168         document.body.appendChild(cal_box);
169         addEvent(cal_box, 'click', DateTimeShortcuts.cancelEventPropagation);
170
171         // next-prev links
172         var cal_nav = quickElement('div', cal_box, '');
173         var cal_nav_prev = quickElement('a', cal_nav, '<', 'href', 'javascript:DateTimeShortcuts.drawPrev('+num+');');
174         cal_nav_prev.className = 'calendarnav-previous';
175         var cal_nav_next = quickElement('a', cal_nav, '>', 'href', 'javascript:DateTimeShortcuts.drawNext('+num+');');
176         cal_nav_next.className = 'calendarnav-next';
177
178         // main box
179         var cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num);
180         cal_main.className = 'calendar';
181         DateTimeShortcuts.calendars[num] = new Calendar(DateTimeShortcuts.calendarDivName2 + num, DateTimeShortcuts.handleCalendarCallback(num));
182         DateTimeShortcuts.calendars[num].drawCurrent();
183
184         // calendar shortcuts
185         var shortcuts = quickElement('div', cal_box, '');
186         shortcuts.className = 'calendar-shortcuts';
187         quickElement('a', shortcuts, gettext('Yesterday'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', -1);');
188         shortcuts.appendChild(document.createTextNode('\240|\240'));
189         quickElement('a', shortcuts, gettext('Today'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
190         shortcuts.appendChild(document.createTextNode('\240|\240'));
191         quickElement('a', shortcuts, gettext('Tomorrow'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', +1);');
192
193         // cancel bar
194         var cancel_p = quickElement('p', cal_box, '');
195         cancel_p.className = 'calendar-cancel';
196         quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');');
197     },
198     openCalendar: function(num) {
199         var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num)
200         var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+num)
201         var inp = DateTimeShortcuts.calendarInputs[num];
202
203         // Determine if the current value in the input has a valid date.
204         // If so, draw the calendar with that date's year and month.
205         if (inp.value) {
206             var date_parts = inp.value.split('-');
207             var year = date_parts[0];
208             var month = parseFloat(date_parts[1]);
209             if (year.match(/\d\d\d\d/) && month >= 1 && month <= 12) {
210                 DateTimeShortcuts.calendars[num].drawDate(month, year);
211             }
212         }
213
214     
215         // Recalculate the clockbox position
216         // is it left-to-right or right-to-left layout ?
217         if (getStyle(document.body,'direction')!='rtl') {
218             cal_box.style.left = findPosX(cal_link) + 17 + 'px';
219         }
220         else {
221             // since style's width is in em, it'd be tough to calculate
222             // px value of it. let's use an estimated px for now
223             // TODO: IE returns wrong value for findPosX when in rtl mode
224             //       (it returns as it was left aligned), needs to be fixed.
225             cal_box.style.left = findPosX(cal_link) - 180 + 'px';
226         }
227         cal_box.style.top = findPosY(cal_link) - 75 + 'px';
228     
229         cal_box.style.display = 'block';
230         addEvent(window, 'click', function() { DateTimeShortcuts.dismissCalendar(num); return true; });
231     },
232     dismissCalendar: function(num) {
233         document.getElementById(DateTimeShortcuts.calendarDivName1+num).style.display = 'none';
234     },
235     drawPrev: function(num) {
236         DateTimeShortcuts.calendars[num].drawPreviousMonth();
237     },
238     drawNext: function(num) {
239         DateTimeShortcuts.calendars[num].drawNextMonth();
240     },
241     handleCalendarCallback: function(num) {
242         return "function(y, m, d) { DateTimeShortcuts.calendarInputs["+num+"].value = y+'-'+(m<10?'0':'')+m+'-'+(d<10?'0':'')+d; document.getElementById(DateTimeShortcuts.calendarDivName1+"+num+").style.display='none';}";
243     },
244     handleCalendarQuickLink: function(num, offset) {
245        var d = new Date();
246        d.setDate(d.getDate() + offset)
247        DateTimeShortcuts.calendarInputs[num].value = d.getISODate();
248        DateTimeShortcuts.dismissCalendar(num);
249     },
250     cancelEventPropagation: function(e) {
251         if (!e) e = window.event;
252         e.cancelBubble = true;
253         if (e.stopPropagation) e.stopPropagation();
254     }
255 }
256
257 addEvent(window, 'load', DateTimeShortcuts.init);