liquid_feedback_frontend

annotate static/gregor.js/gregor.js @ 50:ff1926efa6aa

Created french translation file
author jbe
date Wed Mar 31 17:50:32 2010 +0200 (2010-03-31)
parents 77d58efe99fd
children 77260f05fd4b
rev   line source
bsw@11 1 //
bsw@11 2 // Copyright (c) 2009 Public Software Group e. V., Berlin
bsw@11 3 //
bsw@11 4 // Permission is hereby granted, free of charge, to any person obtaining a
bsw@11 5 // copy of this software and associated documentation files (the
bsw@11 6 // "Software"), to deal in the Software without restriction, including
bsw@11 7 // without limitation the rights to use, copy, modify, merge, publish,
bsw@11 8 // distribute, sublicense, and/or sell copies of the Software, and to
bsw@11 9 // permit persons to whom the Software is furnished to do so, subject to
bsw@11 10 // the following conditions:
bsw@11 11 //
bsw@11 12 // The above copyright notice and this permission notice shall be included
bsw@11 13 // in all copies or substantial portions of the Software.
bsw@11 14 //
bsw@11 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
bsw@11 16 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
bsw@11 17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
bsw@11 18 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
bsw@11 19 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
bsw@11 20 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
bsw@11 21 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
bsw@11 22 //
bsw@11 23
bsw@11 24 //
bsw@11 25 // All date calculations are based on the gregorian calender, also for
bsw@11 26 // dates before 1582 (before the gegorian calendar was introduced).
bsw@11 27 // The supported range is from January 1st 0001 up to December 31st 9999.
bsw@11 28 //
bsw@11 29 // gregor_daycount({year: <year>, month: <month>, day: <day>}) returns
bsw@11 30 // the number of days between the given date and January 1st 0001 (greg.).
bsw@11 31 //
bsw@11 32 // gregor_completeDate({year: <year>, month: <month>, day: <day>}) returns
bsw@11 33 // a structure (an object) with the following properties:
bsw@11 34 // - daycount (days since January 1st 0001, see gregor_daycount)
bsw@11 35 // - year (with century)
bsw@11 36 // - month (from 1 to 12)
bsw@11 37 // - day (from 1 to 28, 29, 30 or 31)
bsw@11 38 // - iso_string (string with format YYYY-MM-DD)
bsw@11 39 // - us_weekday (from 0 for Sunday to 6 for Monday)
bsw@11 40 // - iso_weekday (from 0 for Monday to 6 for Sunday)
bsw@11 41 // - iso_weekyear (Year containing greater part of week st. w. Monday)
bsw@11 42 // - iso_week (from 1 to 52 or 53)
bsw@11 43 // - us_week (from 1 to 53 or 54)
bsw@11 44 //
bsw@11 45 // The structure (the object) passed as parameter to gregor_daycount or
bsw@11 46 // gregor_completeDate may describe a date in the following ways:
bsw@11 47 // - daycount
bsw@11 48 // - year, month, day
bsw@11 49 // - year, us_week, us_weekday
bsw@11 50 // - year, iso_week, iso_weekday
bsw@11 51 // - iso_weekyear, iso_week, iso_weekday
bsw@11 52 //
bsw@11 53 // gregor_sheet({...}) returns a calendar sheet as DOM object. The
bsw@11 54 // structure (the object) passed to the function as an argument is altered
bsw@11 55 // by the function and used to store state variables. Initially it can
bsw@11 56 // contain the following fields:
bsw@11 57 // - year (year to show, defaults to todays year)
bsw@11 58 // - month (month to show, defaults to todays month)
bsw@11 59 // - today (structure describing a day, e.g. year, month, day)
bsw@11 60 // - selected (structure describing a day, e.g. year, month, day)
bsw@11 61 // - navigation ("enabled", "disabled", "hidden", default "enabled")
bsw@11 62 // - week_mode ("iso" or "us", defaults to "iso")
bsw@11 63 // - week_numbers ("left", "right" or null, defaults to null)
bsw@11 64 // - month_names (e.g. ["January", "Feburary", ...])
bsw@11 65 // - weekday_names (e.g. ["Mon", "Tue", ...] or ["Sun", "Mon", ...])
bsw@11 66 // - day_callback (function to render a cell)
bsw@11 67 // - select_callback (function to be called, when a date was selected)
bsw@11 68 // - element (for internal use only)
bsw@11 69 // If "today" is undefined, it is automatically intitialized with the
bsw@11 70 // current clients date. If "selected" is undefined or null, no date is
bsw@11 71 // be initially selected. It is mandatory to provide month_names and
bsw@11 72 // weekday_names.
bsw@11 73 //
bsw@11 74 // gregor_addGui({...}) alters a referenced input field in a way that
bsw@11 75 // focussing on it causes a calendar being shown at its right side, where a
bsw@11 76 // date can be selected. The structure (the object) passed to this function
bsw@11 77 // is only evaluated once, and never modified. All options except "element"
bsw@11 78 // of the gregor_sheet({...}) function may be used as options to
bsw@11 79 // gregor_addGui({...}) as well. In addition an "element_id" must be
bsw@11 80 // provided as argument, containing the id of a text input field. The
bsw@11 81 // behaviour caused by the options "selected" and "select_callback" are
bsw@11 82 // slightly different: If "selected" === undefined, then the current value
bsw@11 83 // of the text field referenced by "element_id" will be parsed and used as
bsw@11 84 // date selection. If "selected" === null, then no date will be initially
bsw@11 85 // selected, and the text field will be cleared. The "select_callback"
bsw@11 86 // function is always called once with the pre-selected date (or with null,
bsw@11 87 // if no date is initially selected). Whenever the selected date is changed
bsw@11 88 // or unselected later, the callback function is called again with the new
bsw@11 89 // date (or with null, in case of deselection).
bsw@11 90 //
bsw@11 91 // EXAMPLE:
bsw@11 92 //
bsw@11 93 // <input type="text" id="test_field" name="test_field" value=""/>
bsw@11 94 // <script type="text/javascript">
bsw@11 95 // gregor_addGui({
bsw@11 96 // element_id: 'test_field',
bsw@11 97 // month_names: [
bsw@11 98 // "January", "February", "March", "April", "May", "June",
bsw@11 99 // "July", "August", "September", "October", "November", "December"
bsw@11 100 // ],
bsw@11 101 // weekday_names: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
bsw@11 102 // week_numbers: "left"
bsw@11 103 // });
bsw@11 104 // </script>
bsw@11 105 //
bsw@11 106
bsw@11 107
bsw@11 108
bsw@11 109
bsw@11 110 // Internal constants and helper functions for date calculation
bsw@11 111
bsw@11 112
bsw@11 113 gregor_c1 = 365; // days of a non-leap year
bsw@11 114 gregor_c4 = 4 * gregor_c1 + 1; // days of a full 4 year cycle
bsw@11 115 gregor_c100 = 25 * gregor_c4 - 1; // days of a full 100 year cycle
bsw@11 116 gregor_c400 = 4 * gregor_c100 + 1; // days of a full 400 year cycle
bsw@11 117
bsw@11 118 gregor_normalMonthOffsets = [
bsw@11 119 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
bsw@11 120 ];
bsw@11 121
bsw@11 122 function gregor_getMonthOffset(year, month) {
bsw@11 123 if (
bsw@11 124 (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) &&
bsw@11 125 month > 2
bsw@11 126 ) return gregor_normalMonthOffsets[month-1] + 1;
bsw@11 127 else return gregor_normalMonthOffsets[month-1];
bsw@11 128 }
bsw@11 129
bsw@11 130 function gregor_formatInteger(int, digits) {
bsw@11 131 var result = int.toFixed();
bsw@11 132 if (digits != null) {
bsw@11 133 while (result.length < digits) result = "0" + result;
bsw@11 134 }
bsw@11 135 return result;
bsw@11 136 }
bsw@11 137
bsw@11 138
bsw@11 139
bsw@11 140 // Calculate days since January 1st 0001 (Gegorian) for a given date
bsw@11 141
bsw@11 142
bsw@11 143 function gregor_daycount(obj) {
bsw@11 144 if (
bsw@11 145 obj.daycount >= 0 && obj.daycount <= 3652058 && obj.daycount % 1 == 0
bsw@11 146 ) {
bsw@11 147 return obj.daycount;
bsw@11 148 } else if (
bsw@11 149 obj.year >= 1 && obj.year <= 9999 && obj.year % 1 == 0 &&
bsw@11 150 obj.month >= 1 && obj.month <= 12 && obj.month % 1 == 0 &&
bsw@11 151 obj.day >= 0 && obj.day <= 31 && obj.day % 1 == 0
bsw@11 152 ) {
bsw@11 153 var n400 = Math.floor((obj.year-1) / 400);
bsw@11 154 var r400 = (obj.year-1) % 400;
bsw@11 155 var n100 = Math.floor(r400 / 100);
bsw@11 156 var r100 = r400 % 100;
bsw@11 157 var n4 = Math.floor(r100 / 4);
bsw@11 158 var n1 = r100 % 4;
bsw@11 159 return (
bsw@11 160 gregor_c400 * n400 +
bsw@11 161 gregor_c100 * n100 +
bsw@11 162 gregor_c4 * n4 +
bsw@11 163 gregor_c1 * n1 +
bsw@11 164 gregor_getMonthOffset(obj.year, obj.month) + (obj.day - 1)
bsw@11 165 );
bsw@11 166 } else if (
bsw@11 167 (
bsw@11 168 (
bsw@11 169 obj.year >= 1 && obj.year <= 9999 &&
bsw@11 170 obj.year % 1 == 0 && obj.iso_weekyear == null
bsw@11 171 ) || (
bsw@11 172 obj.iso_weekyear >= 1 && obj.iso_weekyear <= 9999 &&
bsw@11 173 obj.iso_weekyear % 1 == 0 && obj.year == null
bsw@11 174 )
bsw@11 175 ) &&
bsw@11 176 obj.iso_week >= 0 && obj.iso_week <= 53 && obj.iso_week % 1 == 0 &&
bsw@11 177 obj.iso_weekday >= 0 && obj.iso_weekday <= 6 &&
bsw@11 178 obj.iso_weekday % 1 == 0
bsw@11 179 ) {
bsw@11 180 var jan4th = gregor_daycount({
bsw@11 181 year: (obj.year != null) ? obj.year : obj.iso_weekyear,
bsw@11 182 month: 1,
bsw@11 183 day: 4
bsw@11 184 });
bsw@11 185 var monday0 = jan4th - (jan4th % 7) - 7; // monday of week 0
bsw@11 186 return monday0 + 7 * obj.iso_week + obj.iso_weekday;
bsw@11 187 } else if (
bsw@11 188 obj.year >= 1 && obj.year <= 9999 && obj.year % 1 == 0 &&
bsw@11 189 obj.us_week >= 0 && obj.us_week <= 54 && obj.us_week % 1 == 0 &&
bsw@11 190 obj.us_weekday >= 0 && obj.us_weekday <= 6 && obj.us_weekday % 1 == 0
bsw@11 191 ) {
bsw@11 192 var jan1st = gregor_daycount({
bsw@11 193 year: obj.year,
bsw@11 194 month: 1,
bsw@11 195 day: 1
bsw@11 196 });
bsw@11 197 var sunday0 = jan1st - ((jan1st+1) % 7) - 7; // sunday of week 0
bsw@11 198 return sunday0 + 7 * obj.us_week + obj.us_weekday;
bsw@11 199 }
bsw@11 200 }
bsw@11 201
bsw@11 202
bsw@11 203
bsw@11 204 // Calculate all calendar related numbers for a given date
bsw@11 205
bsw@11 206
bsw@11 207 function gregor_completeDate(obj) {
bsw@11 208 if (
bsw@11 209 obj.daycount >= 0 && obj.daycount <= 3652058 && obj.daycount % 1 == 0
bsw@11 210 ) {
bsw@11 211 var daycount = obj.daycount;
bsw@11 212 var n400 = Math.floor(daycount / gregor_c400);
bsw@11 213 var r400 = daycount % gregor_c400;
bsw@11 214 var n100 = Math.floor(r400 / gregor_c100);
bsw@11 215 var r100 = r400 % gregor_c100;
bsw@11 216 if (n100 == 4) { n100 = 3; r100 = gregor_c100; }
bsw@11 217 var n4 = Math.floor(r100 / gregor_c4);
bsw@11 218 var r4 = r100 % gregor_c4;
bsw@11 219 var n1 = Math.floor(r4 / gregor_c1);
bsw@11 220 var r1 = r4 % gregor_c1;
bsw@11 221 if (n1 == 4) { n1 = 3; r1 = gregor_c1; }
bsw@11 222 var year = 1 + 400 * n400 + 100 * n100 + 4 * n4 + n1;
bsw@11 223 var month = 1 + Math.floor(r1 / 31);
bsw@11 224 var monthOffset = gregor_getMonthOffset(year, month);
bsw@11 225 if (month < 12) {
bsw@11 226 var nextMonthOffset = gregor_getMonthOffset(year, month + 1);
bsw@11 227 if (r1 >= nextMonthOffset) {
bsw@11 228 month++;
bsw@11 229 monthOffset = nextMonthOffset;
bsw@11 230 }
bsw@11 231 }
bsw@11 232 var day = 1 + r1 - monthOffset;
bsw@11 233 var iso_string = ("" +
bsw@11 234 gregor_formatInteger(year, 4) + "-" +
bsw@11 235 gregor_formatInteger(month, 2) + "-" +
bsw@11 236 gregor_formatInteger(day, 2)
bsw@11 237 );
bsw@11 238 var us_weekday = (daycount+1) % 7;
bsw@11 239 var iso_weekday = daycount % 7;
bsw@11 240 var iso_weekyear = year;
bsw@11 241 if (
bsw@11 242 month == 1 && (
bsw@11 243 (day == 3 && iso_weekday == 6) ||
bsw@11 244 (day == 2 && iso_weekday >= 5) ||
bsw@11 245 (day == 1 && iso_weekday >= 4)
bsw@11 246 )
bsw@11 247 ) iso_weekyear--;
bsw@11 248 else if (
bsw@11 249 month == 12 && (
bsw@11 250 (day == 29 && iso_weekday == 0) ||
bsw@11 251 (day == 30 && iso_weekday <= 1) ||
bsw@11 252 (day == 31 && iso_weekday <= 2)
bsw@11 253 )
bsw@11 254 ) iso_weekyear++;
bsw@11 255 var jan4th = gregor_daycount({year: iso_weekyear, month: 1, day: 4});
bsw@11 256 var monday0 = jan4th - (jan4th % 7) - 7; // monday of week 0
bsw@11 257 var iso_week = Math.floor((daycount - monday0) / 7);
bsw@11 258 var jan1st = gregor_daycount({year: year, month: 1, day: 1});
bsw@11 259 var sunday0 = jan1st - ((jan1st+1) % 7) - 7; // sunday of week 0
bsw@11 260 var us_week = Math.floor((daycount - sunday0) / 7);
bsw@11 261 return {
bsw@11 262 daycount: daycount,
bsw@11 263 year: year,
bsw@11 264 month: month,
bsw@11 265 day: day,
bsw@11 266 iso_string: iso_string,
bsw@11 267 us_weekday: (daycount+1) % 7, // 0 = Sunday
bsw@11 268 iso_weekday: daycount % 7, // 0 = Monday
bsw@11 269 iso_weekyear: iso_weekyear,
bsw@11 270 iso_week: iso_week,
bsw@11 271 us_week: us_week
bsw@11 272 };
bsw@11 273 } else if (obj.daycount == null) {
bsw@11 274 var daycount = gregor_daycount(obj);
bsw@11 275 if (daycount != null) {
bsw@11 276 return gregor_completeDate({daycount: gregor_daycount(obj)});
bsw@11 277 }
bsw@11 278 }
bsw@11 279 }
bsw@11 280
bsw@11 281
bsw@11 282
bsw@11 283 // Test gregor_daycount and gregor_completeDate for consistency
bsw@11 284 // (Debugging only)
bsw@11 285
bsw@11 286
bsw@11 287 function gregor_test() {
bsw@11 288 for (i=650000; i<900000; i++) {
bsw@11 289 var obj = gregor_completeDate({daycount: i});
bsw@11 290 var j;
bsw@11 291 j = gregor_daycount({
bsw@11 292 year: obj.year,
bsw@11 293 month: obj.month,
bsw@11 294 day: obj.day
bsw@11 295 });
bsw@11 296 if (i != j) { alert("ERROR"); return; }
bsw@11 297 j = gregor_daycount({
bsw@11 298 iso_weekyear: obj.iso_weekyear,
bsw@11 299 iso_week: obj.iso_week,
bsw@11 300 iso_weekday: obj.iso_weekday
bsw@11 301 });
bsw@11 302 if (i != j) { alert("ERROR"); return; }
bsw@11 303 j = gregor_daycount({
bsw@11 304 year: obj.year,
bsw@11 305 iso_week:
bsw@11 306 (obj.iso_weekyear == obj.year + 1) ? 53 :
bsw@11 307 (obj.iso_weekyear == obj.year - 1) ? 0 :
bsw@11 308 obj.iso_week,
bsw@11 309 iso_weekday: obj.iso_weekday
bsw@11 310 });
bsw@11 311 if (i != j) { alert("ERROR"); return; }
bsw@11 312 j = gregor_daycount({
bsw@11 313 year: obj.year,
bsw@11 314 us_week: obj.us_week,
bsw@11 315 us_weekday: obj.us_weekday
bsw@11 316 });
bsw@11 317 if (i != j) { alert("ERROR"); return; }
bsw@11 318 }
bsw@11 319 alert("SUCCESS");
bsw@11 320 }
bsw@11 321
bsw@11 322
bsw@11 323
bsw@11 324 // Graphical calendar
bsw@11 325
bsw@11 326
bsw@11 327 gregor_iso_weekday_css = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"];
bsw@11 328
bsw@11 329 function gregor_sheet(args) {
bsw@11 330
bsw@11 331 // setting args.today and args.selected
bsw@11 332 if (args.today === undefined) {
bsw@11 333 var js_date = new Date();
bsw@11 334 args.today = gregor_completeDate({
bsw@11 335 year: js_date.getFullYear(),
bsw@11 336 month: js_date.getMonth() + 1,
bsw@11 337 day: js_date.getDate()
bsw@11 338 });
bsw@11 339 } else if (args.today != null) {
bsw@11 340 args.today = gregor_completeDate(args.today);
bsw@11 341 }
bsw@11 342 if (args.selected == "today") {
bsw@11 343 args.selected = args.today;
bsw@11 344 } else if (args.selected != null) {
bsw@11 345 args.selected = gregor_completeDate(args.selected);
bsw@11 346 }
bsw@11 347
bsw@11 348 // setting args.year and args.month
bsw@11 349 if (args.year == null) {
bsw@11 350 if (args.selected != null) args.year = args.selected.year;
bsw@11 351 else args.year = args.today.year;
bsw@11 352 }
bsw@11 353 if (args.month == null) {
bsw@11 354 if (args.selected != null) args.month = args.selected.month;
bsw@11 355 else args.month = args.today.month;
bsw@11 356 }
bsw@11 357
bsw@11 358 // setting first_day
bsw@11 359 var first_day = gregor_completeDate({
bsw@11 360 year: args.year,
bsw@11 361 month: args.month,
bsw@11 362 day: 1
bsw@11 363 });
bsw@11 364 if (first_day == null) return;
bsw@11 365
bsw@11 366 // checking args.navigation, args.week_mode and args.week_numbers
bsw@11 367 if (args.navigation == null) args.navigation = "enabled";
bsw@11 368 else if (
bsw@11 369 args.navigation != "enabled" &&
bsw@11 370 args.navigation != "disabled" &&
bsw@11 371 args.navigation != "hidden"
bsw@11 372 ) return;
bsw@11 373 if (args.week_mode == null) args.week_mode = "iso";
bsw@11 374 else if (args.week_mode != "iso" && args.week_mode != "us") return;
bsw@11 375 if (
bsw@11 376 args.week_numbers != null &&
bsw@11 377 args.week_numbers != "left" &&
bsw@11 378 args.week_numbers != "right"
bsw@11 379 ) return;
bsw@11 380
bsw@11 381 // checking args.month.names and args.weekday_names
bsw@11 382 if (args.month_names.length != 12) return;
bsw@11 383 if (args.weekday_names.length != 7) return;
bsw@11 384
bsw@11 385 // calculating number of days in month
bsw@11 386 var count;
bsw@11 387 if (args.year < 9999 || args.month < 12) {
bsw@11 388 count = gregor_daycount({
bsw@11 389 year: (args.month == 12) ? (args.year + 1) : args.year,
bsw@11 390 month: (args.month == 12) ? 1 : (args.month + 1),
bsw@11 391 day: 1
bsw@11 392 }) - first_day.daycount;
bsw@11 393 } else {
bsw@11 394 // workaround for year 9999
bsw@11 395 count = 31;
bsw@11 396 }
bsw@11 397
bsw@11 398 // locale variables for UI construction
bsw@11 399 var table, row, cell, element;
bsw@11 400
bsw@11 401 // take table element from args.element,
bsw@11 402 // if neccessary create and store it
bsw@11 403 if (args.element == null) {
bsw@11 404 table = document.createElement("table");
bsw@11 405 args.element = table;
bsw@11 406 } else {
bsw@11 407 table = args.element;
bsw@11 408 while (table.firstChild) table.removeChild(table.firstChild);
bsw@11 409 }
bsw@11 410
bsw@11 411 // set CSS class of table according to args.week_numbers
bsw@11 412 if (args.week_numbers == "left") {
bsw@11 413 table.className = "gregor_sheet gregor_weeks_left";
bsw@11 414 } else if (args.week_numbers == "right") {
bsw@11 415 table.className = "gregor_sheet gregor_weeks_right";
bsw@11 416 } else {
bsw@11 417 table.className = "gregor_sheet gregor_weeks_none";
bsw@11 418 }
bsw@11 419
bsw@11 420 // begin of table head
bsw@11 421 var thead = document.createElement("thead");
bsw@11 422
bsw@11 423 // navigation
bsw@11 424 if (args.navigation != "hidden") {
bsw@11 425
bsw@11 426 // UI head row containing the year
bsw@11 427 row = document.createElement("tr");
bsw@11 428 row.className = "gregor_year_row";
bsw@11 429 cell = document.createElement("th");
bsw@11 430 cell.className = "gregor_year";
bsw@11 431 cell.colSpan = args.week_numbers ? 8 : 7;
bsw@11 432 if (args.navigation == "enabled") {
bsw@11 433 element = document.createElement("a");
bsw@11 434 element.className = "gregor_turn gregor_turn_left";
bsw@11 435 element.style.cssFloat = "left";
bsw@11 436 element.style.styleFloat = "left";
bsw@11 437 element.href = "#";
bsw@11 438 element.onclick = function() {
bsw@11 439 if (args.year > 1) args.year--;
bsw@11 440 gregor_sheet(args);
bsw@11 441 return false;
bsw@11 442 }
bsw@11 443 element.ondblclick = element.onclick;
bsw@11 444 element.appendChild(document.createTextNode("<<"));
bsw@11 445 cell.appendChild(element);
bsw@11 446 element = document.createElement("a");
bsw@11 447 element.className = "gregor_turn gregor_turn_right";
bsw@11 448 element.style.cssFloat = "right";
bsw@11 449 element.style.styleFloat = "right";
bsw@11 450 element.href = "#";
bsw@11 451 element.onclick = function() {
bsw@11 452 if (args.year < 9999) args.year++;
bsw@11 453 gregor_sheet(args);
bsw@11 454 return false;
bsw@11 455 }
bsw@11 456 element.ondblclick = element.onclick;
bsw@11 457 element.appendChild(document.createTextNode(">>"));
bsw@11 458 cell.appendChild(element);
bsw@11 459 }
bsw@11 460 cell.appendChild(document.createTextNode(first_day.year));
bsw@11 461 row.appendChild(cell);
bsw@11 462 thead.appendChild(row);
bsw@11 463
bsw@11 464 // UI head row containing the month
bsw@11 465 row = document.createElement("tr");
bsw@11 466 row.className = "gregor_month_row";
bsw@11 467 cell = document.createElement("th");
bsw@11 468 cell.className = "gregor_month";
bsw@11 469 cell.colSpan = args.week_numbers ? 8 : 7;
bsw@11 470 if (args.navigation == "enabled") {
bsw@11 471 element = document.createElement("a");
bsw@11 472 element.className = "gregor_turn gregor_turn_left";
bsw@11 473 element.style.cssFloat = "left";
bsw@11 474 element.style.styleFloat = "left";
bsw@11 475 element.href = "#";
bsw@11 476 element.onclick = function() {
bsw@11 477 if (args.year > 1 || args.month > 1) {
bsw@11 478 args.month--;
bsw@11 479 if (args.month < 1) {
bsw@11 480 args.month = 12;
bsw@11 481 args.year--;
bsw@11 482 }
bsw@11 483 }
bsw@11 484 gregor_sheet(args);
bsw@11 485 return false;
bsw@11 486 }
bsw@11 487 element.ondblclick = element.onclick;
bsw@11 488 element.appendChild(document.createTextNode("<<"));
bsw@11 489 cell.appendChild(element);
bsw@11 490 element = document.createElement("a");
bsw@11 491 element.className = "gregor_turn gregor_turn_right";
bsw@11 492 element.style.cssFloat = "right";
bsw@11 493 element.style.styleFloat = "right";
bsw@11 494 element.href = "#";
bsw@11 495 element.onclick = function() {
bsw@11 496 if (args.year < 9999 || args.month < 12) {
bsw@11 497 args.month++;
bsw@11 498 if (args.month > 12) {
bsw@11 499 args.month = 1;
bsw@11 500 args.year++;
bsw@11 501 }
bsw@11 502 }
bsw@11 503 gregor_sheet(args);
bsw@11 504 return false;
bsw@11 505 }
bsw@11 506 element.ondblclick = element.onclick;
bsw@11 507 element.appendChild(document.createTextNode(">>"));
bsw@11 508 cell.appendChild(element);
bsw@11 509 }
bsw@11 510 cell.appendChild(document.createTextNode(
bsw@11 511 args.month_names[first_day.month-1]
bsw@11 512 ));
bsw@11 513 row.appendChild(cell);
bsw@11 514 thead.appendChild(row);
bsw@11 515
bsw@11 516 // end of navigation
bsw@11 517 }
bsw@11 518
bsw@11 519 // UI weekday row
bsw@11 520 row = document.createElement("tr");
bsw@11 521 row.className = "gregor_weekday_row";
bsw@11 522 if (args.week_numbers == "left") {
bsw@11 523 cell = document.createElement("th");
bsw@11 524 cell.className = "gregor_corner";
bsw@11 525 row.appendChild(cell);
bsw@11 526 }
bsw@11 527 for (var i=0; i<7; i++) {
bsw@11 528 cell = document.createElement("th");
bsw@11 529 cell.className = (
bsw@11 530 "gregor_weekday gregor_" +
bsw@11 531 gregor_iso_weekday_css[(args.week_mode == "us") ? ((i+6)%7) : i]
bsw@11 532 );
bsw@11 533 cell.appendChild(document.createTextNode(args.weekday_names[i]));
bsw@11 534 row.appendChild(cell);
bsw@11 535 }
bsw@11 536 if (args.week_numbers == "right") {
bsw@11 537 cell = document.createElement("th");
bsw@11 538 cell.className = "gregor_corner";
bsw@11 539 row.appendChild(cell);
bsw@11 540 }
bsw@11 541 thead.appendChild(row);
bsw@11 542
bsw@11 543 // end of table head and begin of table body
bsw@11 544 table.appendChild(thead);
bsw@11 545 var tbody = document.createElement("tbody");
bsw@11 546
bsw@11 547 // definition of insert_week function
bsw@11 548 var week = (
bsw@11 549 (args.week_mode == "us") ? first_day.us_week : first_day.iso_week
bsw@11 550 );
bsw@11 551 insert_week = function() {
bsw@11 552 cell = document.createElement("th");
bsw@11 553 cell.className = "gregor_week";
bsw@11 554 cell.appendChild(document.createTextNode(
bsw@11 555 (week < 10) ? ("0" + week) : week)
bsw@11 556 );
bsw@11 557 week++;
bsw@11 558 if (
bsw@11 559 args.week_mode == "iso" && (
bsw@11 560 (
bsw@11 561 args.month == 1 && week > 52
bsw@11 562 ) || (
bsw@11 563 args.month == 12 && week == 53 && (
bsw@11 564 first_day.iso_weekday == 0 ||
bsw@11 565 first_day.iso_weekday == 5 ||
bsw@11 566 first_day.iso_weekday == 6
bsw@11 567 )
bsw@11 568 )
bsw@11 569 )
bsw@11 570 ) week = 1;
bsw@11 571 row.appendChild(cell);
bsw@11 572 }
bsw@11 573
bsw@11 574 // output data fields
bsw@11 575 row = document.createElement("tr");
bsw@11 576 if (args.week_numbers == "left") insert_week();
bsw@11 577 var filler_count = (
bsw@11 578 (args.week_mode == "us") ? first_day.us_weekday : first_day.iso_weekday
bsw@11 579 );
bsw@11 580 for (var i=0; i<filler_count; i++) {
bsw@11 581 cell = document.createElement("td");
bsw@11 582 cell.className = "gregor_empty";
bsw@11 583 row.appendChild(cell);
bsw@11 584 }
bsw@11 585 for (var i=0; i<count; i++) {
bsw@11 586 var date = gregor_completeDate({daycount: first_day.daycount + i});
bsw@11 587 if (row == null) {
bsw@11 588 row = document.createElement("tr");
bsw@11 589 if (args.week_numbers == "left") insert_week();
bsw@11 590 }
bsw@11 591 cell = document.createElement("td");
bsw@11 592 var cssClass = (
bsw@11 593 "gregor_day gregor_" + gregor_iso_weekday_css[date.iso_weekday]
bsw@11 594 );
bsw@11 595 if (args.today != null && date.daycount == args.today.daycount) {
bsw@11 596 cssClass += " gregor_today";
bsw@11 597 }
bsw@11 598 if (args.selected != null && date.daycount == args.selected.daycount) {
bsw@11 599 cssClass += " gregor_selected";
bsw@11 600 }
bsw@11 601 cell.className = cssClass;
bsw@11 602 if (args.day_callback) {
bsw@11 603 args.day_callback(cell, date);
bsw@11 604 } else {
bsw@11 605 element = document.createElement("a");
bsw@11 606 element.href = "#";
bsw@11 607 var generate_onclick = function(date) {
bsw@11 608 return function() {
bsw@11 609 args.selected = date;
bsw@11 610 gregor_sheet(args);
bsw@11 611 if (args.select_callback != null) {
bsw@11 612 args.select_callback(date);
bsw@11 613 }
bsw@11 614 return false;
bsw@11 615 }
bsw@11 616 }
bsw@11 617 element.onclick = generate_onclick(date);
bsw@11 618 element.ondblclick = element.onclick;
bsw@11 619 element.appendChild(document.createTextNode(first_day.day + i));
bsw@11 620 cell.appendChild(element);
bsw@11 621 }
bsw@11 622 row.appendChild(cell);
bsw@11 623 if (row.childNodes.length == ((args.week_numbers == "left") ? 8 : 7)) {
bsw@11 624 if (args.week_numbers == "right") insert_week();
bsw@11 625 tbody.appendChild(row);
bsw@11 626 row = null;
bsw@11 627 }
bsw@11 628 }
bsw@11 629 if (row != null) {
bsw@11 630 while (row.childNodes.length < ((args.week_numbers == "left") ? 8 : 7)) {
bsw@11 631 cell = document.createElement("td");
bsw@11 632 cell.className = "gregor_empty";
bsw@11 633 row.appendChild(cell);
bsw@11 634 }
bsw@11 635 if (args.week_numbers == "right") insert_week();
bsw@11 636 tbody.appendChild(row);
bsw@11 637 }
bsw@11 638
bsw@11 639 // end of table body
bsw@11 640 table.appendChild(tbody);
bsw@11 641
bsw@11 642 // return table
bsw@11 643 return table;
bsw@11 644 }
bsw@11 645
bsw@11 646
bsw@11 647
bsw@11 648 // Rich form field support
bsw@11 649
bsw@11 650
bsw@11 651 function gregor_getAbsoluteLeft(elem) {
bsw@11 652 var result = 0;
bsw@11 653 while (elem && elem.style.position != "static") {
bsw@11 654 result += elem.offsetLeft;
bsw@11 655 elem = elem.offsetParent;
bsw@11 656 }
bsw@11 657 return result;
bsw@11 658 }
bsw@11 659
bsw@11 660 function gregor_getAbsoluteTop(elem) {
bsw@11 661 var result = 0;
bsw@11 662 while (elem && elem.style.position != "static") {
bsw@11 663 result += elem.offsetTop;
bsw@11 664 elem = elem.offsetParent;
bsw@11 665 }
bsw@11 666 return result;
bsw@11 667 }
bsw@11 668
bsw@11 669 function gregor_formatDate(format, date) {
bsw@11 670 if (date == null) return "";
bsw@11 671 var result = format;
bsw@11 672 result = result.replace(/Y+/, function(s) {
bsw@11 673 if (s.length == 2) return gregor_formatInteger(date.year % 100, 2);
bsw@11 674 else return gregor_formatInteger(date.year, s.length);
bsw@11 675 });
bsw@11 676 result = result.replace(/M+/, function(s) {
bsw@11 677 return gregor_formatInteger(date.month, s.length);
bsw@11 678 });
bsw@11 679 result = result.replace(/D+/, function(s) {
bsw@11 680 return gregor_formatInteger(date.day, s.length);
bsw@11 681 });
bsw@11 682 return result;
bsw@11 683 }
bsw@11 684
bsw@11 685 function gregor_map2digitYear(y2, maxYear) {
bsw@11 686 var guess = Math.floor(maxYear / 100) * 100 + y2;
bsw@11 687 if (guess <= maxYear) return guess;
bsw@11 688 else return guess - 100;
bsw@11 689 }
bsw@11 690
bsw@11 691 function gregor_parseDate(format, string, terminated, maxYear) {
bsw@11 692 var numericParts, formatParts;
bsw@11 693 numericParts = string.match(/^\s*([0-9]{4})-([0-9]{2})-([0-9]{2})\s*$/);
bsw@11 694 if (numericParts != null) {
bsw@11 695 return gregor_completeDate({
bsw@11 696 year: numericParts[1],
bsw@11 697 month: numericParts[2],
bsw@11 698 day: numericParts[3]
bsw@11 699 });
bsw@11 700 }
bsw@11 701 numericParts = string.match(/[0-9]+/g);
bsw@11 702 if (numericParts == null) return null;
bsw@11 703 formatParts = format.match(/[YMD]+/g);
bsw@11 704 if (numericParts.length != formatParts.length) return null;
bsw@11 705 if (
bsw@11 706 !terminated && (
bsw@11 707 numericParts[numericParts.length-1].length <
bsw@11 708 formatParts[formatParts.length-1].length
bsw@11 709 )
bsw@11 710 ) return null;
bsw@11 711 var year, month, day;
bsw@11 712 for (var i=0; i<numericParts.length; i++) {
bsw@11 713 var numericPart = numericParts[i];
bsw@11 714 var formatPart = formatParts[i];
bsw@11 715 if (formatPart.match(/^Y+$/)) {
bsw@11 716 if (numericPart.length == 2 && maxYear != null) {
bsw@11 717 year = gregor_map2digitYear(parseInt(numericPart, 10), maxYear);
bsw@11 718 } else if (numericPart.length > 2) {
bsw@11 719 year = parseInt(numericPart, 10);
bsw@11 720 }
bsw@11 721 } else if (formatPart.match(/^M+$/)) {
bsw@11 722 month = parseInt(numericPart, 10);
bsw@11 723 } else if (formatPart.match(/^D+$/)) {
bsw@11 724 day = parseInt(numericPart, 10);
bsw@11 725 } else {
bsw@11 726 //alert("Not implemented.");
bsw@11 727 return null;
bsw@11 728 }
bsw@11 729 }
bsw@11 730 return gregor_completeDate({year: year, month: month, day: day});
bsw@11 731 }
bsw@11 732
bsw@11 733 function gregor_addGui(args) {
bsw@11 734
bsw@11 735 // copy argument structure
bsw@11 736 var state = {};
bsw@11 737 for (key in args) state[key] = args[key];
bsw@11 738
bsw@11 739 // unset state.element, which should never be set anyway
bsw@11 740 state.element = null;
bsw@11 741
bsw@11 742 // save original values of "year" and "month" options
bsw@11 743 var original_year = state.year;
bsw@11 744 var original_month = state.month;
bsw@11 745
bsw@11 746 // get text field element
bsw@11 747 var element = document.getElementById(state.element_id);
bsw@11 748 state.element_id = null;
bsw@11 749
bsw@11 750 // setup state.today, state.selected and state.format options
bsw@11 751 if (state.today === undefined) {
bsw@11 752 var js_date = new Date();
bsw@11 753 state.today = gregor_completeDate({
bsw@11 754 year: js_date.getFullYear(),
bsw@11 755 month: js_date.getMonth() + 1,
bsw@11 756 day: js_date.getDate()
bsw@11 757 });
bsw@11 758 } else if (state.today != null) {
bsw@11 759 state.today = gregor_completeDate(args.today);
bsw@11 760 }
bsw@11 761 if (state.selected == "today") {
bsw@11 762 state.selected = state.today;
bsw@11 763 } else if (args.selected != null) {
bsw@11 764 state.selected = gregor_completeDate(state.selected);
bsw@11 765 }
bsw@11 766 if (state.format == null) state.format = "YYYY-MM-DD";
bsw@11 767
bsw@11 768 // using state.future to calculate maxYear (for 2 digit year conversions)
bsw@11 769 var maxYear = (state.today == null) ? null : (
bsw@11 770 state.today.year +
bsw@11 771 ((state.future == null) ? 12 : state.future)
bsw@11 772 );
bsw@11 773
bsw@11 774 // hook into state.select_callback
bsw@11 775 var select_callback = state.select_callback;
bsw@11 776 state.select_callback = function(date) {
bsw@11 777 element.value = gregor_formatDate(state.format, date);
bsw@11 778 if (select_callback) select_callback(date);
bsw@11 779 };
bsw@11 780
bsw@11 781 // function to parse text field and update calendar sheet state
bsw@11 782 var updateSheet = function(terminated) {
bsw@11 783 var date = gregor_parseDate(
bsw@11 784 state.format, element.value, terminated, maxYear
bsw@11 785 );
bsw@11 786 if (date) {
bsw@11 787 state.year = null;
bsw@11 788 state.month = null;
bsw@11 789 }
bsw@11 790 state.selected = date;
bsw@11 791 gregor_sheet(state);
bsw@11 792 };
bsw@11 793
bsw@11 794 // Initial synchronization
bsw@11 795 if (state.selected === undefined) updateSheet(true);
bsw@11 796 element.value = gregor_formatDate(state.format, state.selected);
bsw@11 797 if (select_callback) select_callback(state.selected);
bsw@11 798
bsw@11 799 // variables storing popup status
bsw@11 800 var visible = false;
bsw@11 801 var focus = false;
bsw@11 802 var protection = false;
bsw@11 803
bsw@11 804 // event handlers for text field
bsw@11 805 element.onfocus = function() {
bsw@11 806 focus = true;
bsw@11 807 if (!visible) {
bsw@11 808 state.year = original_year;
bsw@11 809 state.month = original_month;
bsw@11 810 gregor_sheet(state);
bsw@11 811 state.element.style.position = "absolute";
bsw@11 812 state.element.style.top = gregor_getAbsoluteTop(element) + element.offsetHeight;
bsw@11 813 state.element.style.left = gregor_getAbsoluteLeft(element);
bsw@11 814 state.element.onmousedown = function() {
bsw@11 815 protection = true;
bsw@11 816 };
bsw@11 817 state.element.onmouseup = function() {
bsw@11 818 protection = false;
bsw@11 819 element.focus();
bsw@11 820 };
bsw@11 821 state.element.onmouseout = state.element.onmouseup;
bsw@11 822 element.parentNode.appendChild(state.element);
bsw@11 823 visible = true;
bsw@11 824 }
bsw@11 825 };
bsw@11 826 element.onblur = function() {
bsw@11 827 focus = false;
bsw@11 828 window.setTimeout(function() {
bsw@11 829 if (visible && !focus && !protection) {
bsw@11 830 updateSheet(true);
bsw@11 831 element.value = gregor_formatDate(state.format, state.selected);
bsw@11 832 if (select_callback) select_callback(state.selected);
bsw@11 833 state.element.parentNode.removeChild(state.element);
bsw@11 834 visible = false;
bsw@11 835 protection = false;
bsw@11 836 }
bsw@11 837 }, 1);
bsw@11 838 };
bsw@11 839 element.onkeyup = function() {
bsw@11 840 updateSheet(false);
bsw@11 841 if (select_callback) select_callback(state.selected);
bsw@11 842 };
bsw@11 843
bsw@11 844 }
bsw@11 845

Impressum / About Us