calendar.js 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941
  1. /*
  2. * Copyright Mihai Bazon, 2002-2005 | www.bazon.net/mishoo
  3. * -----------------------------------------------------------
  4. *
  5. * The DHTML Calendar, version 1.0 "It is happening again"
  6. *
  7. * Details and latest version at: www.dynarch.com/projects/calendar
  8. *
  9. * This script is developed by Dynarch.com. Visit us at www.dynarch.com.
  10. *
  11. * This script is distributed under the GNU Lesser General Public License. Read
  12. * the entire license text here: http://www.gnu.org/licenses/lgpl.html
  13. */
  14. // $Id: calendar.js,v 1.1 2008/01/28 03:13:41 szg Exp $
  15. /** The Calendar object constructor. */
  16. function showCalendar(el, format, showsTime, clickObj) {
  17. if (_dynarch_popupCalendar != null) {
  18. _dynarch_popupCalendar.hide(); // so we hide it first.
  19. } else {
  20. var cal = new Calendar(1, null, selected, closeHandler);
  21. // cal.weekNumbers = false;
  22. if (typeof showsTime == "string") {
  23. cal.showsTime = true;
  24. cal.time24 = (showsTime == "24");
  25. }
  26. cal.showsOtherMonths = true;
  27. _dynarch_popupCalendar = cal; // remember it in the global var
  28. cal.setRange(1940, 2070); // min/max year allowed.
  29. cal.create();
  30. }
  31. _dynarch_popupCalendar.setDateFormat(format); // set the specified date
  32. // format
  33. _dynarch_popupCalendar.parseDate(el.value); // try to parse the text in
  34. // field
  35. _dynarch_popupCalendar.sel = el; // inform it what input field we use
  36. _dynarch_popupCalendar.showAtElement(clickObj, "Br"); // show the calendar
  37. return false;
  38. }
  39. // This function gets called when the end-user clicks on some date.
  40. function selected(cal, date) {
  41. cal.sel.value = date; // just update the date in the input field.
  42. if (cal.dateClicked)
  43. cal.callCloseHandler();
  44. }
  45. function closeHandler(cal) {
  46. cal.hide(); // hide the calendar
  47. _dynarch_popupCalendar = null;
  48. }
  49. Calendar = function(firstDayOfWeek, dateStr, onSelected, onClose) {
  50. // member variables
  51. this.activeDiv = null;
  52. this.currentDateEl = null;
  53. this.getDateStatus = null;
  54. this.getDateToolTip = null;
  55. this.getDateText = null;
  56. this.timeout = null;
  57. this.onSelected = onSelected || null;
  58. this.onClose = onClose || null;
  59. this.dragging = false;
  60. this.hidden = false;
  61. this.minYear = 1970;
  62. this.maxYear = 2050;
  63. this.dateFormat = Calendar._TT["DEF_DATE_FORMAT"];
  64. this.ttDateFormat = Calendar._TT["TT_DATE_FORMAT"];
  65. this.isPopup = true;
  66. this.weekNumbers = true;
  67. this.firstDayOfWeek = typeof firstDayOfWeek == "number"
  68. ? firstDayOfWeek
  69. : Calendar._FD; // 0 for Sunday, 1 for Monday, etc.
  70. this.showsOtherMonths = false;
  71. this.dateStr = dateStr;
  72. this.ar_days = null;
  73. this.showsTime = false;
  74. this.time24 = true;
  75. this.yearStep = 2;
  76. this.hiliteToday = true;
  77. this.multiple = null;
  78. // HTML elements
  79. this.table = null;
  80. this.element = null;
  81. this.tbody = null;
  82. this.firstdayname = null;
  83. // Combo boxes
  84. this.monthsCombo = null;
  85. this.yearsCombo = null;
  86. this.hilitedMonth = null;
  87. this.activeMonth = null;
  88. this.hilitedYear = null;
  89. this.activeYear = null;
  90. // Information
  91. this.dateClicked = false;
  92. // one-time initializations
  93. if (typeof Calendar._SDN == "undefined") {
  94. // table of short day names
  95. if (typeof Calendar._SDN_len == "undefined")
  96. Calendar._SDN_len = 3;
  97. var ar = new Array();
  98. for (var i = 8; i > 0;) {
  99. ar[--i] = Calendar._DN[i].substr(0, Calendar._SDN_len);
  100. }
  101. Calendar._SDN = ar;
  102. // table of short month names
  103. if (typeof Calendar._SMN_len == "undefined")
  104. Calendar._SMN_len = 3;
  105. ar = new Array();
  106. for (var i = 12; i > 0;) {
  107. ar[--i] = Calendar._MN[i].substr(0, Calendar._SMN_len);
  108. }
  109. Calendar._SMN = ar;
  110. }
  111. };
  112. // ** constants
  113. // / "static", needed for event handlers.
  114. Calendar._C = null;
  115. // / detect a special case of "web browser"
  116. Calendar.is_ie = (/msie/i.test(navigator.userAgent) && !/opera/i
  117. .test(navigator.userAgent));
  118. Calendar.is_ie5 = (Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent));
  119. // / detect Opera browser
  120. Calendar.is_opera = /opera/i.test(navigator.userAgent);
  121. // / detect KHTML-based browsers
  122. Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent);
  123. // BEGIN: UTILITY FUNCTIONS; beware that these might be moved into a separate
  124. // library, at some point.
  125. Calendar.getAbsolutePos = function(el) {
  126. var SL = 0, ST = 0;
  127. var is_div = /^div$/i.test(el.tagName);
  128. if (is_div && el.scrollLeft)
  129. SL = el.scrollLeft;
  130. if (is_div && el.scrollTop)
  131. ST = el.scrollTop;
  132. var r = {
  133. x : el.offsetLeft - SL,
  134. y : el.offsetTop - ST
  135. };
  136. if (el.offsetParent) {
  137. var tmp = this.getAbsolutePos(el.offsetParent);
  138. r.x += tmp.x;
  139. r.y += tmp.y;
  140. }
  141. return r;
  142. };
  143. Calendar.isRelated = function(el, evt) {
  144. var related = evt.relatedTarget;
  145. if (!related) {
  146. var type = evt.type;
  147. if (type == "mouseover") {
  148. related = evt.fromElement;
  149. } else if (type == "mouseout") {
  150. related = evt.toElement;
  151. }
  152. }
  153. while (related) {
  154. if (related == el) {
  155. return true;
  156. }
  157. related = related.parentNode;
  158. }
  159. return false;
  160. };
  161. Calendar.removeClass = function(el, className) {
  162. if (!(el && el.className)) {
  163. return;
  164. }
  165. var cls = el.className.split(" ");
  166. var ar = new Array();
  167. for (var i = cls.length; i > 0;) {
  168. if (cls[--i] != className) {
  169. ar[ar.length] = cls[i];
  170. }
  171. }
  172. el.className = ar.join(" ");
  173. };
  174. Calendar.addClass = function(el, className) {
  175. Calendar.removeClass(el, className);
  176. el.className += " " + className;
  177. };
  178. // FIXME: the following 2 functions totally suck, are useless and should be
  179. // replaced immediately.
  180. Calendar.getElement = function(ev) {
  181. var f = Calendar.is_ie ? window.event.srcElement : ev.currentTarget;
  182. while (f.nodeType != 1 || /^div$/i.test(f.tagName))
  183. f = f.parentNode;
  184. return f;
  185. };
  186. Calendar.getTargetElement = function(ev) {
  187. var f = Calendar.is_ie ? window.event.srcElement : ev.target;
  188. while (f.nodeType != 1)
  189. f = f.parentNode;
  190. return f;
  191. };
  192. Calendar.stopEvent = function(ev) {
  193. ev || (ev = window.event);
  194. if (Calendar.is_ie) {
  195. ev.cancelBubble = true;
  196. ev.returnValue = false;
  197. } else {
  198. ev.preventDefault();
  199. ev.stopPropagation();
  200. }
  201. return false;
  202. };
  203. Calendar.addEvent = function(el, evname, func) {
  204. if (el.attachEvent) { // IE
  205. el.attachEvent("on" + evname, func);
  206. } else if (el.addEventListener) { // Gecko / W3C
  207. el.addEventListener(evname, func, true);
  208. } else {
  209. el["on" + evname] = func;
  210. }
  211. };
  212. Calendar.removeEvent = function(el, evname, func) {
  213. if (el.detachEvent) { // IE
  214. el.detachEvent("on" + evname, func);
  215. } else if (el.removeEventListener) { // Gecko / W3C
  216. el.removeEventListener(evname, func, true);
  217. } else {
  218. el["on" + evname] = null;
  219. }
  220. };
  221. Calendar.createElement = function(type, parent) {
  222. var el = null;
  223. if (document.createElementNS) {
  224. // use the XHTML namespace; IE won't normally get here unless
  225. // _they_ "fix" the DOM2 implementation.
  226. el = document.createElementNS("http://www.w3.org/1999/xhtml", type);
  227. } else {
  228. el = document.createElement(type);
  229. }
  230. if (typeof parent != "undefined") {
  231. parent.appendChild(el);
  232. }
  233. return el;
  234. };
  235. // END: UTILITY FUNCTIONS
  236. // BEGIN: CALENDAR STATIC FUNCTIONS
  237. /** Internal -- adds a set of events to make some element behave like a button. */
  238. Calendar._add_evs = function(el) {
  239. with (Calendar) {
  240. addEvent(el, "mouseover", dayMouseOver);
  241. addEvent(el, "mousedown", dayMouseDown);
  242. addEvent(el, "mouseout", dayMouseOut);
  243. if (is_ie) {
  244. addEvent(el, "dblclick", dayMouseDblClick);
  245. el.setAttribute("unselectable", true);
  246. }
  247. }
  248. };
  249. Calendar.findMonth = function(el) {
  250. if (typeof el.month != "undefined") {
  251. return el;
  252. } else if (typeof el.parentNode.month != "undefined") {
  253. return el.parentNode;
  254. }
  255. return null;
  256. };
  257. Calendar.findYear = function(el) {
  258. if (typeof el.year != "undefined") {
  259. return el;
  260. } else if (typeof el.parentNode.year != "undefined") {
  261. return el.parentNode;
  262. }
  263. return null;
  264. };
  265. Calendar.showMonthsCombo = function() {
  266. var cal = Calendar._C;
  267. if (!cal) {
  268. return false;
  269. }
  270. var cal = cal;
  271. var cd = cal.activeDiv;
  272. var mc = cal.monthsCombo;
  273. if (cal.hilitedMonth) {
  274. Calendar.removeClass(cal.hilitedMonth, "hilite");
  275. }
  276. if (cal.activeMonth) {
  277. Calendar.removeClass(cal.activeMonth, "active");
  278. }
  279. var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()];
  280. Calendar.addClass(mon, "active");
  281. cal.activeMonth = mon;
  282. var s = mc.style;
  283. s.display = "block";
  284. if (cd.navtype < 0)
  285. s.left = cd.offsetLeft + "px";
  286. else {
  287. var mcw = mc.offsetWidth;
  288. if (typeof mcw == "undefined")
  289. // Konqueror brain-dead techniques
  290. mcw = 50;
  291. s.left = (cd.offsetLeft + cd.offsetWidth - mcw) + "px";
  292. }
  293. s.top = (cd.offsetTop + cd.offsetHeight) + "px";
  294. };
  295. Calendar.showYearsCombo = function(fwd) {
  296. var cal = Calendar._C;
  297. if (!cal) {
  298. return false;
  299. }
  300. var cal = cal;
  301. var cd = cal.activeDiv;
  302. var yc = cal.yearsCombo;
  303. if (cal.hilitedYear) {
  304. Calendar.removeClass(cal.hilitedYear, "hilite");
  305. }
  306. if (cal.activeYear) {
  307. Calendar.removeClass(cal.activeYear, "active");
  308. }
  309. cal.activeYear = null;
  310. var Y = cal.date.getFullYear() + (fwd ? 1 : -1);
  311. var yr = yc.firstChild;
  312. var show = false;
  313. for (var i = 12; i > 0; --i) {
  314. if (Y >= cal.minYear && Y <= cal.maxYear) {
  315. yr.innerHTML = Y;
  316. yr.year = Y;
  317. yr.style.display = "block";
  318. show = true;
  319. } else {
  320. yr.style.display = "none";
  321. }
  322. yr = yr.nextSibling;
  323. Y += fwd ? cal.yearStep : -cal.yearStep;
  324. }
  325. if (show) {
  326. var s = yc.style;
  327. s.display = "block";
  328. if (cd.navtype < 0)
  329. s.left = cd.offsetLeft + "px";
  330. else {
  331. var ycw = yc.offsetWidth;
  332. if (typeof ycw == "undefined")
  333. // Konqueror brain-dead techniques
  334. ycw = 50;
  335. s.left = (cd.offsetLeft + cd.offsetWidth - ycw) + "px";
  336. }
  337. s.top = (cd.offsetTop + cd.offsetHeight) + "px";
  338. }
  339. };
  340. // event handlers
  341. Calendar.tableMouseUp = function(ev) {
  342. var cal = Calendar._C;
  343. if (!cal) {
  344. return false;
  345. }
  346. if (cal.timeout) {
  347. clearTimeout(cal.timeout);
  348. }
  349. var el = cal.activeDiv;
  350. if (!el) {
  351. return false;
  352. }
  353. var target = Calendar.getTargetElement(ev);
  354. ev || (ev = window.event);
  355. Calendar.removeClass(el, "active");
  356. if (target == el || target.parentNode == el) {
  357. Calendar.cellClick(el, ev);
  358. }
  359. var mon = Calendar.findMonth(target);
  360. var date = null;
  361. if (mon) {
  362. date = new Date(cal.date);
  363. if (mon.month != date.getMonth()) {
  364. date.setMonth(mon.month);
  365. cal.setDate(date);
  366. cal.dateClicked = false;
  367. cal.callHandler();
  368. }
  369. } else {
  370. var year = Calendar.findYear(target);
  371. if (year) {
  372. date = new Date(cal.date);
  373. if (year.year != date.getFullYear()) {
  374. date.setFullYear(year.year);
  375. cal.setDate(date);
  376. cal.dateClicked = false;
  377. cal.callHandler();
  378. }
  379. }
  380. }
  381. with (Calendar) {
  382. removeEvent(document, "mouseup", tableMouseUp);
  383. removeEvent(document, "mouseover", tableMouseOver);
  384. removeEvent(document, "mousemove", tableMouseOver);
  385. cal._hideCombos();
  386. _C = null;
  387. return stopEvent(ev);
  388. }
  389. };
  390. Calendar.tableMouseOver = function(ev) {
  391. var cal = Calendar._C;
  392. if (!cal) {
  393. return;
  394. }
  395. var el = cal.activeDiv;
  396. var target = Calendar.getTargetElement(ev);
  397. if (target == el || target.parentNode == el) {
  398. Calendar.addClass(el, "hilite active");
  399. Calendar.addClass(el.parentNode, "rowhilite");
  400. } else {
  401. if (typeof el.navtype == "undefined"
  402. || (el.navtype != 50 && (el.navtype == 0 || Math
  403. .abs(el.navtype) > 2)))
  404. Calendar.removeClass(el, "active");
  405. Calendar.removeClass(el, "hilite");
  406. Calendar.removeClass(el.parentNode, "rowhilite");
  407. }
  408. ev || (ev = window.event);
  409. if (el.navtype == 50 && target != el) {
  410. var pos = Calendar.getAbsolutePos(el);
  411. var w = el.offsetWidth;
  412. var x = ev.clientX;
  413. var dx;
  414. var decrease = true;
  415. if (x > pos.x + w) {
  416. dx = x - pos.x - w;
  417. decrease = false;
  418. } else
  419. dx = pos.x - x;
  420. if (dx < 0)
  421. dx = 0;
  422. var range = el._range;
  423. var current = el._current;
  424. var count = Math.floor(dx / 10) % range.length;
  425. for (var i = range.length; --i >= 0;)
  426. if (range[i] == current)
  427. break;
  428. while (count-- > 0)
  429. if (decrease) {
  430. if (--i < 0)
  431. i = range.length - 1;
  432. } else if (++i >= range.length)
  433. i = 0;
  434. var newval = range[i];
  435. el.innerHTML = newval;
  436. cal.onUpdateTime();
  437. }
  438. var mon = Calendar.findMonth(target);
  439. if (mon) {
  440. if (mon.month != cal.date.getMonth()) {
  441. if (cal.hilitedMonth) {
  442. Calendar.removeClass(cal.hilitedMonth, "hilite");
  443. }
  444. Calendar.addClass(mon, "hilite");
  445. cal.hilitedMonth = mon;
  446. } else if (cal.hilitedMonth) {
  447. Calendar.removeClass(cal.hilitedMonth, "hilite");
  448. }
  449. } else {
  450. if (cal.hilitedMonth) {
  451. Calendar.removeClass(cal.hilitedMonth, "hilite");
  452. }
  453. var year = Calendar.findYear(target);
  454. if (year) {
  455. if (year.year != cal.date.getFullYear()) {
  456. if (cal.hilitedYear) {
  457. Calendar.removeClass(cal.hilitedYear, "hilite");
  458. }
  459. Calendar.addClass(year, "hilite");
  460. cal.hilitedYear = year;
  461. } else if (cal.hilitedYear) {
  462. Calendar.removeClass(cal.hilitedYear, "hilite");
  463. }
  464. } else if (cal.hilitedYear) {
  465. Calendar.removeClass(cal.hilitedYear, "hilite");
  466. }
  467. }
  468. return Calendar.stopEvent(ev);
  469. };
  470. Calendar.tableMouseDown = function(ev) {
  471. if (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) {
  472. return Calendar.stopEvent(ev);
  473. }
  474. };
  475. Calendar.calDragIt = function(ev) {
  476. var cal = Calendar._C;
  477. if (!(cal && cal.dragging)) {
  478. return false;
  479. }
  480. var posX;
  481. var posY;
  482. if (Calendar.is_ie) {
  483. posY = window.event.clientY + document.body.scrollTop;
  484. posX = window.event.clientX + document.body.scrollLeft;
  485. } else {
  486. posX = ev.pageX;
  487. posY = ev.pageY;
  488. }
  489. cal.hideShowCovered();
  490. var st = cal.element.style;
  491. st.left = (posX - cal.xOffs) + "px";
  492. st.top = (posY - cal.yOffs) + "px";
  493. return Calendar.stopEvent(ev);
  494. };
  495. Calendar.calDragEnd = function(ev) {
  496. var cal = Calendar._C;
  497. if (!cal) {
  498. return false;
  499. }
  500. cal.dragging = false;
  501. with (Calendar) {
  502. removeEvent(document, "mousemove", calDragIt);
  503. removeEvent(document, "mouseup", calDragEnd);
  504. tableMouseUp(ev);
  505. }
  506. cal.hideShowCovered();
  507. };
  508. Calendar.dayMouseDown = function(ev) {
  509. var el = Calendar.getElement(ev);
  510. if (el.disabled) {
  511. return false;
  512. }
  513. var cal = el.calendar;
  514. cal.activeDiv = el;
  515. Calendar._C = cal;
  516. if (el.navtype != 300)
  517. with (Calendar) {
  518. if (el.navtype == 50) {
  519. el._current = el.innerHTML;
  520. addEvent(document, "mousemove", tableMouseOver);
  521. } else
  522. addEvent(document, Calendar.is_ie5 ? "mousemove" : "mouseover",
  523. tableMouseOver);
  524. addClass(el, "hilite active");
  525. addEvent(document, "mouseup", tableMouseUp);
  526. }
  527. else if (cal.isPopup) {
  528. cal._dragStart(ev);
  529. }
  530. if (el.navtype == -1 || el.navtype == 1) {
  531. if (cal.timeout)
  532. clearTimeout(cal.timeout);
  533. cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250);
  534. } else if (el.navtype == -2 || el.navtype == 2) {
  535. if (cal.timeout)
  536. clearTimeout(cal.timeout);
  537. cal.timeout = setTimeout((el.navtype > 0)
  538. ? "Calendar.showYearsCombo(true)"
  539. : "Calendar.showYearsCombo(false)", 250);
  540. } else {
  541. cal.timeout = null;
  542. }
  543. return Calendar.stopEvent(ev);
  544. };
  545. Calendar.dayMouseDblClick = function(ev) {
  546. Calendar.cellClick(Calendar.getElement(ev), ev || window.event);
  547. if (Calendar.is_ie) {
  548. document.selection.empty();
  549. }
  550. };
  551. Calendar.dayMouseOver = function(ev) {
  552. var el = Calendar.getElement(ev);
  553. if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) {
  554. return false;
  555. }
  556. if (el.ttip) {
  557. if (el.ttip.substr(0, 1) == "_") {
  558. // -----------------------------------
  559. el.ttip = el.caldate.print(el.calendar.ttDateFormat)
  560. + el.ttip.substr(1);
  561. // add chinese DateLunar Print..
  562. el.ttip = el.ttip + "<br>" + el.caldate.DateLunarPrint();
  563. // add by sunzhigang ,print out all festivals the calender defined.
  564. el.ttip = el.ttip + el.caldate.FestivalPrint();
  565. }
  566. el.calendar.tooltips.innerHTML = el.ttip;
  567. }
  568. if (el.navtype != 300) {
  569. Calendar.addClass(el, "hilite");
  570. if (el.caldate) {
  571. Calendar.addClass(el.parentNode, "rowhilite");
  572. }
  573. }
  574. return Calendar.stopEvent(ev);
  575. };
  576. Calendar.dayMouseOut = function(ev) {
  577. with (Calendar) {
  578. var el = getElement(ev);
  579. if (isRelated(el, ev) || _C || el.disabled)
  580. return false;
  581. removeClass(el, "hilite");
  582. if (el.caldate)
  583. removeClass(el.parentNode, "rowhilite");
  584. if (el.calendar)
  585. el.calendar.tooltips.innerHTML = _TT["SEL_DATE"];
  586. return stopEvent(ev);
  587. }
  588. };
  589. /**
  590. * A generic "click" handler :) handles all types of buttons defined in this
  591. * calendar.
  592. */
  593. Calendar.cellClick = function(el, ev) {
  594. var cal = el.calendar;
  595. var closing = false;
  596. var newdate = false;
  597. var date = null;
  598. if (typeof el.navtype == "undefined") {
  599. if (cal.currentDateEl) {
  600. Calendar.removeClass(cal.currentDateEl, "selected");
  601. Calendar.addClass(el, "selected");
  602. closing = (cal.currentDateEl == el);
  603. if (!closing) {
  604. cal.currentDateEl = el;
  605. }
  606. }
  607. cal.date.setDateOnly(el.caldate);
  608. date = cal.date;
  609. var other_month = !(cal.dateClicked = !el.otherMonth);
  610. if (!other_month && !cal.currentDateEl)
  611. cal._toggleMultipleDate(new Date(date));
  612. else
  613. newdate = !el.disabled;
  614. // a date was clicked
  615. if (other_month)
  616. cal._init(cal.firstDayOfWeek, date);
  617. } else {
  618. if (el.navtype == 200) {
  619. Calendar.removeClass(el, "hilite");
  620. cal.callCloseHandler();
  621. return;
  622. }
  623. date = new Date(cal.date);
  624. if (el.navtype == 0)
  625. date.setDateOnly(allGetServerTime()); // TODAY
  626. // unless "today" was clicked, we assume no date was clicked so
  627. // the selected handler will know not to close the calenar when
  628. // in single-click mode.
  629. // cal.dateClicked = (el.navtype == 0);
  630. cal.dateClicked = false;
  631. var year = date.getFullYear();
  632. var mon = date.getMonth();
  633. function setMonth(m) {
  634. var day = date.getDate();
  635. var max = date.getMonthDays(m);
  636. if (day > max) {
  637. date.setDate(max);
  638. }
  639. date.setMonth(m);
  640. };
  641. switch (el.navtype) {
  642. case 400 :
  643. Calendar.removeClass(el, "hilite");
  644. var text = Calendar._TT["ABOUT"];
  645. if (typeof text != "undefined") {
  646. text += cal.showsTime ? Calendar._TT["ABOUT_TIME"] : "";
  647. } else {
  648. // FIXME: this should be removed as soon as lang files get
  649. // updated!
  650. text = "Help and about box text is not translated into this language.\n"
  651. + "If you know this language and you feel generous please update\n"
  652. + "the corresponding file in \"lang\" subdir to match calendar-en.js\n"
  653. + "and send it back to <mihai_bazon@yahoo.com> to get it into the distribution ;-)\n\n"
  654. + "Thank you!\n"
  655. + "http://dynarch.com/mishoo/calendar.epl\n";
  656. }
  657. alert(text);
  658. return;
  659. case -2 :
  660. if (year > cal.minYear) {
  661. date.setFullYear(year - 1);
  662. }
  663. break;
  664. case -1 :
  665. if (mon > 0) {
  666. setMonth(mon - 1);
  667. } else if (year-- > cal.minYear) {
  668. date.setFullYear(year);
  669. setMonth(11);
  670. }
  671. break;
  672. case 1 :
  673. if (mon < 11) {
  674. setMonth(mon + 1);
  675. } else if (year < cal.maxYear) {
  676. date.setFullYear(year + 1);
  677. setMonth(0);
  678. }
  679. break;
  680. case 2 :
  681. if (year < cal.maxYear) {
  682. date.setFullYear(year + 1);
  683. }
  684. break;
  685. case 100 :
  686. cal.setFirstDayOfWeek(el.fdow);
  687. return;
  688. case 50 :
  689. var range = el._range;
  690. var current = el.innerHTML;
  691. for (var i = range.length; --i >= 0;)
  692. if (range[i] == current)
  693. break;
  694. if (ev && ev.shiftKey) {
  695. if (--i < 0)
  696. i = range.length - 1;
  697. } else if (++i >= range.length)
  698. i = 0;
  699. var newval = range[i];
  700. el.innerHTML = newval;
  701. cal.onUpdateTime();
  702. return;
  703. case 0 :
  704. // TODAY will bring us here
  705. if ((typeof cal.getDateStatus == "function")
  706. && cal.getDateStatus(date, date.getFullYear(), date
  707. .getMonth(), date.getDate())) {
  708. return false;
  709. }
  710. break;
  711. }
  712. if (!date.equalsTo(cal.date)) {
  713. cal.setDate(date);
  714. newdate = true;
  715. } else if (el.navtype == 0)
  716. newdate = closing = true;
  717. }
  718. if (newdate) {
  719. ev && cal.callHandler();
  720. }
  721. if (closing) {
  722. Calendar.removeClass(el, "hilite");
  723. ev && cal.callCloseHandler();
  724. }
  725. };
  726. // END: CALENDAR STATIC FUNCTIONS
  727. // BEGIN: CALENDAR OBJECT FUNCTIONS
  728. /**
  729. * This function creates the calendar inside the given parent. If _par is null
  730. * than it creates a popup calendar inside the BODY element. If _par is an
  731. * element, be it BODY, then it creates a non-popup calendar (still hidden).
  732. * Some properties need to be set before calling this function.
  733. */
  734. Calendar.prototype.create = function(_par) {
  735. var parent = null;
  736. if (!_par) {
  737. // default parent is the document body, in which case we create
  738. // a popup calendar.
  739. parent = document.getElementsByTagName("body")[0];
  740. this.isPopup = true;
  741. } else {
  742. parent = _par;
  743. this.isPopup = false;
  744. }
  745. this.date = this.dateStr ? new Date(this.dateStr) : allGetServerTime();
  746. var table = Calendar.createElement("table");
  747. this.table = table;
  748. table.cellSpacing = 0;
  749. table.cellPadding = 0;
  750. table.calendar = this;
  751. Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown);
  752. var div = Calendar.createElement("div");
  753. this.element = div;
  754. div.className = "calendar";
  755. if (this.isPopup) {
  756. div.style.position = "absolute";
  757. div.style.display = "none";
  758. }
  759. div.appendChild(table);
  760. var thead = Calendar.createElement("thead", table);
  761. var cell = null;
  762. var row = null;
  763. var cal = this;
  764. var hh = function(text, cs, navtype) {
  765. cell = Calendar.createElement("td", row);
  766. cell.colSpan = cs;
  767. cell.className = "cabutton";
  768. if (navtype != 0 && Math.abs(navtype) <= 2)
  769. cell.className += " nav";
  770. Calendar._add_evs(cell);
  771. cell.calendar = cal;
  772. cell.navtype = navtype;
  773. cell.innerHTML = "<div unselectable='on'>" + text + "</div>";
  774. return cell;
  775. };
  776. row = Calendar.createElement("tr", thead);
  777. var title_length = 6;
  778. (this.isPopup) && --title_length;
  779. (this.weekNumbers) && ++title_length;
  780. hh("?", 1, 400).ttip = Calendar._TT["INFO"];
  781. this.title = hh("", title_length, 300);
  782. this.title.className = "title";
  783. if (this.isPopup) {
  784. this.title.ttip = Calendar._TT["DRAG_TO_MOVE"];
  785. this.title.style.cursor = "move";
  786. hh("&#x00d7;", 1, 200).ttip = Calendar._TT["CLOSE"];
  787. }
  788. row = Calendar.createElement("tr", thead);
  789. row.className = "headrow";
  790. this._nav_py = hh("&#x00ab;", 1, -2);
  791. this._nav_py.ttip = Calendar._TT["PREV_YEAR"];
  792. this._nav_pm = hh("&#x2039;", 1, -1);
  793. this._nav_pm.ttip = Calendar._TT["PREV_MONTH"];
  794. this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0);
  795. this._nav_now.ttip = Calendar._TT["GO_TODAY"];
  796. this._nav_nm = hh("&#x203a;", 1, 1);
  797. this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];
  798. this._nav_ny = hh("&#x00bb;", 1, 2);
  799. this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"];
  800. // day names
  801. row = Calendar.createElement("tr", thead);
  802. row.className = "daynames";
  803. if (this.weekNumbers) {
  804. cell = Calendar.createElement("td", row);
  805. cell.className = "name wn";
  806. cell.innerHTML = Calendar._TT["WK"];
  807. }
  808. for (var i = 7; i > 0; --i) {
  809. cell = Calendar.createElement("td", row);
  810. if (!i) {
  811. cell.navtype = 100;
  812. cell.calendar = this;
  813. Calendar._add_evs(cell);
  814. }
  815. }
  816. this.firstdayname = (this.weekNumbers)
  817. ? row.firstChild.nextSibling
  818. : row.firstChild;
  819. this._displayWeekdays();
  820. var tbody = Calendar.createElement("tbody", table);
  821. this.tbody = tbody;
  822. for (i = 6; i > 0; --i) {
  823. row = Calendar.createElement("tr", tbody);
  824. if (this.weekNumbers) {
  825. cell = Calendar.createElement("td", row);
  826. }
  827. for (var j = 7; j > 0; --j) {
  828. cell = Calendar.createElement("td", row);
  829. cell.calendar = this;
  830. Calendar._add_evs(cell);
  831. }
  832. }
  833. if (this.showsTime) {
  834. row = Calendar.createElement("tr", tbody);
  835. row.className = "time";
  836. cell = Calendar.createElement("td", row);
  837. cell.className = "time";
  838. cell.colSpan = 2;
  839. cell.innerHTML = Calendar._TT["TIME"] || "&nbsp;";
  840. cell = Calendar.createElement("td", row);
  841. cell.className = "time";
  842. cell.colSpan = this.weekNumbers ? 4 : 3;
  843. (function() {
  844. function makeTimePart(className, init, range_start, range_end) {
  845. var part = Calendar.createElement("span", cell);
  846. part.className = className;
  847. part.innerHTML = init;
  848. part.calendar = cal;
  849. part.ttip = Calendar._TT["TIME_PART"];
  850. part.navtype = 50;
  851. part._range = [];
  852. if (typeof range_start != "number")
  853. part._range = range_start;
  854. else {
  855. for (var i = range_start; i <= range_end; ++i) {
  856. var txt;
  857. if (i < 10 && range_end >= 10)
  858. txt = '0' + i;
  859. else
  860. txt = '' + i;
  861. part._range[part._range.length] = txt;
  862. }
  863. }
  864. Calendar._add_evs(part);
  865. return part;
  866. };
  867. var hrs = cal.date.getHours();
  868. var mins = cal.date.getMinutes();
  869. var t12 = !cal.time24;
  870. var pm = (hrs > 12);
  871. if (t12 && pm)
  872. hrs -= 12;
  873. var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23);
  874. var span = Calendar.createElement("span", cell);
  875. span.innerHTML = ":";
  876. span.className = "colon";
  877. var M = makeTimePart("minute", mins, 0, 59);
  878. var AP = null;
  879. cell = Calendar.createElement("td", row);
  880. cell.className = "time";
  881. cell.colSpan = 2;
  882. if (t12)
  883. AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]);
  884. else
  885. cell.innerHTML = "&nbsp;";
  886. cal.onSetTime = function() {
  887. var pm, hrs = this.date.getHours(), mins = this.date
  888. .getMinutes();
  889. if (t12) {
  890. pm = (hrs >= 12);
  891. if (pm)
  892. hrs -= 12;
  893. if (hrs == 0)
  894. hrs = 12;
  895. AP.innerHTML = pm ? "pm" : "am";
  896. }
  897. H.innerHTML = (hrs < 10) ? ("0" + hrs) : hrs;
  898. M.innerHTML = (mins < 10) ? ("0" + mins) : mins;
  899. };
  900. cal.onUpdateTime = function() {
  901. var date = this.date;
  902. var h = parseInt(H.innerHTML, 10);
  903. if (t12) {
  904. if (/pm/i.test(AP.innerHTML) && h < 12)
  905. h += 12;
  906. else if (/am/i.test(AP.innerHTML) && h == 12)
  907. h = 0;
  908. }
  909. var d = date.getDate();
  910. var m = date.getMonth();
  911. var y = date.getFullYear();
  912. date.setHours(h);
  913. date.setMinutes(parseInt(M.innerHTML, 10));
  914. date.setFullYear(y);
  915. date.setMonth(m);
  916. date.setDate(d);
  917. this.dateClicked = false;
  918. this.callHandler();
  919. };
  920. })();
  921. } else {
  922. this.onSetTime = this.onUpdateTime = function() {
  923. };
  924. }
  925. var tfoot = Calendar.createElement("tfoot", table);
  926. row = Calendar.createElement("tr", tfoot);
  927. row.className = "footrow";
  928. cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300);
  929. cell.className = "ttip";
  930. if (this.isPopup) {
  931. cell.ttip = Calendar._TT["DRAG_TO_MOVE"];
  932. cell.style.cursor = "move";
  933. }
  934. this.tooltips = cell;
  935. div = Calendar.createElement("div", this.element);
  936. this.monthsCombo = div;
  937. div.className = "combo";
  938. for (i = 0; i < Calendar._MN.length; ++i) {
  939. var mn = Calendar.createElement("div");
  940. mn.className = Calendar.is_ie ? "label-IEfix" : "label";
  941. mn.month = i;
  942. mn.innerHTML = Calendar._SMN[i];
  943. div.appendChild(mn);
  944. }
  945. div = Calendar.createElement("div", this.element);
  946. this.yearsCombo = div;
  947. div.className = "combo";
  948. for (i = 12; i > 0; --i) {
  949. var yr = Calendar.createElement("div");
  950. yr.className = Calendar.is_ie ? "label-IEfix" : "label";
  951. div.appendChild(yr);
  952. }
  953. this._init(this.firstDayOfWeek, this.date);
  954. parent.appendChild(this.element);
  955. };
  956. /** keyboard navigation, only for popup calendars */
  957. Calendar._keyEvent = function(ev) {
  958. var cal = window._dynarch_popupCalendar;
  959. if (!cal || cal.multiple)
  960. return false;
  961. (Calendar.is_ie) && (ev = window.event);
  962. var act = (Calendar.is_ie || ev.type == "keypress"), K = ev.keyCode;
  963. if (ev.ctrlKey) {
  964. switch (K) {
  965. case 37 : // KEY left
  966. act && Calendar.cellClick(cal._nav_pm);
  967. break;
  968. case 38 : // KEY up
  969. act && Calendar.cellClick(cal._nav_py);
  970. break;
  971. case 39 : // KEY right
  972. act && Calendar.cellClick(cal._nav_nm);
  973. break;
  974. case 40 : // KEY down
  975. act && Calendar.cellClick(cal._nav_ny);
  976. break;
  977. default :
  978. return false;
  979. }
  980. } else
  981. switch (K) {
  982. case 32 : // KEY space (now)
  983. Calendar.cellClick(cal._nav_now);
  984. break;
  985. case 27 : // KEY esc
  986. act && cal.callCloseHandler();
  987. break;
  988. case 37 : // KEY left
  989. case 38 : // KEY up
  990. case 39 : // KEY right
  991. case 40 : // KEY down
  992. if (act) {
  993. var prev, x, y, ne, el, step;
  994. prev = K == 37 || K == 38;
  995. step = (K == 37 || K == 39) ? 1 : 7;
  996. function setVars() {
  997. el = cal.currentDateEl;
  998. var p = el.pos;
  999. x = p & 15;
  1000. y = p >> 4;
  1001. ne = cal.ar_days[y][x];
  1002. };
  1003. setVars();
  1004. function prevMonth() {
  1005. var date = new Date(cal.date);
  1006. date.setDate(date.getDate() - step);
  1007. cal.setDate(date);
  1008. };
  1009. function nextMonth() {
  1010. var date = new Date(cal.date);
  1011. date.setDate(date.getDate() + step);
  1012. cal.setDate(date);
  1013. };
  1014. while (1) {
  1015. switch (K) {
  1016. case 37 : // KEY left
  1017. if (--x >= 0)
  1018. ne = cal.ar_days[y][x];
  1019. else {
  1020. x = 6;
  1021. K = 38;
  1022. continue;
  1023. }
  1024. break;
  1025. case 38 : // KEY up
  1026. if (--y >= 0)
  1027. ne = cal.ar_days[y][x];
  1028. else {
  1029. prevMonth();
  1030. setVars();
  1031. }
  1032. break;
  1033. case 39 : // KEY right
  1034. if (++x < 7)
  1035. ne = cal.ar_days[y][x];
  1036. else {
  1037. x = 0;
  1038. K = 40;
  1039. continue;
  1040. }
  1041. break;
  1042. case 40 : // KEY down
  1043. if (++y < cal.ar_days.length)
  1044. ne = cal.ar_days[y][x];
  1045. else {
  1046. nextMonth();
  1047. setVars();
  1048. }
  1049. break;
  1050. }
  1051. break;
  1052. }
  1053. if (ne) {
  1054. if (!ne.disabled)
  1055. Calendar.cellClick(ne);
  1056. else if (prev)
  1057. prevMonth();
  1058. else
  1059. nextMonth();
  1060. }
  1061. }
  1062. break;
  1063. case 13 : // KEY enter
  1064. if (act)
  1065. Calendar.cellClick(cal.currentDateEl, ev);
  1066. break;
  1067. default :
  1068. return false;
  1069. }
  1070. return Calendar.stopEvent(ev);
  1071. };
  1072. /**
  1073. * (RE)Initializes the calendar to the given date and firstDayOfWeek
  1074. */
  1075. Calendar.prototype._init = function(firstDayOfWeek, date) {
  1076. var today = allGetServerTime(), TY = today.getFullYear(), TM = today.getMonth(), TD = today
  1077. .getDate();
  1078. this.table.style.visibility = "hidden";
  1079. var year = date.getFullYear();
  1080. if (year < this.minYear) {
  1081. year = this.minYear;
  1082. date.setFullYear(year);
  1083. } else if (year > this.maxYear) {
  1084. year = this.maxYear;
  1085. date.setFullYear(year);
  1086. }
  1087. this.firstDayOfWeek = firstDayOfWeek;
  1088. this.date = new Date(date);
  1089. var month = date.getMonth();
  1090. var mday = date.getDate();
  1091. var no_days = date.getMonthDays();
  1092. // calendar voodoo for computing the first day that would actually be
  1093. // displayed in the calendar, even if it's from the previous month.
  1094. // WARNING: this is magic. ;-)
  1095. date.setDate(1);
  1096. var day1 = (date.getDay() - this.firstDayOfWeek) % 7;
  1097. if (day1 < 0)
  1098. day1 += 7;
  1099. date.setDate(-day1);
  1100. date.setDate(date.getDate() + 1);
  1101. var row = this.tbody.firstChild;
  1102. var MN = Calendar._SMN[month];
  1103. var ar_days = this.ar_days = new Array();
  1104. var weekend = Calendar._TT["WEEKEND"];
  1105. var dates = this.multiple ? (this.datesCells = {}) : null;
  1106. for (var i = 0; i < 6; ++i, row = row.nextSibling) {
  1107. var cell = row.firstChild;
  1108. if (this.weekNumbers) {
  1109. cell.className = "day wn";
  1110. cell.innerHTML = date.getWeekNumber();
  1111. cell = cell.nextSibling;
  1112. }
  1113. row.className = "daysrow";
  1114. var hasdays = false, iday, dpos = ar_days[i] = [];
  1115. for (var j = 0; j < 7; ++j, cell = cell.nextSibling, date.setDate(iday
  1116. + 1)) {
  1117. iday = date.getDate();
  1118. var wday = date.getDay();
  1119. cell.className = "day";
  1120. cell.pos = i << 4 | j;
  1121. dpos[j] = cell;
  1122. var current_month = (date.getMonth() == month);
  1123. if (!current_month) {
  1124. if (this.showsOtherMonths) {
  1125. cell.className += " othermonth";
  1126. cell.otherMonth = true;
  1127. } else {
  1128. cell.className = "emptycell";
  1129. cell.innerHTML = "&nbsp;";
  1130. cell.disabled = true;
  1131. continue;
  1132. }
  1133. } else {
  1134. cell.otherMonth = false;
  1135. hasdays = true;
  1136. }
  1137. cell.disabled = false;
  1138. cell.innerHTML = this.getDateText
  1139. ? this.getDateText(date, iday)
  1140. : iday;
  1141. if (dates)
  1142. dates[date.print("%Y%m%d")] = cell;
  1143. if (this.getDateStatus) {
  1144. // ========SEND THIS OBJECT TO SETDATE
  1145. // STATUS=====================================================
  1146. var status = this.getDateStatus(this, date, year, month, iday);
  1147. if (this.getDateToolTip) {
  1148. var toolTip = this.getDateToolTip(date, year, month, iday);
  1149. if (toolTip)
  1150. cell.title = toolTip;
  1151. }
  1152. if (status === true) {
  1153. cell.className += " disabled";
  1154. cell.disabled = true;
  1155. } else {
  1156. if (/disabled/i.test(status))
  1157. cell.disabled = true;
  1158. cell.className += " " + status;
  1159. }
  1160. }
  1161. if (!cell.disabled) {
  1162. cell.caldate = new Date(date);
  1163. cell.ttip = "_";
  1164. if (!this.multiple && current_month && iday == mday
  1165. && this.hiliteToday) {
  1166. cell.className += " selected";
  1167. this.currentDateEl = cell;
  1168. }
  1169. if (date.getFullYear() == TY && date.getMonth() == TM
  1170. && iday == TD) {
  1171. cell.className += " today";
  1172. cell.ttip += Calendar._TT["PART_TODAY"];
  1173. }
  1174. if (weekend.indexOf(wday.toString()) != -1)
  1175. cell.className += cell.otherMonth
  1176. ? " oweekend"
  1177. : " weekend";
  1178. }
  1179. }
  1180. if (!(hasdays || this.showsOtherMonths))
  1181. row.className = "emptyrow";
  1182. }
  1183. // modify by sunzhigang to show year first
  1184. this.title.innerHTML = year + ", " + Calendar._MN[month];
  1185. this.onSetTime();
  1186. this.table.style.visibility = "visible";
  1187. this._initMultipleDates();
  1188. // PROFILE
  1189. // this.tooltips.innerHTML = "Generated in " + ((allGetServerTime()) - today) + "
  1190. // ms";
  1191. };
  1192. Calendar.prototype._initMultipleDates = function() {
  1193. if (this.multiple) {
  1194. for (var i in this.multiple) {
  1195. var cell = this.datesCells[i];
  1196. var d = this.multiple[i];
  1197. if (!d)
  1198. continue;
  1199. if (cell)
  1200. cell.className += " selected";
  1201. }
  1202. }
  1203. };
  1204. Calendar.prototype._toggleMultipleDate = function(date) {
  1205. if (this.multiple) {
  1206. var ds = date.print("%Y%m%d");
  1207. var cell = this.datesCells[ds];
  1208. if (cell) {
  1209. var d = this.multiple[ds];
  1210. if (!d) {
  1211. Calendar.addClass(cell, "selected");
  1212. this.multiple[ds] = date;
  1213. } else {
  1214. Calendar.removeClass(cell, "selected");
  1215. delete this.multiple[ds];
  1216. }
  1217. }
  1218. }
  1219. };
  1220. Calendar.prototype.setDateToolTipHandler = function(unaryFunction) {
  1221. this.getDateToolTip = unaryFunction;
  1222. };
  1223. /**
  1224. * Calls _init function above for going to a certain date (but only if the date
  1225. * is different than the currently selected one).
  1226. */
  1227. Calendar.prototype.setDate = function(date) {
  1228. if (!date.equalsTo(this.date)) {
  1229. this._init(this.firstDayOfWeek, date);
  1230. }
  1231. };
  1232. /**
  1233. * Refreshes the calendar. Useful if the "disabledHandler" function is dynamic,
  1234. * meaning that the list of disabled date can change at runtime. Just * call
  1235. * this function if you think that the list of disabled dates should * change.
  1236. */
  1237. Calendar.prototype.refresh = function() {
  1238. this._init(this.firstDayOfWeek, this.date);
  1239. };
  1240. /**
  1241. * Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday,
  1242. * etc.).
  1243. */
  1244. Calendar.prototype.setFirstDayOfWeek = function(firstDayOfWeek) {
  1245. this._init(firstDayOfWeek, this.date);
  1246. this._displayWeekdays();
  1247. };
  1248. /**
  1249. * Allows customization of what dates are enabled. The "unaryFunction" parameter
  1250. * must be a function object that receives the date (as a JS Date object) and
  1251. * returns a boolean value. If the returned value is true then the passed date
  1252. * will be marked as disabled.
  1253. */
  1254. Calendar.prototype.setDateStatusHandler = Calendar.prototype.setDisabledHandler = function(
  1255. unaryFunction) {
  1256. this.getDateStatus = unaryFunction;
  1257. };
  1258. /** Customization of allowed year range for the calendar. */
  1259. Calendar.prototype.setRange = function(a, z) {
  1260. this.minYear = a;
  1261. this.maxYear = z;
  1262. };
  1263. /** Calls the first user handler (selectedHandler). */
  1264. Calendar.prototype.callHandler = function() {
  1265. if (this.onSelected) {
  1266. this.onSelected(this, this.date.print(this.dateFormat));
  1267. }
  1268. };
  1269. /** Calls the second user handler (closeHandler). */
  1270. Calendar.prototype.callCloseHandler = function() {
  1271. if (this.onClose) {
  1272. this.onClose(this);
  1273. }
  1274. this.hideShowCovered();
  1275. };
  1276. /** Removes the calendar object from the DOM tree and destroys it. */
  1277. Calendar.prototype.destroy = function() {
  1278. var el = this.element.parentNode;
  1279. el.removeChild(this.element);
  1280. Calendar._C = null;
  1281. window._dynarch_popupCalendar = null;
  1282. };
  1283. /**
  1284. * Moves the calendar element to a different section in the DOM tree (changes
  1285. * its parent).
  1286. */
  1287. Calendar.prototype.reparent = function(new_parent) {
  1288. var el = this.element;
  1289. el.parentNode.removeChild(el);
  1290. new_parent.appendChild(el);
  1291. };
  1292. // This gets called when the user presses a mouse button anywhere in the
  1293. // document, if the calendar is shown. If the click was outside the open
  1294. // calendar this function closes it.
  1295. Calendar._checkCalendar = function(ev) {
  1296. var calendar = window._dynarch_popupCalendar;
  1297. if (!calendar) {
  1298. return false;
  1299. }
  1300. var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar
  1301. .getTargetElement(ev);
  1302. for (; el != null && el != calendar.element; el = el.parentNode);
  1303. if (el == null) {
  1304. // calls closeHandler which should hide the calendar.
  1305. window._dynarch_popupCalendar.callCloseHandler();
  1306. return Calendar.stopEvent(ev);
  1307. }
  1308. };
  1309. /** Shows the calendar. */
  1310. Calendar.prototype.show = function() {
  1311. var rows = this.table.getElementsByTagName("tr");
  1312. for (var i = rows.length; i > 0;) {
  1313. var row = rows[--i];
  1314. Calendar.removeClass(row, "rowhilite");
  1315. var cells = row.getElementsByTagName("td");
  1316. for (var j = cells.length; j > 0;) {
  1317. var cell = cells[--j];
  1318. Calendar.removeClass(cell, "hilite");
  1319. Calendar.removeClass(cell, "active");
  1320. }
  1321. }
  1322. this.element.style.display = "block";
  1323. this.hidden = false;
  1324. if (this.isPopup) {
  1325. window._dynarch_popupCalendar = this;
  1326. Calendar.addEvent(document, "keydown", Calendar._keyEvent);
  1327. Calendar.addEvent(document, "keypress", Calendar._keyEvent);
  1328. Calendar.addEvent(document, "mousedown", Calendar._checkCalendar);
  1329. }
  1330. this.hideShowCovered();
  1331. };
  1332. /**
  1333. * Hides the calendar. Also removes any "hilite" from the class of any TD
  1334. * element.
  1335. */
  1336. Calendar.prototype.hide = function() {
  1337. if (this.isPopup) {
  1338. Calendar.removeEvent(document, "keydown", Calendar._keyEvent);
  1339. Calendar.removeEvent(document, "keypress", Calendar._keyEvent);
  1340. Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar);
  1341. }
  1342. this.element.style.display = "none";
  1343. this.hidden = true;
  1344. this.hideShowCovered();
  1345. };
  1346. /**
  1347. * Shows the calendar at a given absolute position (beware that, depending on
  1348. * the calendar element style -- position property -- this might be relative to
  1349. * the parent's containing rectangle).
  1350. */
  1351. Calendar.prototype.showAt = function(x, y) {
  1352. var s = this.element.style;
  1353. s.left = x + "px";
  1354. s.top = y + "px";
  1355. this.show();
  1356. };
  1357. /** Shows the calendar near a given element. */
  1358. Calendar.prototype.showAtElement = function(el, opts) {
  1359. var self = this;
  1360. var p = Calendar.getAbsolutePos(el);
  1361. if (!opts || typeof opts != "string") {
  1362. this.showAt(p.x, p.y + el.offsetHeight);
  1363. return true;
  1364. }
  1365. function fixPosition(box) {
  1366. if (box.x < 0)
  1367. box.x = 0;
  1368. if (box.y < 0)
  1369. box.y = 0;
  1370. var cp = document.createElement("div");
  1371. var s = cp.style;
  1372. s.position = "absolute";
  1373. s.right = s.bottom = s.width = s.height = "0px";
  1374. document.body.appendChild(cp);
  1375. var br = Calendar.getAbsolutePos(cp);
  1376. document.body.removeChild(cp);
  1377. if (Calendar.is_ie) {
  1378. br.y += document.body.scrollTop;
  1379. br.x += document.body.scrollLeft;
  1380. } else {
  1381. br.y += window.scrollY;
  1382. br.x += window.scrollX;
  1383. }
  1384. var tmp = box.x + box.width - br.x;
  1385. if (tmp > 0)
  1386. box.x -= tmp;
  1387. tmp = box.y + box.height - br.y;
  1388. if (tmp > 0)
  1389. box.y -= tmp;
  1390. };
  1391. this.element.style.display = "block";
  1392. Calendar.continuation_for_the_fucking_khtml_browser = function() {
  1393. var w = self.element.offsetWidth;
  1394. var h = self.element.offsetHeight;
  1395. self.element.style.display = "none";
  1396. var valign = opts.substr(0, 1);
  1397. var halign = "l";
  1398. if (opts.length > 1) {
  1399. halign = opts.substr(1, 1);
  1400. }
  1401. // vertical alignment
  1402. switch (valign) {
  1403. case "T" :
  1404. p.y -= h;
  1405. break;
  1406. case "B" :
  1407. p.y += el.offsetHeight;
  1408. break;
  1409. case "C" :
  1410. p.y += (el.offsetHeight - h) / 2;
  1411. break;
  1412. case "t" :
  1413. p.y += el.offsetHeight - h;
  1414. break;
  1415. case "b" :
  1416. break; // already there
  1417. }
  1418. // horizontal alignment
  1419. switch (halign) {
  1420. case "L" :
  1421. p.x -= w;
  1422. break;
  1423. case "R" :
  1424. p.x += el.offsetWidth;
  1425. break;
  1426. case "C" :
  1427. p.x += (el.offsetWidth - w) / 2;
  1428. break;
  1429. case "l" :
  1430. p.x += el.offsetWidth - w;
  1431. break;
  1432. case "r" :
  1433. break; // already there
  1434. }
  1435. p.width = w;
  1436. p.height = h + 40;
  1437. self.monthsCombo.style.display = "none";
  1438. fixPosition(p);
  1439. self.showAt(p.x, p.y);
  1440. };
  1441. if (Calendar.is_khtml)
  1442. setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10);
  1443. else
  1444. Calendar.continuation_for_the_fucking_khtml_browser();
  1445. };
  1446. /** Customizes the date format. */
  1447. Calendar.prototype.setDateFormat = function(str) {
  1448. this.dateFormat = str;
  1449. };
  1450. /** Customizes the tooltip date format. */
  1451. Calendar.prototype.setTtDateFormat = function(str) {
  1452. this.ttDateFormat = str;
  1453. };
  1454. /**
  1455. * Tries to identify the date represented in a string. If successful it also
  1456. * calls this.setDate which moves the calendar to the given date.
  1457. */
  1458. Calendar.prototype.parseDate = function(str, fmt) {
  1459. if (!fmt)
  1460. fmt = this.dateFormat;
  1461. this.setDate(Date.parseDate(str, fmt));
  1462. };
  1463. Calendar.prototype.hideShowCovered = function() {
  1464. if (!Calendar.is_ie && !Calendar.is_opera)
  1465. return;
  1466. function getVisib(obj) {
  1467. var value = obj.style.visibility;
  1468. if (!value) {
  1469. if (document.defaultView
  1470. && typeof(document.defaultView.getComputedStyle) == "function") { // Gecko,
  1471. // W3C
  1472. if (!Calendar.is_khtml)
  1473. value = document.defaultView.getComputedStyle(obj, "")
  1474. .getPropertyValue("visibility");
  1475. else
  1476. value = '';
  1477. } else if (obj.currentStyle) { // IE
  1478. value = obj.currentStyle.visibility;
  1479. } else
  1480. value = '';
  1481. }
  1482. return value;
  1483. };
  1484. var tags = new Array("applet", "iframe", "select");
  1485. var el = this.element;
  1486. var p = Calendar.getAbsolutePos(el);
  1487. var EX1 = p.x;
  1488. var EX2 = el.offsetWidth + EX1;
  1489. var EY1 = p.y;
  1490. var EY2 = el.offsetHeight + EY1;
  1491. for (var k = tags.length; k > 0;) {
  1492. var ar = document.getElementsByTagName(tags[--k]);
  1493. var cc = null;
  1494. for (var i = ar.length; i > 0;) {
  1495. cc = ar[--i];
  1496. p = Calendar.getAbsolutePos(cc);
  1497. var CX1 = p.x;
  1498. var CX2 = cc.offsetWidth + CX1;
  1499. var CY1 = p.y;
  1500. var CY2 = cc.offsetHeight + CY1;
  1501. if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2)
  1502. || (CY2 < EY1)) {
  1503. if (!cc.__msh_save_visibility) {
  1504. cc.__msh_save_visibility = getVisib(cc);
  1505. }
  1506. cc.style.visibility = cc.__msh_save_visibility;
  1507. } else {
  1508. if (!cc.__msh_save_visibility) {
  1509. cc.__msh_save_visibility = getVisib(cc);
  1510. }
  1511. cc.style.visibility = "hidden";
  1512. }
  1513. }
  1514. }
  1515. };
  1516. /** Internal function; it displays the bar with the names of the weekday. */
  1517. Calendar.prototype._displayWeekdays = function() {
  1518. var fdow = this.firstDayOfWeek;
  1519. var cell = this.firstdayname;
  1520. var weekend = Calendar._TT["WEEKEND"];
  1521. for (var i = 0; i < 7; ++i) {
  1522. cell.className = "day name";
  1523. var realday = (i + fdow) % 7;
  1524. if (i) {
  1525. cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s",
  1526. Calendar._DN[realday]);
  1527. cell.navtype = 100;
  1528. cell.calendar = this;
  1529. cell.fdow = realday;
  1530. Calendar._add_evs(cell);
  1531. }
  1532. if (weekend.indexOf(realday.toString()) != -1) {
  1533. Calendar.addClass(cell, "weekend");
  1534. }
  1535. cell.innerHTML = Calendar._SDN[(i + fdow) % 7];
  1536. cell = cell.nextSibling;
  1537. }
  1538. };
  1539. /** Internal function. Hides all combo boxes that might be displayed. */
  1540. Calendar.prototype._hideCombos = function() {
  1541. this.monthsCombo.style.display = "none";
  1542. this.yearsCombo.style.display = "none";
  1543. };
  1544. /** Internal function. Starts dragging the element. */
  1545. Calendar.prototype._dragStart = function(ev) {
  1546. if (this.dragging) {
  1547. return;
  1548. }
  1549. this.dragging = true;
  1550. var posX;
  1551. var posY;
  1552. if (Calendar.is_ie) {
  1553. posY = window.event.clientY + document.body.scrollTop;
  1554. posX = window.event.clientX + document.body.scrollLeft;
  1555. } else {
  1556. posY = ev.clientY + window.scrollY;
  1557. posX = ev.clientX + window.scrollX;
  1558. }
  1559. var st = this.element.style;
  1560. this.xOffs = posX - parseInt(st.left);
  1561. this.yOffs = posY - parseInt(st.top);
  1562. with (Calendar) {
  1563. addEvent(document, "mousemove", calDragIt);
  1564. addEvent(document, "mouseup", calDragEnd);
  1565. }
  1566. };
  1567. // BEGIN: DATE OBJECT PATCHES
  1568. /** Adds the number of days array to the Date object. */
  1569. Date._MD = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
  1570. /** Constants used for time computations */
  1571. Date.SECOND = 1000 /* milliseconds */;
  1572. Date.MINUTE = 60 * Date.SECOND;
  1573. Date.HOUR = 60 * Date.MINUTE;
  1574. Date.DAY = 24 * Date.HOUR;
  1575. Date.WEEK = 7 * Date.DAY;
  1576. Date.parseDate = function(str, fmt) {
  1577. var today = allGetServerTime();
  1578. var y = 0;
  1579. var m = -1;
  1580. var d = 0;
  1581. var a = str.split(/\W+/);
  1582. var b = fmt.match(/%./g);
  1583. var i = 0, j = 0;
  1584. var hr = 0;
  1585. var min = 0;
  1586. for (i = 0; i < a.length; ++i) {
  1587. if (!a[i])
  1588. continue;
  1589. switch (b[i]) {
  1590. case "%d" :
  1591. case "%e" :
  1592. d = parseInt(a[i], 10);
  1593. break;
  1594. case "%m" :
  1595. m = parseInt(a[i], 10) - 1;
  1596. break;
  1597. case "%Y" :
  1598. case "%y" :
  1599. y = parseInt(a[i], 10);
  1600. (y < 100) && (y += (y > 29) ? 1900 : 2000);
  1601. break;
  1602. case "%b" :
  1603. case "%B" :
  1604. for (j = 0; j < 12; ++j) {
  1605. if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i]
  1606. .toLowerCase()) {
  1607. m = j;
  1608. break;
  1609. }
  1610. }
  1611. break;
  1612. case "%H" :
  1613. case "%I" :
  1614. case "%k" :
  1615. case "%l" :
  1616. hr = parseInt(a[i], 10);
  1617. break;
  1618. case "%P" :
  1619. case "%p" :
  1620. if (/pm/i.test(a[i]) && hr < 12)
  1621. hr += 12;
  1622. else if (/am/i.test(a[i]) && hr >= 12)
  1623. hr -= 12;
  1624. break;
  1625. case "%M" :
  1626. min = parseInt(a[i], 10);
  1627. break;
  1628. }
  1629. }
  1630. if (isNaN(y))
  1631. y = today.getFullYear();
  1632. if (isNaN(m))
  1633. m = today.getMonth();
  1634. if (isNaN(d))
  1635. d = today.getDate();
  1636. if (isNaN(hr))
  1637. hr = today.getHours();
  1638. if (isNaN(min))
  1639. min = today.getMinutes();
  1640. if (y != 0 && m != -1 && d != 0)
  1641. return new Date(y, m, d, hr, min, 0);
  1642. y = 0;
  1643. m = -1;
  1644. d = 0;
  1645. for (i = 0; i < a.length; ++i) {
  1646. if (a[i].search(/[a-zA-Z]+/) != -1) {
  1647. var t = -1;
  1648. for (j = 0; j < 12; ++j) {
  1649. if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i]
  1650. .toLowerCase()) {
  1651. t = j;
  1652. break;
  1653. }
  1654. }
  1655. if (t != -1) {
  1656. if (m != -1) {
  1657. d = m + 1;
  1658. }
  1659. m = t;
  1660. }
  1661. } else if (parseInt(a[i], 10) <= 12 && m == -1) {
  1662. m = a[i] - 1;
  1663. } else if (parseInt(a[i], 10) > 31 && y == 0) {
  1664. y = parseInt(a[i], 10);
  1665. (y < 100) && (y += (y > 29) ? 1900 : 2000);
  1666. } else if (d == 0) {
  1667. d = a[i];
  1668. }
  1669. }
  1670. if (y == 0)
  1671. y = today.getFullYear();
  1672. if (m != -1 && d != 0)
  1673. return new Date(y, m, d, hr, min, 0);
  1674. return today;
  1675. };
  1676. /** Returns the number of days in the current month */
  1677. Date.prototype.getMonthDays = function(month) {
  1678. var year = this.getFullYear();
  1679. if (typeof month == "undefined") {
  1680. month = this.getMonth();
  1681. }
  1682. if (((0 == (year % 4)) && ((0 != (year % 100)) || (0 == (year % 400))))
  1683. && month == 1) {
  1684. return 29;
  1685. } else {
  1686. return Date._MD[month];
  1687. }
  1688. };
  1689. /** Returns the number of day in the year. */
  1690. Date.prototype.getDayOfYear = function() {
  1691. var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0,
  1692. 0, 0);
  1693. var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
  1694. var time = now - then;
  1695. return Math.floor(time / Date.DAY);
  1696. };
  1697. /** Returns the number of the week in year, as defined in ISO 8601. */
  1698. Date.prototype.getWeekNumber = function() {
  1699. var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0,
  1700. 0);
  1701. var DoW = d.getDay();
  1702. d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
  1703. var ms = d.valueOf(); // GMT
  1704. d.setMonth(0);
  1705. d.setDate(4); // Thu in Week 1
  1706. return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
  1707. };
  1708. /** Checks date and time equality */
  1709. Date.prototype.equalsTo = function(date) {
  1710. return ((this.getFullYear() == date.getFullYear())
  1711. && (this.getMonth() == date.getMonth())
  1712. && (this.getDate() == date.getDate())
  1713. && (this.getHours() == date.getHours()) && (this.getMinutes() == date
  1714. .getMinutes()));
  1715. };
  1716. /** Set only the year, month, date parts (keep existing time) */
  1717. Date.prototype.setDateOnly = function(date) {
  1718. var tmp = new Date(date);
  1719. this.setDate(1);
  1720. this.setFullYear(tmp.getFullYear());
  1721. this.setMonth(tmp.getMonth());
  1722. this.setDate(tmp.getDate());
  1723. };
  1724. /** Prints the date in a string according to the given format. */
  1725. Date.prototype.print = function(str) {
  1726. var m = this.getMonth();
  1727. var d = this.getDate();
  1728. var y = this.getFullYear();
  1729. var wn = this.getWeekNumber();
  1730. var w = this.getDay();
  1731. var s = {};
  1732. var hr = this.getHours();
  1733. var pm = (hr >= 12);
  1734. var ir = (pm) ? (hr - 12) : hr;
  1735. var dy = this.getDayOfYear();
  1736. if (ir == 0)
  1737. ir = 12;
  1738. var min = this.getMinutes();
  1739. var sec = this.getSeconds();
  1740. s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N]
  1741. s["%A"] = Calendar._DN[w]; // full weekday name
  1742. s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N]
  1743. s["%B"] = Calendar._MN[m]; // full month name
  1744. // FIXME: %c : preferred date and time representation for the current locale
  1745. s["%C"] = 1 + Math.floor(y / 100); // the century number
  1746. s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
  1747. s["%e"] = d; // the day of the month (range 1 to 31)
  1748. // FIXME: %D : american date style: %m/%d/%y
  1749. // FIXME: %E, %F, %G, %g, %h (man strftime)
  1750. s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
  1751. s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
  1752. s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day
  1753. // of
  1754. // the
  1755. // year
  1756. // (range
  1757. // 001
  1758. // to
  1759. // 366)
  1760. s["%k"] = hr; // hour, range 0 to 23 (24h format)
  1761. s["%l"] = ir; // hour, range 1 to 12 (12h format)
  1762. s["%m"] = (m < 9) ? ("0" + (1 + m)) : (1 + m); // month, range 01 to 12
  1763. s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
  1764. s["%n"] = "\n"; // a newline character
  1765. s["%p"] = pm ? "PM" : "AM";
  1766. s["%P"] = pm ? "pm" : "am";
  1767. // FIXME: %r : the time in am/pm notation %I:%M:%S %p
  1768. // FIXME: %R : the time in 24-hour notation %H:%M
  1769. s["%s"] = Math.floor(this.getTime() / 1000);
  1770. s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
  1771. s["%t"] = "\t"; // a tab character
  1772. // FIXME: %T : the time in 24-hour notation (%H:%M:%S)
  1773. s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
  1774. s["%u"] = w + 1; // the day of the week (range 1 to 7, 1 = MON)
  1775. s["%w"] = w; // the day of the week (range 0 to 6, 0 = SUN)
  1776. // FIXME: %x : preferred date representation for the current locale without
  1777. // the time
  1778. // FIXME: %X : preferred time representation for the current locale without
  1779. // the date
  1780. s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to
  1781. // 99)
  1782. s["%Y"] = y; // year with the century
  1783. s["%%"] = "%"; // a literal '%' character
  1784. var re = /%./g;
  1785. if (!Calendar.is_ie5 && !Calendar.is_khtml)
  1786. return str.replace(re, function(par) {
  1787. return s[par] || par;
  1788. });
  1789. var a = str.match(re);
  1790. for (var i = 0; i < a.length; i++) {
  1791. var tmp = s[a[i]];
  1792. if (tmp) {
  1793. re = new RegExp(a[i], 'g');
  1794. str = str.replace(re, tmp);
  1795. }
  1796. }
  1797. return str;
  1798. };
  1799. Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear;
  1800. Date.prototype.setFullYear = function(y) {
  1801. var d = new Date(this);
  1802. d.__msh_oldSetFullYear(y);
  1803. if (d.getMonth() != this.getMonth())
  1804. this.setDate(28);
  1805. this.__msh_oldSetFullYear(y);
  1806. };
  1807. // END: DATE OBJECT PATCHES
  1808. // global object that remembers the calendar
  1809. window._dynarch_popupCalendar = null;