puffer 0.0.12 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,32 +5,1457 @@
5
5
  *
6
6
  * @copyright (C) 2009-2010 Nikolay Nemshilov
7
7
  */
8
- var Calendar=RightJS.Calendar=function(q,p,f){function x(a,b,c,e){if(f.Fx)if(c===undefined){c=a.options.fxName;if(e===undefined){e={duration:a.options.fxDuration,onFinish:f(a.fire).bind(a,b)};if(b==="hide")e.duration=(f.Fx.Durations[e.duration]||e.duration)/2}}if(!f.Fx||!c)a.fire(b);return a.$super(c,e)}function t(a){return(a<10?"0":"")+a}var o=f,y=f.$,D=f.$$,r=f.$w,E=f.$ext,F=f.isString,z=f.isArray,G=f.isFunction,u=f.Class,l=f.Element,A=f.Input,B=f.RegExp,C=f.Browser,s=new f.Class(f.Element,{initialize:function(a,
9
- b){this.$super("div",b);this._.innerHTML=a;this.addClass("rui-button");this.on("selectstart","stopEvent")},disable:function(){return this.addClass("rui-button-disabled")},enable:function(){return this.removeClass("rui-button-disabled")},disabled:function(){return this.hasClass("rui-button-disabled")},enabled:function(){return!this.disabled()},fire:function(){this.enabled()&&this.$super.apply(this,arguments);return this}}),n=new (function(a,b){if(!b){b=a;a="DIV"}var c=new f.Class(f.Element.Wrappers[a]||
10
- f.Element,{initialize:function(e,d){this.key=e;var g=[{"class":"rui-"+e}];this instanceof f.Input||this instanceof f.Form||g.unshift(a);this.$super.apply(this,g);if(f.isString(d))d=f.$(d);if(d instanceof f.Element){this._=d._;if("$listeners"in d)d.$listeners=d.$listeners;d={}}this.setOptions(d,this);return f.Wrapper.Cache[f.$uid(this._)]=this},setOptions:function(e,d){d=d||this;f.Options.setOptions.call(this,f.Object.merge(e,eval("("+(d.get("data-"+this.key)||"{}")+")")));return this}});c=new f.Class(c,
11
- b);f.Observer.createShortcuts(c.prototype,c.EVENTS||[]);return c})({include:[{show:function(a,b){this.constructor.current=this;return x(this,"show",a,b)},hide:function(a,b){this.constructor.current=null;return x(this,"show",a,b)},showAt:function(a,b,c){var e=this.hide(null).shownAt=a=f.$(a),d=(this.reAnchor||(this.reAnchor=new f.Element("div",{"class":"rui-re-anchor"})).insert(this)).insertTo(e,"after").position();a=e.dimensions();var g=p(e.getStyle("borderTopWidth")),h=p(e.getStyle("borderLeftWidth")),
12
- j=p(e.getStyle("borderRightWidth")),i=p(e.getStyle("borderBottomWidth"));e=a.top-d.y+g;d=a.left-d.x+h;h=a.width-h-j;a=a.height-g-i;this.setStyle("visibility:hidden").show(null);if(b==="right")d+=h-this.size().x;else e+=a;this.moveTo(d,e);if(c)b==="left"||b==="right"?this.setHeight(a):this.setWidth(h);this.setStyle("visibility:visible").hide(null);return this.show()},toggleAt:function(a,b,c){return this.hidden()?this.showAt(a,b,c):this.hide()}},{assignTo:function(a,b){a=f.$(a);if(b=f.$(b)){b[this.key]=
13
- this;b.assignedInput=a}else a[this.key]=this;var c=f(function(){if(this.visible()&&(!this.showAt||this.shownAt===a))this.setValue(a.value())}).bind(this);a.on({keyup:c,change:c});this.onChange(function(){if(!this.showAt||this.shownAt===a)a.setValue(this.getValue())});return this}}],extend:{version:"2.2.0",EVENTS:r("show hide change done"),Options:{format:"ISO",showTime:null,showButtons:false,minDate:false,maxDate:false,fxName:"fade",fxDuration:"short",firstDay:1,numberOfMonths:1,timePeriod:1,twentyFourHour:null,
14
- listYears:false,hideOnPick:false,update:null,trigger:null,cssRule:"*[data-calendar]"},Formats:{ISO:"%Y-%m-%d",POSIX:"%Y/%m/%d",EUR:"%d-%m-%Y",US:"%m/%d/%Y"},i18n:{Done:"Done",Now:"Now",NextMonth:"Next Month",PrevMonth:"Previous Month",NextYear:"Next Year",PrevYear:"Previous Year",dayNames:r("Sunday Monday Tuesday Wednesday Thursday Friday Saturday"),dayNamesShort:r("Sun Mon Tue Wed Thu Fri Sat"),dayNamesMin:r("Su Mo Tu We Th Fr Sa"),monthNames:r("January February March April May June July August September October November December"),
15
- monthNamesShort:r("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec")},current:null,hideAll:function(a){D("div.rui-calendar").each(function(b){b instanceof n&&b!==a&&b.visible()&&!b.inlined()&&b.hide()})}},initialize:function(a){this.$super("calendar",a);this.addClass("rui-panel");a=this.options;this.insert([this.swaps=new H(a),this.greed=new I(a)]);if(a.showTime)this.insert(this.timepicker=new J(a));if(a.showButtons)this.insert(this.buttons=new K(a));this.setDate(new Date).initEvents()},setDate:function(a,
16
- b){if(a=this.parse(a)){var c=this.options;if(c.minDate&&c.minDate>a)a=new Date(c.minDate);if(c.maxDate&&c.maxDate<a){a=new Date(c.maxDate);a.setDate(a.getDate()-1)}this._date=b?new Date(this._date||this.date):null;this.greed.setDate(this._date||a,a);if(c.minDate||c.maxDate)this.swaps.setDate(a);this.timepicker&&!b&&this.timepicker.setDate(a);if(a!=this.date)this.fire("change",{date:this.date=a})}return this},getDate:function(){return this.date},setValue:function(a){return this.setDate(a)},getValue:function(a){return this.format(a)},
17
- insertTo:function(a,b){this.addClass("rui-calendar-inline");return this.$super(a,b)},done:function(){this.inlined()||this.hide();this.fire("done",{date:this.date})},inlined:function(){return this.hasClass("rui-calendar-inline")},setOptions:function(a){a=a||{};this.$super(a,y(a.trigger||a.update));var b=this.constructor,c=this.options;c.i18n={};for(var e in b.i18n)c.i18n[e]=z(b.i18n[e])?b.i18n[e].clone():b.i18n[e];E(c.i18n,a.i18n);c.dayNames=c.i18n.dayNamesMin;c.firstDay&&c.dayNames.push(c.dayNames.shift());
18
- if(!z(c.numberOfMonths))c.numberOfMonths=[c.numberOfMonths,1];if(c.minDate)c.minDate=this.parse(c.minDate);if(c.maxDate){c.maxDate=this.parse(c.maxDate);c.maxDate.setDate(c.maxDate.getDate()+1)}c.format=o(b.Formats[c.format]||c.format).trim();if(c.showTime===null)c.showTime=c.format.search(/%[HkIl]/)>-1;if(c.twentyFourHour===null)c.twentyFourHour=c.format.search(/%[Il]/)<0;if(c.timePeriod>60&&12%Math.ceil(c.timePeriod/60))c.twentyFourHour=true;c.update&&this.assignTo(c.update,c.trigger);return this},
19
- hideOthers:function(){n.hideAll(this);return this}}),H=new u(l,{initialize:function(a){this.$super("div",{"class":"swaps"});this.options=a;var b=a.i18n;this.insert([this.prevMonth=new s("&lsaquo;",{title:b.PrevMonth,"class":"prev-month"}),this.nextMonth=new s("&rsaquo;",{title:b.NextMonth,"class":"next-month"})]);if(a.listYears)this.insert([this.prevYear=new s("&laquo;",{title:b.PrevYear,"class":"prev-year"}),this.nextYear=new s("&raquo;",{title:b.NextYear,"class":"next-year"})]);this.buttons=o([this.prevMonth,
20
- this.nextMonth,this.prevYear,this.nextYear]).compact();this.onClick(this.clicked)},setDate:function(a){var b=this.options,c=b.numberOfMonths[0]*b.numberOfMonths[1],e=true,d=true,g=true,h=true;if(b.minDate){g=new Date(a.getFullYear(),0,1,0,0,0);var j=new Date(b.minDate.getFullYear(),0,1,0,0,0);e=g>j;g.setMonth(a.getMonth()-Math.ceil(c-c/2));j.setMonth(b.minDate.getMonth());g=g>=j}if(b.maxDate){a=new Date(a);b=new Date(b.maxDate);c=o([a,b]);c.each(function(i){i.setDate(32);i.setMonth(i.getMonth()-1);
21
- i.setDate(32-i.getDate());i.setHours(0);i.setMinutes(0);i.setSeconds(0);i.setMilliseconds(0)});h=a<b;c.each("setMonth",0);d=a<b}this.nextMonth[h?"enable":"disable"]();this.prevMonth[g?"enable":"disable"]();if(this.nextYear){this.nextYear[d?"enable":"disable"]();this.prevYear[e?"enable":"disable"]()}},clicked:function(a){(a=a.target)&&this.buttons.include(a)&&a.enabled()&&this.fire(a.get("className").split(/\s+/)[0])}}),L=new u(l,{initialize:function(a){this.$super("table",{"class":"month"});this.options=
22
- a;this.insert(this.caption=new l("caption"));this.insert("<thead><tr>"+a.dayNames.map(function(d){return"<th>"+d+"</th>"}).join("")+"</tr></thead>");this.days=[];a=(new l("tbody")).insertTo(this);var b,c,e;for(c=0;c<6;c++){e=(new l("tr")).insertTo(a);for(b=0;b<7;b++)this.days.push((new l("td")).insertTo(e))}this.onClick(this.clicked)},setDate:function(a,b){a.setDate(32);var c=32-a.getDate();a.setMonth(a.getMonth()-1);for(var e=Math.ceil(b.getTime()/864E5),d=this.options,g=d.i18n,h=this.days,j=0,i=
23
- h.length-1,k,m,v;j<7;j++){k=h[j]._;m=h[i-j]._;v=h[i-j-7]._;k.innerHTML=m.innerHTML=v.innerHTML="";k.className=m.className=v.className="blank"}j=1;i=0;for(var w;j<=c;j++){a.setDate(j);m=a.getDay();if(d.firstDay===1)m=m>0?m-1:6;if(j===1||m===0){w=h.slice(i*7,i*7+7);i++}k=w[m]._;if(C.OLD){k.innerHTML="";k.appendChild(q.createTextNode(j))}else k.innerHTML=""+j;k.className=e===Math.ceil(a.getTime()/864E5)?"selected":"";if(d.minDate&&d.minDate>a||d.maxDate&&d.maxDate<a)k.className="disabled";w[m].date=
24
- new Date(a)}c=(d.listYears?g.monthNamesShort[a.getMonth()]+",":g.monthNames[a.getMonth()])+" "+a.getFullYear();e=this.caption._;if(C.OLD){e.innerHTML="";e.appendChild(q.createTextNode(c))}else e.innerHTML=c},clicked:function(a){a=a.target;var b=a.date;if(a&&b&&!a.hasClass("disabled")&&!a.hasClass("blank")){a.addClass("selected");this.fire("date-set",{date:b.getDate(),month:b.getMonth(),year:b.getFullYear()})}}}),I=new u(l,{initialize:function(a){this.$super("table",{"class":"greed"});this.months=
25
- [];for(var b=(new l("tbody")).insertTo(this),c,e=0;e<a.numberOfMonths[1];e++)for(var d=(new l("tr")).insertTo(b),g=0;g<a.numberOfMonths[0];g++){this.months.push(c=new L(a));(new l("td")).insertTo(d).insert(c)}},setDate:function(a,b){var c=this.months,e=c.length;b=b||a;for(var d=-Math.ceil(e-e/2)+1,g=0;d<Math.floor(e-e/2)+1;d++,g++){var h=new Date(a);h.setMonth(a.getMonth()+d);c[g].setDate(h,b)}}}),J=new u(l,{initialize:function(a){this.$super("div",{"class":"timepicker"});this.options=a;var b=o(this.timeChanged).bind(this);
26
- this.insert([this.hours=(new l("select")).onChange(b),this.minutes=(new l("select")).onChange(b)]);for(var c=a.timePeriod<60?a.timePeriod:60,e=a.timePeriod<60?1:Math.ceil(a.timePeriod/60),d=0;d<60;d++){var g=t(d);if(d<24&&d%e==0)if(a.twentyFourHour)this.hours.insert(new l("option",{value:d,html:g}));else if(d<12)this.hours.insert(new l("option",{value:d,html:d==0?12:d}));d%c==0&&this.minutes.insert(new l("option",{value:d,html:g}))}if(!a.twentyFourHour){this.meridian=(new l("select")).onChange(b).insertTo(this);
27
- o(o(a.format).includes(/%P/)?["am","pm"]:["AM","PM"]).each(function(h){this.meridian.insert(new l("option",{value:h.toLowerCase(),html:h}))},this)}},setDate:function(a){var b=this.options,c=b.timePeriod<60?a.getHours():Math.round(a.getHours()/(b.timePeriod/60))*(b.timePeriod/60);a=Math.round(a.getMinutes()/(b.timePeriod%60))*b.timePeriod;if(this.meridian){this.meridian.setValue(c<12?"am":"pm");c=c==0||c==12?12:c>12?c-12:c}this.hours.setValue(c);this.minutes.setValue(a)},timeChanged:function(a){a.stopPropagation();
28
- a=p(this.hours.value());var b=p(this.minutes.value());if(this.meridian){if(a==12)a=0;if(this.meridian.value()=="pm")a+=12}this.fire("time-set",{hours:a,minutes:b})}}),K=new u(l,{initialize:function(a){this.$super("div",{"class":"buttons"});this.insert([(new s(a.i18n.Now,{"class":"now"})).onClick("fire","now-clicked"),(new s(a.i18n.Done,{"class":"done"})).onClick("fire","done-clicked")])}});n.include({parse:function(a){var b;if(F(a)&&a){var c=B.escape(this.options.format),e=o(c.match(/%[a-z]/ig)).map("match",
29
- /[a-z]$/i).map("first").without("%");c=new B("^"+c.replace(/%p/i,"(pm|PM|am|AM)").replace(/(%[a-z])/ig,"(.+?)")+"$");if(a=o(a).trim().match(c)){a.shift();for(var d=c=null,g=null,h=null,j=null,i;a.length;){var k=a.shift(),m=e.shift();if(m.toLowerCase()=="b")d=this.options.i18n[m=="b"?"monthNamesShort":"monthNames"].indexOf(k);else if(m.toLowerCase()=="p")i=k.toLowerCase();else{k=p(k,10);switch(m){case "d":case "e":b=k;break;case "m":d=k-1;break;case "y":case "Y":c=k;break;case "H":case "k":case "I":case "l":g=
30
- k;break;case "M":h=k;break;case "S":j=k;break}}}if(i){g=g==12?0:g;g=i=="pm"?g+12:g}b=new Date(c,d,b,g,h,j)}}else if(a instanceof Date||Date.parse(a))b=new Date(a);return!b||isNaN(b.getTime())?null:b},format:function(a){var b=this.options.i18n,c=this.date.getDay(),e=this.date.getMonth(),d=this.date.getDate(),g=this.date.getFullYear(),h=this.date.getHours(),j=this.date.getMinutes(),i=this.date.getSeconds(),k=h==0?12:h<13?h:h-12;b={a:b.dayNamesShort[c],A:b.dayNames[c],b:b.monthNamesShort[e],B:b.monthNames[e],
31
- d:t(d),e:""+d,m:(e<9?"0":"")+(e+1),y:(""+g).substring(2,4),Y:""+g,H:t(h),k:""+h,I:(h>0&&(h<10||h>12&&h<22)?"0":"")+k,l:""+k,p:h<12?"AM":"PM",P:h<12?"am":"pm",M:t(j),S:t(i),"%":"%"};a=a||this.options.format;for(var m in b)a=a.replace("%"+m,b[m]);return a}});n.include({initEvents:function(){var a=this._terminate;this.on({"prev-day":["_shiftDate",{Date:-1}],"next-day":["_shiftDate",{Date:1}],"prev-week":["_shiftDate",{Date:-7}],"next-week":["_shiftDate",{Date:7}],"prev-month":["_shiftDate",{Month:-1}],
32
- "next-month":["_shiftDate",{Month:1}],"prev-year":["_shiftDate",{FullYear:-1}],"next-year":["_shiftDate",{FullYear:1}],"date-set":this._changeDate,"time-set":this._changeTime,"now-clicked":this._setNow,"done-clicked":this.done,click:a,mousedown:a,focus:a,blur:a})},_shiftDate:function(a){var b=new Date(this.date);for(var c in a)b["set"+c](b["get"+c]()+a[c]);this.setDate(b)},_changeDate:function(a){var b=new Date(this.date);b.setDate(a.date);b.setMonth(a.month);b.setFullYear(a.year);this.setDate(b,
33
- true);this.options.hideOnPick&&this.done()},_changeTime:function(a){var b=new Date(this.date);b.setHours(a.hours);b.setMinutes(a.minutes);this.setDate(b)},_setNow:function(){this.setDate(new Date)},_terminate:function(a){a.stopPropagation();if(this._hide_delay){this._hide_delay.cancel();this._hide_delay=null}}});y(q).on({focus:function(a){a=a.target instanceof A&&a.target.get("type")=="text"?a.target:null;n.hideAll();if(a&&(a.calendar||a.match(n.Options.cssRule)))(a.calendar||new n({update:a})).setValue(a.value()).showAt(a)},
34
- blur:function(a){var b=a.target.calendar;if(b)b._hide_delay=o(function(){b.hide()}).delay(200)},click:function(a){var b=a.target instanceof l?a.target:null;if(b&&(b.calendar||b.match(n.Options.cssRule))){if(!(b instanceof A)||b.get("type")!="text"){a.stop();(b.calendar||new n({trigger:b})).hide(null).toggleAt(b.assignedInput)}}else a.find("div.rui-calendar")||n.hideAll()},keydown:function(a){var b=n.current,c={27:"hide",37:"prev-day",39:"next-day",38:"prev-week",40:"next-week",33:"prev-month",34:"next-month",
35
- 13:"done"}[a.keyCode];if(c&&b&&b.visible()){a.stop();G(b[c])?b[c]():b.fire(c)}}});(function(){var a=q.createElement("style"),b=q.createTextNode(".rui-panel{margin:0;padding:.5em;position:relative;background-color:#EEE;border:1px solid #BBB;border-radius:.3em;-moz-border-radius:.3em;-webkit-border-radius:.3em;box-shadow:.15em .3em .5em #BBB;-moz-box-shadow:.15em .3em .5em #BBB;-webkit-box-shadow:.15em .3em .5em #BBB;cursor:default} *.rui-button{display:inline-block; *display:inline; *zoom:1;height:1em;line-height:1em;margin:0;padding:.2em .5em;text-align:center;border:1px solid #CCC;border-radius:.2em;-moz-border-radius:.2em;-webkit-border-radius:.2em;cursor:pointer;color:#333;background-color:#FFF;user-select:none;-moz-user-select:none;-webkit-user-select:none} *.rui-button:hover{color:#111;border-color:#999;background-color:#DDD;box-shadow:#888 0 0 .1em;-moz-box-shadow:#888 0 0 .1em;-webkit-box-shadow:#888 0 0 .1em} *.rui-button:active{color:#000;border-color:#777;text-indent:1px;box-shadow:none;-moz-box-shadow:none;-webkit-box-shadow:none} *.rui-button-disabled, *.rui-button-disabled:hover, *.rui-button-disabled:active{color:#888;background:#DDD;border-color:#CCC;cursor:default;text-indent:0;box-shadow:none;-moz-box-shadow:none;-webkit-box-shadow:none}div.rui-re-anchor{margin:0;padding:0;background:none;border:none;float:none;display:inline;position:absolute;z-index:9999}div.rui-calendar .swaps,div.rui-calendar .greed,div.rui-calendar .timepicker,div.rui-calendar .buttons,div.rui-calendar table,div.rui-calendar table tr,div.rui-calendar table th,div.rui-calendar table td,div.rui-calendar table tbody,div.rui-calendar table thead,div.rui-calendar table caption{background:none;border:none;width:auto;height:auto;margin:0;padding:0}div.rui-calendar-inline{position:relative;display:inline-block; *display:inline; *zoom:1;box-shadow:none;-moz-box-shadow:none;-webkit-box-shadow:none}div.rui-calendar .swaps{position:relative}div.rui-calendar .swaps .rui-button{position:absolute;float:left;width:1em;padding:.15em .4em}div.rui-calendar .swaps .next-month{right:0em;_right:.5em}div.rui-calendar .swaps .prev-year{left:2.05em}div.rui-calendar .swaps .next-year{right:2.05em;_right:2.52em}div.rui-calendar .greed{border-spacing:0px;border-collapse:collapse;border-size:0}div.rui-calendar .greed td{vertical-align:top;padding-left:.4em}div.rui-calendar .greed>tbody>tr>td:first-child{padding:0}div.rui-calendar .month{margin-top:.2em;border-spacing:1px;border-collapse:separate}div.rui-calendar .month caption{text-align:center}div.rui-calendar .month th{color:#666;text-align:center}div.rui-calendar .month td{text-align:right;padding:.1em .3em;background-color:#FFF;border:1px solid #CCC;cursor:pointer;color:#555;border-radius:.2em;-moz-border-radius:.2em;-webkit-border-radius:.2em}div.rui-calendar .month td:hover{background-color:#CCC;border-color:#AAA;color:#000}div.rui-calendar .month td.blank{background:transparent;cursor:default;border:none}div.rui-calendar .month td.selected{background-color:#BBB;border-color:#AAA;color:#222;font-weight:bold;padding:.1em .2em}div.rui-calendar .month td.disabled{color:#888;background:#EEE;border-color:#CCC;cursor:default}div.rui-calendar .timepicker{border-top:1px solid #ccc;margin-top:.3em;padding-top:.5em;text-align:center}div.rui-calendar .timepicker select{margin:0 .4em}div.rui-calendar .buttons{position:relative;margin-top:.5em}div.rui-calendar .buttons div.rui-button{width:4em;padding:.25em .5em}div.rui-calendar .buttons .done{position:absolute;right:0em;top:0}");
36
- a.type="text/css";if(a.styleSheet)a.styleSheet.cssText=b.nodeValue;else a.appendChild(b);q.getElementsByTagName("head")[0].appendChild(a)})();return n}(document,parseInt,RightJS);
8
+ var Calendar = RightJS.Calendar = (function(document, parseInt, RightJS) {
9
+ /**
10
+ * This module defines the basic widgets constructor
11
+ * it creates an abstract proxy with the common functionality
12
+ * which then we reuse and override in the actual widgets
13
+ *
14
+ * Copyright (C) 2010-2011 Nikolay Nemshilov
15
+ */
16
+
17
+ /**
18
+ * The filenames to include
19
+ *
20
+ * Copyright (C) 2010-2011 Nikolay Nemshilov
21
+ */
22
+
23
+ var R = RightJS,
24
+ $ = RightJS.$,
25
+ $$ = RightJS.$$,
26
+ $w = RightJS.$w,
27
+ $ext = RightJS.$ext,
28
+ $uid = RightJS.$uid,
29
+ isString = RightJS.isString,
30
+ isArray = RightJS.isArray,
31
+ isFunction = RightJS.isFunction,
32
+ Class = RightJS.Class,
33
+ Element = RightJS.Element,
34
+ Input = RightJS.Input,
35
+ RegExp = RightJS.RegExp,
36
+ Browser = RightJS.Browser;
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+ /**
47
+ * The widget units constructor
48
+ *
49
+ * @param String tag-name or Object methods
50
+ * @param Object methods
51
+ * @return Widget wrapper
52
+ */
53
+ function Widget(tag_name, methods) {
54
+ if (!methods) {
55
+ methods = tag_name;
56
+ tag_name = 'DIV';
57
+ }
58
+
59
+ /**
60
+ * An Abstract Widget Unit
61
+ *
62
+ * Copyright (C) 2010 Nikolay Nemshilov
63
+ */
64
+ var AbstractWidget = new RightJS.Class(RightJS.Element.Wrappers[tag_name] || RightJS.Element, {
65
+ /**
66
+ * The common constructor
67
+ *
68
+ * @param Object options
69
+ * @param String optional tag name
70
+ * @return void
71
+ */
72
+ initialize: function(key, options) {
73
+ this.key = key;
74
+ var args = [{'class': 'rui-' + key}];
75
+
76
+ // those two have different constructors
77
+ if (!(this instanceof RightJS.Input || this instanceof RightJS.Form)) {
78
+ args.unshift(tag_name);
79
+ }
80
+ this.$super.apply(this, args);
81
+
82
+ if (RightJS.isString(options)) {
83
+ options = RightJS.$(options);
84
+ }
85
+
86
+ // if the options is another element then
87
+ // try to dynamically rewrap it with our widget
88
+ if (options instanceof RightJS.Element) {
89
+ this._ = options._;
90
+ if ('$listeners' in options) {
91
+ options.$listeners = options.$listeners;
92
+ }
93
+ options = {};
94
+ }
95
+ this.setOptions(options, this);
96
+
97
+ return (RightJS.Wrapper.Cache[RightJS.$uid(this._)] = this);
98
+ },
99
+
100
+ // protected
101
+
102
+ /**
103
+ * Catches the options
104
+ *
105
+ * @param Object user-options
106
+ * @param Element element with contextual options
107
+ * @return void
108
+ */
109
+ setOptions: function(options, element) {
110
+ element = element || this;
111
+ RightJS.Options.setOptions.call(this,
112
+ RightJS.Object.merge(options, eval("("+(
113
+ element.get('data-'+ this.key) || '{}'
114
+ )+")"))
115
+ );
116
+ return this;
117
+ }
118
+ });
119
+
120
+ /**
121
+ * Creating the actual widget class
122
+ *
123
+ */
124
+ var Klass = new RightJS.Class(AbstractWidget, methods);
125
+
126
+ // creating the widget related shortcuts
127
+ RightJS.Observer.createShortcuts(Klass.prototype, Klass.EVENTS || []);
128
+
129
+ return Klass;
130
+ }
131
+
132
+
133
+ /**
134
+ * A shared button unit.
135
+ * NOTE: we use the DIV units instead of INPUTS
136
+ * so those buttons didn't interfere with
137
+ * the user's tab-index on his page
138
+ *
139
+ * Copyright (C) 2010-2011 Nikolay Nemshilov
140
+ */
141
+ var Button = new RightJS.Class(RightJS.Element, {
142
+ /**
143
+ * Constructor
144
+ *
145
+ * @param String caption
146
+ * @param Object options
147
+ * @return void
148
+ */
149
+ initialize: function(caption, options) {
150
+ this.$super('div', options);
151
+ this._.innerHTML = caption;
152
+ this.addClass('rui-button');
153
+ this.on('selectstart', 'stopEvent');
154
+ },
155
+
156
+ /**
157
+ * Disasbles the button
158
+ *
159
+ * @return Button this
160
+ */
161
+ disable: function() {
162
+ return this.addClass('rui-button-disabled');
163
+ },
164
+
165
+ /**
166
+ * Enables the button
167
+ *
168
+ * @return Button this
169
+ */
170
+ enable: function() {
171
+ return this.removeClass('rui-button-disabled');
172
+ },
173
+
174
+ /**
175
+ * Checks if the button is disabled
176
+ *
177
+ * @return Button this
178
+ */
179
+ disabled: function() {
180
+ return this.hasClass('rui-button-disabled');
181
+ },
182
+
183
+ /**
184
+ * Checks if the button is enabled
185
+ *
186
+ * @return Button this
187
+ */
188
+ enabled: function() {
189
+ return !this.disabled();
190
+ },
191
+
192
+ /**
193
+ * Overloading the method, so it fired the events
194
+ * only when the button is active
195
+ *
196
+ * @return Button this
197
+ */
198
+ fire: function() {
199
+ if (this.enabled()) {
200
+ this.$super.apply(this, arguments);
201
+ }
202
+ return this;
203
+ }
204
+ });
205
+
206
+
207
+ /**
208
+ * A shared module that toggles a widget visibility status
209
+ * in a uniformed way according to the options settings
210
+ *
211
+ * Copyright (C) 2010-2011 Nikolay Nemshilov
212
+ */
213
+ var Toggler = {
214
+ /**
215
+ * Shows the element
216
+ *
217
+ * @param String fx-name
218
+ * @param Object fx-options
219
+ * @return Element this
220
+ */
221
+ show: function(fx_name, fx_options) {
222
+ this.constructor.current = this;
223
+ return Toggler_toggle(this, 'show', fx_name, fx_options);
224
+ },
225
+
226
+ /**
227
+ * Hides the element
228
+ *
229
+ * @param String fx-name
230
+ * @param Object fx-options
231
+ * @return Element this
232
+ */
233
+ hide: function(fx_name, fx_options) {
234
+ this.constructor.current = null;
235
+ return Toggler_toggle(this, 'show', fx_name, fx_options);
236
+ },
237
+
238
+ /**
239
+ * Toggles the widget at the given element
240
+ *
241
+ * @param Element the related element
242
+ * @param String position right/bottom (bottom is the default)
243
+ * @param Boolean marker if the element should be resized to the element size
244
+ * @return Widget this
245
+ */
246
+ showAt: function(element, where, resize) {
247
+ this.hide(null).shownAt = element = RightJS.$(element);
248
+
249
+ // moves this element at the given one
250
+ Toggler_re_position.call(this, element, where, resize);
251
+
252
+ return this.show();
253
+ },
254
+
255
+ /**
256
+ * Toggles the widget at the given element
257
+ *
258
+ * @param Element the related element
259
+ * @param String position top/left/right/bottom (bottom is the default)
260
+ * @param Boolean marker if the element should be resized to the element size
261
+ * @return Widget this
262
+ */
263
+ toggleAt: function(element, where, resize) {
264
+ return this.hidden() ? this.showAt(element, where, resize) : this.hide();
265
+ }
266
+ };
267
+
268
+
269
+ /**
270
+ * toggles the element's state according to the current settings
271
+ *
272
+ * @param event String 'show' or 'hide' the event name
273
+ * @param String an optional fx-name
274
+ * @param Object an optional fx-options hash
275
+ * @return void
276
+ */
277
+ function Toggler_toggle(element, event, fx_name, fx_options) {
278
+ if (RightJS.Fx) {
279
+ if (fx_name === undefined) {
280
+ fx_name = element.options.fxName;
281
+
282
+ if (fx_options === undefined) {
283
+ fx_options = {
284
+ duration: element.options.fxDuration,
285
+ onFinish: RightJS(element.fire).bind(element, event)
286
+ };
287
+
288
+ // hide on double time
289
+ if (event === 'hide') {
290
+ fx_options.duration = (RightJS.Fx.Durations[fx_options.duration] ||
291
+ fx_options.duration) / 2;
292
+ }
293
+ }
294
+ }
295
+ }
296
+
297
+ // manually trigger the event if no fx were specified
298
+ if (!RightJS.Fx || !fx_name) { element.fire(event); }
299
+
300
+ return element.$super(fx_name, fx_options);
301
+ }
302
+
303
+ /**
304
+ * Relatively positions the current element
305
+ * against the specified one
306
+ *
307
+ * NOTE: this function is called in a context
308
+ * of another element
309
+ *
310
+ * @param Element the target element
311
+ * @param String position 'right' or 'bottom'
312
+ * @param Boolean if `true` then the element size will be adjusted
313
+ * @return void
314
+ */
315
+ function Toggler_re_position(element, where, resize) {
316
+ var anchor = this.reAnchor || (this.reAnchor =
317
+ new RightJS.Element('div', {'class': 'rui-re-anchor'}))
318
+ .insert(this),
319
+
320
+ pos = anchor.insertTo(element, 'after').position(),
321
+ dims = element.dimensions(), target = this,
322
+
323
+ border_top = parseInt(element.getStyle('borderTopWidth')),
324
+ border_left = parseInt(element.getStyle('borderLeftWidth')),
325
+ border_right = parseInt(element.getStyle('borderRightWidth')),
326
+ border_bottom = parseInt(element.getStyle('borderBottomWidth')),
327
+
328
+ top = dims.top - pos.y + border_top,
329
+ left = dims.left - pos.x + border_left,
330
+ width = dims.width - border_left - border_right,
331
+ height = dims.height - border_top - border_bottom;
332
+
333
+ // making the element to appear so we could read it's sizes
334
+ target.setStyle('visibility:hidden').show(null);
335
+
336
+ if (where === 'right') {
337
+ left += width - target.size().x;
338
+ } else { // bottom
339
+ top += height;
340
+ }
341
+
342
+ target.moveTo(left, top);
343
+
344
+ if (resize) {
345
+ if (where === 'left' || where === 'right') {
346
+ target.setHeight(height);
347
+ } else {
348
+ target.setWidth(width);
349
+ }
350
+ }
351
+
352
+ // rolling the invisibility back
353
+ target.setStyle('visibility:visible').hide(null);
354
+ }
355
+
356
+ /**
357
+ * A shared module that provides for the widgets an ability
358
+ * to be assigned to an input element and work in pair with it
359
+ *
360
+ * NOTE: this module works in pair with the 'RePosition' module!
361
+ *
362
+ * Copyright (C) 2010 Nikolay Nemshilov
363
+ */
364
+ var Assignable = {
365
+ /**
366
+ * Assigns the widget to serve the given input element
367
+ *
368
+ * Basically it puts the references of the current widget
369
+ * to the input and trigger objects so they could be recognized
370
+ * later, and it also synchronizes the changes between the input
371
+ * element and the widget
372
+ *
373
+ * @param {Element} input field
374
+ * @param {Element} optional trigger
375
+ * @return Widget this
376
+ */
377
+ assignTo: function(input, trigger) {
378
+ input = RightJS.$(input);
379
+ trigger = RightJS.$(trigger);
380
+
381
+ if (trigger) {
382
+ trigger[this.key] = this;
383
+ trigger.assignedInput = input;
384
+ } else {
385
+ input[this.key] = this;
386
+ }
387
+
388
+ var on_change = RightJS(function() {
389
+ if (this.visible() && (!this.showAt || this.shownAt === input)) {
390
+ this.setValue(input.value());
391
+ }
392
+ }).bind(this);
393
+
394
+ input.on({
395
+ keyup: on_change,
396
+ change: on_change
397
+ });
398
+
399
+ this.onChange(function() {
400
+ if (!this.showAt || this.shownAt === input) {
401
+ input.setValue(this.getValue());
402
+ }
403
+ });
404
+
405
+ return this;
406
+ }
407
+ };
408
+
409
+
410
+ /**
411
+ * Converts a number into a string with leading zeros
412
+ *
413
+ * @param Number number
414
+ * @return String with zeros
415
+ */
416
+ function zerofy(number) {
417
+ return (number < 10 ? '0' : '') + number;
418
+ }
419
+
420
+
421
+ /**
422
+ * The calendar widget for RightJS
423
+ *
424
+ * Copyright (C) 2009-2011 Nikolay Nemshilov
425
+ */
426
+ var Calendar = new Widget({
427
+ include: [Toggler, Assignable],
428
+
429
+ extend: {
430
+ version: '2.2.0',
431
+
432
+ EVENTS: $w('show hide change done'),
433
+
434
+ Options: {
435
+ format: 'ISO', // a key out of the predefined formats or a format string
436
+
437
+ showTime: null, // null for automatic, or true|false to enforce
438
+ showButtons: false, // show the bottom buttons
439
+
440
+ minDate: false, // the minimal date available
441
+ maxDate: false, // the maximal date available
442
+
443
+ fxName: 'fade', // set to null if you don't wanna any fx
444
+ fxDuration: 'short', // the fx-duration
445
+
446
+ firstDay: 1, // 1 for Monday, 0 for Sunday
447
+ numberOfMonths: 1, // a number or [x, y] greed definition
448
+ timePeriod: 1, // the timepicker minimal periods (in minutes, might be bigger than 60)
449
+
450
+ twentyFourHour: null, // null for automatic, or true|false to enforce
451
+ listYears: false, // show/hide the years listing buttons
452
+
453
+ hideOnPick: false, // hides the popup when the user changes a day
454
+
455
+ update: null, // a reference to an input element to assign to
456
+ trigger: null, // a reference to a trigger element that would be paired too
457
+
458
+ cssRule: '*[data-calendar]' // css rule for calendar related elements
459
+ },
460
+
461
+ Formats: {
462
+ ISO: '%Y-%m-%d',
463
+ POSIX: '%Y/%m/%d',
464
+ EUR: '%d-%m-%Y',
465
+ US: '%m/%d/%Y'
466
+ },
467
+
468
+ i18n: {
469
+ Done: 'Done',
470
+ Now: 'Now',
471
+ NextMonth: 'Next Month',
472
+ PrevMonth: 'Previous Month',
473
+ NextYear: 'Next Year',
474
+ PrevYear: 'Previous Year',
475
+
476
+ dayNames: $w('Sunday Monday Tuesday Wednesday Thursday Friday Saturday'),
477
+ dayNamesShort: $w('Sun Mon Tue Wed Thu Fri Sat'),
478
+ dayNamesMin: $w('Su Mo Tu We Th Fr Sa'),
479
+ monthNames: $w('January February March April May June July August September October November December'),
480
+ monthNamesShort: $w('Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec')
481
+ },
482
+
483
+ current: null,
484
+
485
+ // hides all the popup calendars
486
+ hideAll: function(that_one) {
487
+ $$('div.rui-calendar').each(function(element) {
488
+ if (element instanceof Calendar && element !== that_one && element.visible() && !element.inlined()) {
489
+ element.hide();
490
+ }
491
+ });
492
+ }
493
+ },
494
+
495
+ /**
496
+ * Basic constructor
497
+ *
498
+ * @param Object options
499
+ */
500
+ initialize: function(options) {
501
+ this.$super('calendar', options);
502
+ this.addClass('rui-panel');
503
+
504
+ options = this.options;
505
+
506
+ this.insert([
507
+ this.swaps = new Swaps(options),
508
+ this.greed = new Greed(options)
509
+ ]);
510
+
511
+ if (options.showTime) {
512
+ this.insert(this.timepicker = new Timepicker(options));
513
+ }
514
+
515
+ if (options.showButtons) {
516
+ this.insert(this.buttons = new Buttons(options));
517
+ }
518
+
519
+ this.setDate(new Date()).initEvents();
520
+ },
521
+
522
+ /**
523
+ * Sets the date on the calendar
524
+ *
525
+ * NOTE: if it's `true` then it will change the date but
526
+ * won't shift the months greed (used in the days picking)
527
+ *
528
+ * @param Date date or String date
529
+ * @param Boolean no-shifting mode
530
+ * @return Calendar this
531
+ */
532
+ setDate: function(date, no_shift) {
533
+ if ((date = this.parse(date))) {
534
+ var options = this.options;
535
+
536
+ // checking the date range constrains
537
+ if (options.minDate && options.minDate > date) {
538
+ date = new Date(options.minDate);
539
+ }
540
+ if (options.maxDate && options.maxDate < date) {
541
+ date = new Date(options.maxDate);
542
+ date.setDate(date.getDate() - 1);
543
+ }
544
+
545
+ // setting the dates greed
546
+ this._date = no_shift ? new Date(this._date || this.date) : null;
547
+ this.greed.setDate(this._date || date, date);
548
+
549
+ // updating the shifters state
550
+ if (options.minDate || options.maxDate) {
551
+ this.swaps.setDate(date);
552
+ }
553
+
554
+ // updating the time-picker
555
+ if (this.timepicker && !no_shift) {
556
+ this.timepicker.setDate(date);
557
+ }
558
+
559
+ if (date != this.date) {
560
+ this.fire('change', {date: this.date = date});
561
+ }
562
+ }
563
+
564
+ return this;
565
+ },
566
+
567
+ /**
568
+ * Returns the current date on the calendar
569
+ *
570
+ * @return Date currently selected date on the calendar
571
+ */
572
+ getDate: function() {
573
+ return this.date;
574
+ },
575
+
576
+ /**
577
+ * Sets the value as a string
578
+ *
579
+ * @param String value
580
+ * @return Calendar this
581
+ */
582
+ setValue: function(value) {
583
+ return this.setDate(value);
584
+ },
585
+
586
+ /**
587
+ * Returns the value as a string
588
+ *
589
+ * @param String optional format
590
+ * @return String formatted date
591
+ */
592
+ getValue: function(format) {
593
+ return this.format(format);
594
+ },
595
+
596
+ /**
597
+ * Inserts the calendar into the element making it inlined
598
+ *
599
+ * @param Element element or String element id
600
+ * @param String optional position top/bottom/before/after/instead, 'bottom' is default
601
+ * @return Calendar this
602
+ */
603
+ insertTo: function(element, position) {
604
+ this.addClass('rui-calendar-inline');
605
+ return this.$super(element, position);
606
+ },
607
+
608
+ /**
609
+ * Marks it done
610
+ *
611
+ * @return Calendar this
612
+ */
613
+ done: function() {
614
+ if (!this.inlined()) {
615
+ this.hide();
616
+ }
617
+
618
+ this.fire('done', {date: this.date});
619
+ },
620
+
621
+ /**
622
+ * Checks if the calendar is inlined
623
+ *
624
+ * @return boolean check
625
+ */
626
+ inlined: function() {
627
+ return this.hasClass('rui-calendar-inline');
628
+ },
629
+
630
+ // protected
631
+
632
+ /**
633
+ * additional options processing
634
+ *
635
+ * @param Object options
636
+ * @return Calendar this
637
+ */
638
+ setOptions: function(user_options) {
639
+ user_options = user_options || {};
640
+ this.$super(user_options, $(user_options.trigger || user_options.update));
641
+
642
+ var klass = this.constructor, options = this.options;
643
+
644
+ // merging the i18n tables
645
+ options.i18n = {};
646
+
647
+ for (var key in klass.i18n) {
648
+ options.i18n[key] = isArray(klass.i18n[key]) ? klass.i18n[key].clone() : klass.i18n[key];
649
+ }
650
+ $ext(options.i18n, user_options.i18n);
651
+
652
+ // defining the current days sequence
653
+ options.dayNames = options.i18n.dayNamesMin;
654
+ if (options.firstDay) {
655
+ options.dayNames.push(options.dayNames.shift());
656
+ }
657
+
658
+ // the monthes table cleaning up
659
+ if (!isArray(options.numberOfMonths)) {
660
+ options.numberOfMonths = [options.numberOfMonths, 1];
661
+ }
662
+
663
+ // min/max dates preprocessing
664
+ if (options.minDate) {
665
+ options.minDate = this.parse(options.minDate);
666
+ }
667
+ if (options.maxDate) {
668
+ options.maxDate = this.parse(options.maxDate);
669
+ options.maxDate.setDate(options.maxDate.getDate() + 1);
670
+ }
671
+
672
+ // format catching up
673
+ options.format = R(klass.Formats[options.format] || options.format).trim();
674
+
675
+ // setting up the showTime option
676
+ if (options.showTime === null) {
677
+ options.showTime = options.format.search(/%[HkIl]/) > -1;
678
+ }
679
+
680
+ // setting up the 24-hours format
681
+ if (options.twentyFourHour === null) {
682
+ options.twentyFourHour = options.format.search(/%[Il]/) < 0;
683
+ }
684
+
685
+ // enforcing the 24 hours format if the time threshold is some weird number
686
+ if (options.timePeriod > 60 && 12 % Math.ceil(options.timePeriod/60)) {
687
+ options.twentyFourHour = true;
688
+ }
689
+
690
+ if (options.update) {
691
+ this.assignTo(options.update, options.trigger);
692
+ }
693
+
694
+ return this;
695
+ },
696
+
697
+ /**
698
+ * hides all the other calendars on the page
699
+ *
700
+ * @return Calendar this
701
+ */
702
+ hideOthers: function() {
703
+ Calendar.hideAll(this);
704
+ return this;
705
+ }
706
+ });
707
+
708
+
709
+ /**
710
+ * The calendar month/year swapping buttons block
711
+ *
712
+ * Copyright (C) 2010-2011 Nikolay Nemshilov
713
+ */
714
+ var Swaps = new Class(Element, {
715
+ /**
716
+ * Constructor
717
+ *
718
+ * @param Object options
719
+ * @return void
720
+ */
721
+ initialize: function(options) {
722
+ this.$super('div', {'class': 'swaps'});
723
+ this.options = options;
724
+
725
+ var i18n = options.i18n;
726
+
727
+ this.insert([
728
+ this.prevMonth = new Button('&lsaquo;', {title: i18n.PrevMonth, 'class': 'prev-month'}),
729
+ this.nextMonth = new Button('&rsaquo;', {title: i18n.NextMonth, 'class': 'next-month'})
730
+ ]);
731
+
732
+ if (options.listYears) {
733
+ this.insert([
734
+ this.prevYear = new Button('&laquo;', {title: i18n.PrevYear, 'class': 'prev-year'}),
735
+ this.nextYear = new Button('&raquo;', {title: i18n.NextYear, 'class': 'next-year'})
736
+ ]);
737
+ }
738
+
739
+ this.buttons = R([this.prevMonth, this.nextMonth, this.prevYear, this.nextYear]).compact();
740
+
741
+ this.onClick(this.clicked);
742
+ },
743
+
744
+ /**
745
+ * Changes the swapping buttons state depending on the options and the current date
746
+ *
747
+ * @param Date date
748
+ * @return void
749
+ */
750
+ setDate: function(date) {
751
+ var options = this.options, months_num = options.numberOfMonths[0] * options.numberOfMonths[1],
752
+ has_prev_year = true, has_next_year = true, has_prev_month = true, has_next_month = true;
753
+
754
+ if (options.minDate) {
755
+ var beginning = new Date(date.getFullYear(),0,1,0,0,0);
756
+ var min_date = new Date(options.minDate.getFullYear(),0,1,0,0,0);
757
+
758
+ has_prev_year = beginning > min_date;
759
+
760
+ beginning.setMonth(date.getMonth() - Math.ceil(months_num - months_num/2));
761
+ min_date.setMonth(options.minDate.getMonth());
762
+
763
+ has_prev_month = beginning >= min_date;
764
+ }
765
+
766
+ if (options.maxDate) {
767
+ var end = new Date(date);
768
+ var max_date = new Date(options.maxDate);
769
+ var dates = R([end, max_date]);
770
+ dates.each(function(date) {
771
+ date.setDate(32);
772
+ date.setMonth(date.getMonth() - 1);
773
+ date.setDate(32 - date.getDate());
774
+ date.setHours(0);
775
+ date.setMinutes(0);
776
+ date.setSeconds(0);
777
+ date.setMilliseconds(0);
778
+ });
779
+
780
+ has_next_month = end < max_date;
781
+
782
+ // checking the next year
783
+ dates.each('setMonth', 0);
784
+ has_next_year = end < max_date;
785
+ }
786
+
787
+ this.nextMonth[has_next_month ? 'enable':'disable']();
788
+ this.prevMonth[has_prev_month ? 'enable':'disable']();
789
+
790
+ if (this.nextYear) {
791
+ this.nextYear[has_next_year ? 'enable':'disable']();
792
+ this.prevYear[has_prev_year ? 'enable':'disable']();
793
+ }
794
+ },
795
+
796
+ // protected
797
+
798
+ // handles the clicks on the
799
+ clicked: function(event) {
800
+ var target = event.target;
801
+ if (target && this.buttons.include(target)) {
802
+ if (target.enabled()) {
803
+ this.fire(target.get('className').split(/\s+/)[0]);
804
+ }
805
+ }
806
+ }
807
+ });
808
+
809
+
810
+ /**
811
+ * Represents a single month block
812
+ *
813
+ * Copyright (C) 2010-2011 Nikolay Nemshilov
814
+ */
815
+ var Month = new Class(Element, {
816
+ /**
817
+ * Constructor
818
+ *
819
+ * @param Object options
820
+ * @return void
821
+ */
822
+ initialize: function(options) {
823
+ this.$super('table', {'class': 'month'});
824
+ this.options = options;
825
+
826
+ // the caption (for the month name)
827
+ this.insert(this.caption = new Element('caption'));
828
+
829
+ // the headline for the day-names
830
+ this.insert('<thead><tr>'+
831
+ options.dayNames.map(function(name) {return '<th>'+ name +'</th>';}).join('') +
832
+ '</tr></thead>');
833
+
834
+ // the body with the day-cells
835
+ this.days = [];
836
+
837
+ var tbody = new Element('tbody').insertTo(this), x, y, row;
838
+
839
+ for (y=0; y < 6; y++) {
840
+ row = new Element('tr').insertTo(tbody);
841
+ for (x=0; x < 7; x++) {
842
+ this.days.push(new Element('td').insertTo(row));
843
+ }
844
+ }
845
+
846
+ this.onClick(this.clicked);
847
+ },
848
+
849
+ /**
850
+ * Initializes the month values by the date
851
+ *
852
+ * @param Date date
853
+ * @return void
854
+ */
855
+ setDate: function(date, current_date) {
856
+ // getting the number of days in the month
857
+ date.setDate(32);
858
+ var days_number = 32 - date.getDate();
859
+ date.setMonth(date.getMonth()-1);
860
+
861
+ var cur_day = Math.ceil(current_date.getTime() / 86400000),
862
+ options = this.options, i18n = options.i18n, days = this.days;
863
+
864
+ // resetting the first and last two weeks cells
865
+ // because there will be some empty cells over there
866
+ for (var i=0, len = days.length-1, one, two, tre; i < 7; i++) {
867
+ one = days[i]._;
868
+ two = days[len - i]._;
869
+ tre = days[len - i - 7]._;
870
+
871
+ one.innerHTML = two.innerHTML = tre.innerHTML = '';
872
+ one.className = two.className = tre.className = 'blank';
873
+ }
874
+
875
+ // putting the actual day numbers in place
876
+ for (var i=1, row=0, week, cell; i <= days_number; i++) {
877
+ date.setDate(i);
878
+ var day_num = date.getDay();
879
+
880
+ if (options.firstDay === 1) { day_num = day_num > 0 ? day_num-1 : 6; }
881
+ if (i === 1 || day_num === 0) {
882
+ week = days.slice(row*7, row*7 + 7); row ++;
883
+ }
884
+
885
+ cell = week[day_num]._;
886
+
887
+ if (Browser.OLD) { // IE6 has a nasty glitch with that
888
+ cell.innerHTML = '';
889
+ cell.appendChild(document.createTextNode(i));
890
+ } else {
891
+ cell.innerHTML = ''+i;
892
+ }
893
+
894
+ cell.className = cur_day === Math.ceil(date.getTime() / 86400000) ? 'selected' : '';
895
+
896
+ if ((options.minDate && options.minDate > date) || (options.maxDate && options.maxDate < date)) {
897
+ cell.className = 'disabled';
898
+ }
899
+
900
+ week[day_num].date = new Date(date);
901
+ }
902
+
903
+ // setting up the caption with the month name
904
+ var caption = (options.listYears ?
905
+ i18n.monthNamesShort[date.getMonth()] + ',' :
906
+ i18n.monthNames[date.getMonth()])+
907
+ ' '+date.getFullYear(),
908
+ element = this.caption._;
909
+
910
+ if (Browser.OLD) {
911
+ element.innerHTML = '';
912
+ element.appendChild(document.createTextNode(caption));
913
+ } else {
914
+ element.innerHTML = caption;
915
+ }
916
+ },
917
+
918
+ // protected
919
+
920
+ /**
921
+ * Handles clicks on the day-cells
922
+ *
923
+ * @param Event click event
924
+ * @return void
925
+ */
926
+ clicked: function(event) {
927
+ var target = event.target, date = target.date;
928
+
929
+ if (target && date && !target.hasClass('disabled') && !target.hasClass('blank')) {
930
+ target.addClass('selected');
931
+
932
+ this.fire('date-set', {
933
+ date: date.getDate(),
934
+ month: date.getMonth(),
935
+ year: date.getFullYear()
936
+ });
937
+ }
938
+ }
939
+ });
940
+
941
+
942
+ /**
943
+ * The calendar months greed unit
944
+ *
945
+ * Copyright (C) 2010-2011 Nikolay Nemshilov
946
+ */
947
+ var Greed = new Class(Element, {
948
+ /**
949
+ * Constructor
950
+ *
951
+ * @param Object options
952
+ * @return void
953
+ */
954
+ initialize: function(options) {
955
+ this.$super('table', {'class': 'greed'});
956
+
957
+ this.months = [];
958
+
959
+ var tbody = new Element('tbody').insertTo(this), month;
960
+
961
+ for (var y=0; y < options.numberOfMonths[1]; y++) {
962
+ var row = new Element('tr').insertTo(tbody);
963
+ for (var x=0; x < options.numberOfMonths[0]; x++) {
964
+ this.months.push(month = new Month(options));
965
+ new Element('td').insertTo(row).insert(month);
966
+ }
967
+ }
968
+ },
969
+
970
+ /**
971
+ * Sets the months to the date
972
+ *
973
+ * @param Date date in the middle of the greed
974
+ * @param the current date (might be different)
975
+ * @return void
976
+ */
977
+ setDate: function(date, current_date) {
978
+ var months = this.months, months_num = months.length;
979
+
980
+ current_date = current_date || date;
981
+
982
+ for (var i=-Math.ceil(months_num - months_num/2)+1,j=0; i < Math.floor(months_num - months_num/2)+1; i++,j++) {
983
+ var month_date = new Date(date);
984
+ month_date.setMonth(date.getMonth() + i);
985
+ months[j].setDate(month_date, current_date);
986
+ }
987
+ }
988
+ });
989
+
990
+
991
+ /**
992
+ * The time-picker block unit
993
+ *
994
+ * Copyright (C) 2010-2011 Nikolay Nemshilov
995
+ */
996
+ var Timepicker = new Class(Element, {
997
+ /**
998
+ * Constructor
999
+ *
1000
+ * @param Object options
1001
+ * @return void
1002
+ */
1003
+ initialize: function(options) {
1004
+ this.$super('div', {'class': 'timepicker'});
1005
+ this.options = options;
1006
+
1007
+ var on_change = R(this.timeChanged).bind(this);
1008
+
1009
+ this.insert([
1010
+ this.hours = new Element('select').onChange(on_change),
1011
+ this.minutes = new Element('select').onChange(on_change)
1012
+ ]);
1013
+
1014
+ var minutes_threshold = options.timePeriod < 60 ? options.timePeriod : 60;
1015
+ var hours_threshold = options.timePeriod < 60 ? 1 : Math.ceil(options.timePeriod / 60);
1016
+
1017
+ for (var i=0; i < 60; i++) {
1018
+ var caption = zerofy(i);
1019
+
1020
+ if (i < 24 && i % hours_threshold == 0) {
1021
+ if (options.twentyFourHour) {
1022
+ this.hours.insert(new Element('option', {value: i, html: caption}));
1023
+ } else if (i < 12) {
1024
+ this.hours.insert(new Element('option', {value: i, html: i == 0 ? 12 : i}));
1025
+ }
1026
+ }
1027
+
1028
+ if (i % minutes_threshold == 0) {
1029
+ this.minutes.insert(new Element('option', {value: i, html: caption}));
1030
+ }
1031
+ }
1032
+
1033
+
1034
+ // adding the meridian picker if it's a 12 am|pm picker
1035
+ if (!options.twentyFourHour) {
1036
+ this.meridian = new Element('select').onChange(on_change).insertTo(this);
1037
+
1038
+ R(R(options.format).includes(/%P/) ? ['am', 'pm'] : ['AM', 'PM']).each(function(value) {
1039
+ this.meridian.insert(new Element('option', {value: value.toLowerCase(), html: value}));
1040
+ }, this);
1041
+ }
1042
+ },
1043
+
1044
+ /**
1045
+ * Sets the time-picker values by the data
1046
+ *
1047
+ * @param Date date
1048
+ * @return void
1049
+ */
1050
+ setDate: function(date) {
1051
+ var options = this.options;
1052
+ var hour = options.timePeriod < 60 ? date.getHours() :
1053
+ Math.round(date.getHours()/(options.timePeriod/60)) * (options.timePeriod/60);
1054
+ var minute = Math.round(date.getMinutes() / (options.timePeriod % 60)) * options.timePeriod;
1055
+
1056
+ if (this.meridian) {
1057
+ this.meridian.setValue(hour < 12 ? 'am' : 'pm');
1058
+ hour = (hour == 0 || hour == 12) ? 12 : hour > 12 ? (hour - 12) : hour;
1059
+ }
1060
+
1061
+ this.hours.setValue(hour);
1062
+ this.minutes.setValue(minute);
1063
+ },
1064
+
1065
+ // protected
1066
+
1067
+ /**
1068
+ * Handles the time-picking events
1069
+ *
1070
+ * @return void
1071
+ */
1072
+ timeChanged: function(event) {
1073
+ event.stopPropagation();
1074
+
1075
+ var hours = parseInt(this.hours.value());
1076
+ var minutes = parseInt(this.minutes.value());
1077
+
1078
+ if (this.meridian) {
1079
+ if (hours == 12) {
1080
+ hours = 0;
1081
+ }
1082
+ if (this.meridian.value() == 'pm') {
1083
+ hours += 12;
1084
+ }
1085
+ }
1086
+
1087
+ this.fire('time-set', {hours: hours, minutes: minutes});
1088
+ }
1089
+ });
1090
+
1091
+
1092
+ /**
1093
+ * The bottom-buttons block unit
1094
+ *
1095
+ * Copyright (C) 2010 Nikolay Nemshilov
1096
+ */
1097
+ var Buttons = new Class(Element, {
1098
+ /**
1099
+ * Constructor
1100
+ *
1101
+ * @param Object options
1102
+ * @return void
1103
+ */
1104
+ initialize: function(options) {
1105
+ this.$super('div', {'class': 'buttons'});
1106
+
1107
+ this.insert([
1108
+ new Button(options.i18n.Now, {'class': 'now'}).onClick('fire', 'now-clicked'),
1109
+ new Button(options.i18n.Done, {'class': 'done'}).onClick('fire', 'done-clicked')
1110
+ ]);
1111
+ }
1112
+ });
1113
+
1114
+
1115
+ /**
1116
+ * This module handles the dates parsing/formatting processes
1117
+ *
1118
+ * To format dates and times this scripts use the GNU (C/Python/Ruby) strftime
1119
+ * function formatting principles
1120
+ *
1121
+ * %a - The abbreviated weekday name (``Sun'')
1122
+ * %A - The full weekday name (``Sunday'')
1123
+ * %b - The abbreviated month name (``Jan'')
1124
+ * %B - The full month name (``January'')
1125
+ * %d - Day of the month (01..31)
1126
+ * %e - Day of the month without leading zero (1..31)
1127
+ * %m - Month of the year (01..12)
1128
+ * %y - Year without a century (00..99)
1129
+ * %Y - Year with century
1130
+ * %H - Hour of the day, 24-hour clock (00..23)
1131
+ * %k - Hour of the day, 24-hour clock without leading zero (0..23)
1132
+ * %I - Hour of the day, 12-hour clock (01..12)
1133
+ * %l - Hour of the day, 12-hour clock without leading zer (0..12)
1134
+ * %p - Meridian indicator (``AM'' or ``PM'')
1135
+ * %P - Meridian indicator (``pm'' or ``pm'')
1136
+ * %M - Minute of the hour (00..59)
1137
+ * %S - Second of the minute (00..60)
1138
+ * %% - Literal ``%'' character
1139
+ *
1140
+ * Copyright (C) 2009-2010 Nikolay V. Nemshilov
1141
+ */
1142
+ Calendar.include({
1143
+
1144
+ /**
1145
+ * Parses out the given string based on the current date formatting
1146
+ *
1147
+ * @param String string date
1148
+ * @return Date parsed date or null if it wasn't parsed
1149
+ */
1150
+ parse: function(string) {
1151
+ var date;
1152
+
1153
+ if (isString(string) && string) {
1154
+ var tpl = RegExp.escape(this.options.format);
1155
+ var holders = R(tpl.match(/%[a-z]/ig)).map('match', /[a-z]$/i).map('first').without('%');
1156
+ var re = new RegExp('^'+tpl.replace(/%p/i, '(pm|PM|am|AM)').replace(/(%[a-z])/ig, '(.+?)')+'$');
1157
+
1158
+ var match = R(string).trim().match(re);
1159
+
1160
+ if (match) {
1161
+ match.shift();
1162
+
1163
+ var year = null, month = null, hour = null, minute = null, second = null, meridian;
1164
+
1165
+ while (match.length) {
1166
+ var value = match.shift();
1167
+ var key = holders.shift();
1168
+
1169
+ if (key.toLowerCase() == 'b') {
1170
+ month = this.options.i18n[key=='b' ? 'monthNamesShort' : 'monthNames'].indexOf(value);
1171
+ } else if (key.toLowerCase() == 'p') {
1172
+ meridian = value.toLowerCase();
1173
+ } else {
1174
+ value = parseInt(value, 10);
1175
+ switch(key) {
1176
+ case 'd':
1177
+ case 'e': date = value; break;
1178
+ case 'm': month = value-1; break;
1179
+ case 'y':
1180
+ case 'Y': year = value; break;
1181
+ case 'H':
1182
+ case 'k':
1183
+ case 'I':
1184
+ case 'l': hour = value; break;
1185
+ case 'M': minute = value; break;
1186
+ case 'S': second = value; break;
1187
+ }
1188
+ }
1189
+ }
1190
+
1191
+ // converting 1..12am|pm into 0..23 hours marker
1192
+ if (meridian) {
1193
+ hour = hour == 12 ? 0 : hour;
1194
+ hour = (meridian == 'pm' ? hour + 12 : hour);
1195
+ }
1196
+
1197
+ date = new Date(year, month, date, hour, minute, second);
1198
+ }
1199
+ } else if (string instanceof Date || Date.parse(string)) {
1200
+ date = new Date(string);
1201
+ }
1202
+
1203
+ return (!date || isNaN(date.getTime())) ? null : date;
1204
+ },
1205
+
1206
+ /**
1207
+ * Formats the current date into a string depend on the current or given format
1208
+ *
1209
+ * @param String optional format
1210
+ * @return String formatted data
1211
+ */
1212
+ format: function(format) {
1213
+ var i18n = this.options.i18n;
1214
+ var day = this.date.getDay();
1215
+ var month = this.date.getMonth();
1216
+ var date = this.date.getDate();
1217
+ var year = this.date.getFullYear();
1218
+ var hour = this.date.getHours();
1219
+ var minute = this.date.getMinutes();
1220
+ var second = this.date.getSeconds();
1221
+
1222
+ var hour_ampm = (hour == 0 ? 12 : hour < 13 ? hour : hour - 12);
1223
+
1224
+ var values = {
1225
+ a: i18n.dayNamesShort[day],
1226
+ A: i18n.dayNames[day],
1227
+ b: i18n.monthNamesShort[month],
1228
+ B: i18n.monthNames[month],
1229
+ d: zerofy(date),
1230
+ e: ''+date,
1231
+ m: (month < 9 ? '0' : '') + (month+1),
1232
+ y: (''+year).substring(2,4),
1233
+ Y: ''+year,
1234
+ H: zerofy(hour),
1235
+ k: '' + hour,
1236
+ I: (hour > 0 && (hour < 10 || (hour > 12 && hour < 22)) ? '0' : '') + hour_ampm,
1237
+ l: '' + hour_ampm,
1238
+ p: hour < 12 ? 'AM' : 'PM',
1239
+ P: hour < 12 ? 'am' : 'pm',
1240
+ M: zerofy(minute),
1241
+ S: zerofy(second),
1242
+ '%': '%'
1243
+ };
1244
+
1245
+ var result = format || this.options.format;
1246
+ for (var key in values) {
1247
+ result = result.replace('%'+key, values[key]);
1248
+ }
1249
+
1250
+ return result;
1251
+ }
1252
+ });
1253
+
1254
+
1255
+ /**
1256
+ * This module handles the events connection
1257
+ *
1258
+ * Copyright (C) 2009-2010 Nikolay Nemshilov
1259
+ */
1260
+ Calendar.include({
1261
+
1262
+ // protected
1263
+
1264
+ // connects the events with handlers
1265
+ initEvents: function() {
1266
+ var shift = '_shiftDate', terminate = this._terminate;
1267
+
1268
+ this.on({
1269
+ // the dates/months/etc listing events
1270
+ 'prev-day': [shift, {Date: -1}],
1271
+ 'next-day': [shift, {Date: 1}],
1272
+ 'prev-week': [shift, {Date: -7}],
1273
+ 'next-week': [shift, {Date: 7}],
1274
+ 'prev-month': [shift, {Month: -1}],
1275
+ 'next-month': [shift, {Month: 1}],
1276
+ 'prev-year': [shift, {FullYear: -1}],
1277
+ 'next-year': [shift, {FullYear: 1}],
1278
+
1279
+ // the date/time picking events
1280
+ 'date-set': this._changeDate,
1281
+ 'time-set': this._changeTime,
1282
+
1283
+ // the bottom buttons events
1284
+ 'now-clicked': this._setNow,
1285
+ 'done-clicked': this.done,
1286
+
1287
+ // handling the clicks
1288
+ 'click': terminate,
1289
+ 'mousedown': terminate,
1290
+ 'focus': terminate,
1291
+ 'blur': terminate
1292
+ });
1293
+ },
1294
+
1295
+ // shifts the date according to the params
1296
+ _shiftDate: function(params) {
1297
+ var date = new Date(this.date), options = this.options;
1298
+
1299
+ // shifting the date according to the params
1300
+ for (var key in params) {
1301
+ date['set'+key](date['get'+key]() + params[key]);
1302
+ }
1303
+
1304
+ this.setDate(date);
1305
+ },
1306
+
1307
+ // changes the current date (not the time)
1308
+ _changeDate: function(event) {
1309
+ var date = new Date(this.date);
1310
+
1311
+ date.setDate(event.date);
1312
+ date.setMonth(event.month);
1313
+ date.setFullYear(event.year);
1314
+
1315
+ this.setDate(date, true); // <- `true` means just change the date without shifting the list
1316
+
1317
+ if (this.options.hideOnPick) {
1318
+ this.done();
1319
+ }
1320
+ },
1321
+
1322
+ // changes the current time (not the date)
1323
+ _changeTime: function(event) {
1324
+ var date = new Date(this.date);
1325
+
1326
+ date.setHours(event.hours);
1327
+ date.setMinutes(event.minutes);
1328
+
1329
+ this.setDate(date);
1330
+ },
1331
+
1332
+ // resets the calendar to the current time
1333
+ _setNow: function() {
1334
+ this.setDate(new Date());
1335
+ },
1336
+
1337
+ /** simply stops the event so we didn't bother the things outside of the object
1338
+ *
1339
+ * @param {Event} event
1340
+ * @return void
1341
+ * @private
1342
+ */
1343
+ _terminate: function(event) {
1344
+ event.stopPropagation(); // don't let the clicks go anywere out of the clanedar
1345
+
1346
+ if (this._hide_delay) {
1347
+ this._hide_delay.cancel();
1348
+ this._hide_delay = null;
1349
+ }
1350
+ }
1351
+ });
1352
+
1353
+
1354
+ /**
1355
+ * Document level event listeners for navigation and lazy initialization
1356
+ *
1357
+ * Copyright (C) 2009-2010 Nikolay Nemshilov
1358
+ */
1359
+ $(document).on({
1360
+ /**
1361
+ * Watches the focus events and dispalys the calendar
1362
+ * popups when there is a related input element
1363
+ *
1364
+ * @param Event focus-event
1365
+ * @return void
1366
+ */
1367
+ focus: function(event) {
1368
+ var target = event.target instanceof Input && event.target.get('type') == 'text' ? event.target : null;
1369
+
1370
+ Calendar.hideAll();
1371
+
1372
+ if (target && (target.calendar || target.match(Calendar.Options.cssRule))) {
1373
+ (target.calendar || new Calendar({update: target}))
1374
+ .setValue(target.value()).showAt(target);
1375
+ }
1376
+ },
1377
+
1378
+ /**
1379
+ * Watches the input elements blur events
1380
+ * and hides shown popups
1381
+ *
1382
+ * @param Event blur-event
1383
+ * @return void
1384
+ */
1385
+ blur: function(event) {
1386
+ var target = event.target, calendar = target.calendar;
1387
+
1388
+ if (calendar) {
1389
+ // we use the delay so it didn't get hidden when the user clicks the calendar itself
1390
+ calendar._hide_delay = R(function() {
1391
+ calendar.hide();
1392
+ }).delay(200);
1393
+ }
1394
+ },
1395
+
1396
+ /**
1397
+ * Catches clicks on trigger elements
1398
+ *
1399
+ * @param Event click
1400
+ * @return void
1401
+ */
1402
+ click: function(event) {
1403
+ var target = (event.target instanceof Element) ? event.target : null;
1404
+
1405
+ if (target && (target.calendar || target.match(Calendar.Options.cssRule))) {
1406
+ if (!(target instanceof Input) || target.get('type') != 'text') {
1407
+ event.stop();
1408
+ (target.calendar || new Calendar({trigger: target}))
1409
+ .hide(null).toggleAt(target.assignedInput);
1410
+ }
1411
+ } else if (!event.find('div.rui-calendar')){
1412
+ Calendar.hideAll();
1413
+ }
1414
+ },
1415
+
1416
+ /**
1417
+ * Catching the key-downs to navigate in the currently
1418
+ * opened Calendar hover
1419
+ *
1420
+ * @param Event event
1421
+ * @return void
1422
+ */
1423
+ keydown: function(event) {
1424
+ var calendar = Calendar.current, name = ({
1425
+ 27: 'hide', // Escape
1426
+ 37: 'prev-day', // Left Arrow
1427
+ 39: 'next-day', // Right Arrow
1428
+ 38: 'prev-week', // Up Arrow
1429
+ 40: 'next-week', // Down Arrow
1430
+ 33: 'prev-month', // Page Up
1431
+ 34: 'next-month', // Page Down
1432
+ 13: 'done' // Enter
1433
+ })[event.keyCode];
1434
+
1435
+ if (name && calendar && calendar.visible()) {
1436
+ event.stop();
1437
+ if (isFunction(calendar[name])) {
1438
+ calendar[name]();
1439
+ } else {
1440
+ calendar.fire(name);
1441
+ }
1442
+ }
1443
+ }
1444
+ });
1445
+ (function() {
1446
+ var style = document.createElement('style'),
1447
+ rules = document.createTextNode(".rui-panel{margin:0;padding:.5em;position:relative;background-color:#EEE;border:1px solid #BBB;border-radius:.3em;-moz-border-radius:.3em;-webkit-border-radius:.3em;box-shadow:.15em .3em .5em #BBB;-moz-box-shadow:.15em .3em .5em #BBB;-webkit-box-shadow:.15em .3em .5em #BBB;cursor:default} *.rui-button{display:inline-block; *display:inline; *zoom:1;height:1em;line-height:1em;margin:0;padding:.2em .5em;text-align:center;border:1px solid #CCC;border-radius:.2em;-moz-border-radius:.2em;-webkit-border-radius:.2em;cursor:pointer;color:#333;background-color:#FFF;user-select:none;-moz-user-select:none;-webkit-user-select:none} *.rui-button:hover{color:#111;border-color:#999;background-color:#DDD;box-shadow:#888 0 0 .1em;-moz-box-shadow:#888 0 0 .1em;-webkit-box-shadow:#888 0 0 .1em} *.rui-button:active{color:#000;border-color:#777;text-indent:1px;box-shadow:none;-moz-box-shadow:none;-webkit-box-shadow:none} *.rui-button-disabled, *.rui-button-disabled:hover, *.rui-button-disabled:active{color:#888;background:#DDD;border-color:#CCC;cursor:default;text-indent:0;box-shadow:none;-moz-box-shadow:none;-webkit-box-shadow:none}div.rui-re-anchor{margin:0;padding:0;background:none;border:none;float:none;display:inline;position:absolute;z-index:9999}div.rui-calendar .swaps,div.rui-calendar .greed,div.rui-calendar .timepicker,div.rui-calendar .buttons,div.rui-calendar table,div.rui-calendar table tr,div.rui-calendar table th,div.rui-calendar table td,div.rui-calendar table tbody,div.rui-calendar table thead,div.rui-calendar table caption{background:none;border:none;width:auto;height:auto;margin:0;padding:0}div.rui-calendar-inline{position:relative;display:inline-block; *display:inline; *zoom:1;box-shadow:none;-moz-box-shadow:none;-webkit-box-shadow:none}div.rui-calendar .swaps{position:relative}div.rui-calendar .swaps .rui-button{position:absolute;float:left;width:1em;padding:.15em .4em}div.rui-calendar .swaps .next-month{right:0em;_right:.5em}div.rui-calendar .swaps .prev-year{left:2.05em}div.rui-calendar .swaps .next-year{right:2.05em;_right:2.52em}div.rui-calendar .greed{border-spacing:0px;border-collapse:collapse;border-size:0}div.rui-calendar .greed td{vertical-align:top;padding-left:.4em}div.rui-calendar .greed>tbody>tr>td:first-child{padding:0}div.rui-calendar .month{margin-top:.2em;border-spacing:1px;border-collapse:separate}div.rui-calendar .month caption{text-align:center}div.rui-calendar .month th{color:#666;text-align:center}div.rui-calendar .month td{text-align:right;padding:.1em .3em;background-color:#FFF;border:1px solid #CCC;cursor:pointer;color:#555;border-radius:.2em;-moz-border-radius:.2em;-webkit-border-radius:.2em}div.rui-calendar .month td:hover{background-color:#CCC;border-color:#AAA;color:#000}div.rui-calendar .month td.blank{background:transparent;cursor:default;border:none}div.rui-calendar .month td.selected{background-color:#BBB;border-color:#AAA;color:#222;font-weight:bold;padding:.1em .2em}div.rui-calendar .month td.disabled{color:#888;background:#EEE;border-color:#CCC;cursor:default}div.rui-calendar .timepicker{border-top:1px solid #ccc;margin-top:.3em;padding-top:.5em;text-align:center}div.rui-calendar .timepicker select{margin:0 .4em}div.rui-calendar .buttons{position:relative;margin-top:.5em}div.rui-calendar .buttons div.rui-button{width:4em;padding:.25em .5em}div.rui-calendar .buttons .done{position:absolute;right:0em;top:0}");
1448
+
1449
+ style.type = 'text/css';
1450
+
1451
+ if(style.styleSheet) {
1452
+ style.styleSheet.cssText = rules.nodeValue;
1453
+ } else {
1454
+ style.appendChild(rules);
1455
+ }
1456
+
1457
+ document.getElementsByTagName('head')[0].appendChild(style);
1458
+ })();
1459
+
1460
+ return Calendar;
1461
+ })(document, parseInt, RightJS);