My Calendar - Version 1.0.0

Version Description

  • Initial launch.

=

Download this release

Release Info

Developer joedolson
Plugin Icon 128x128 My Calendar
Version 1.0.0
Comparing to
See all releases

Version 1.0.0

date-utilities.php ADDED
@@ -0,0 +1,85 @@
1
+ <?php
2
+
3
+
4
+ function add_date($givendate,$day=0,$mth=0,$yr=0) {
5
+ $cd = strtotime($givendate);
6
+ $newdate = date('Y-m-d', mktime(date('h',$cd),date('i',$cd), date('s',$cd), date('m',$cd)+$mth,date('d',$cd)+$day, date('Y',$cd)+$yr));
7
+ return $newdate;
8
+ }
9
+ function date_comp($early,$late) {
10
+ $firstdate = strtotime($early);
11
+ $lastdate = strtotime($late);
12
+ if ($firstdate <= $lastdate) {
13
+ return true;
14
+ } else {
15
+ return false;
16
+ }
17
+ }
18
+
19
+ function date_equal($early,$late) {
20
+ $firstdate = strtotime($early);
21
+ $lastdate = strtotime($late);
22
+ if ($early == $late) {
23
+ return true;
24
+ } else {
25
+ return false;
26
+ }
27
+ }
28
+
29
+ // Function to compare time in event objects
30
+ function time_cmp($a, $b) {
31
+ if ($a->event_time == $b->event_time) {
32
+ return 0;
33
+ }
34
+ return ($a->event_time < $b->event_time) ? -1 : 1;
35
+ }
36
+
37
+ // Function to compare datetime in event objects
38
+ function datetime_cmp($a, $b) {
39
+ $event_dt_a = strtotime($a->event_begin .' '. $a->event_time);
40
+ $event_dt_b = strtotime($b->event_begin .' '. $b->event_time);
41
+ if ($event_dt_a == $event_dt_b ) {
42
+ return 0;
43
+ }
44
+ return ( $event_dt_a < $event_dt_b ) ? -1 : 1;
45
+ }
46
+
47
+ function timediff_cmp($a, $b) {
48
+ $event_dt_a = strtotime($a->event_begin .' '. $a->event_time);
49
+ $event_dt_b = strtotime($b->event_begin .' '. $b->event_time);
50
+ $diff_a = jd_date_diff_precise($event_dt_a);
51
+ $diff_b = jd_date_diff_precise($event_dt_b);
52
+
53
+ if ( $diff_a == $diff_b ) {
54
+ return 0;
55
+ }
56
+ return ( $diff_a < $diff_b ) ? -1 : 1;
57
+ }
58
+
59
+ function jd_date_diff_precise($start,$end="NOW") {
60
+ if ($end == "NOW") {
61
+ $end = strtotime("NOW");
62
+ }
63
+ $sdate = $start;
64
+ $edate = $end;
65
+
66
+ $time = $edate - $sdate;
67
+
68
+ return abs($time);
69
+ }
70
+
71
+ function jd_date_diff($start, $end="NOW") {
72
+ $sdate = strtotime($start);
73
+ $edate = strtotime($end);
74
+
75
+ $time = $edate - $sdate;
76
+ if ($time < 86400 && $time > -86400) {
77
+ return false;
78
+ } else {
79
+ $pday = ($edate - $sdate) / 86400;
80
+ $preday = explode('.',$pday);
81
+ return $preday[0];
82
+ }
83
+ }
84
+
85
+ ?>
icons/art.png ADDED
Binary file
icons/concert.png ADDED
Binary file
icons/event.png ADDED
Binary file
icons/games.png ADDED
Binary file
icons/globe.png ADDED
Binary file
icons/meeting.png ADDED
Binary file
icons/rehearsal.png ADDED
Binary file
icons/school.png ADDED
Binary file
images/event-details.jpg ADDED
Binary file
images/event-details.png ADDED
Binary file
js/jquery-colorpicker.js ADDED
@@ -0,0 +1,44 @@
1
+ ;(function($){var _remove=$.fn.remove;$.fn.remove=function(){$("*",this).add(this).triggerHandler("remove");return _remove.apply(this,arguments);};function isVisible(element){function checkStyles(element){var style=element.style;return(style.display!='none'&&style.visibility!='hidden');}
2
+ var visible=checkStyles(element);(visible&&$.each($.dir(element,'parentNode'),function(){return(visible=checkStyles(this));}));return visible;}
3
+ $.extend($.expr[':'],{data:function(a,i,m){return $.data(a,m[3]);},tabbable:function(a,i,m){var nodeName=a.nodeName.toLowerCase();return(a.tabIndex>=0&&(('a'==nodeName&&a.href)||(/input|select|textarea|button/.test(nodeName)&&'hidden'!=a.type&&!a.disabled))&&isVisible(a));}});$.keyCode={BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38};function getter(namespace,plugin,method,args){function getMethods(type){var methods=$[namespace][plugin][type]||[];return(typeof methods=='string'?methods.split(/,?\s+/):methods);}
4
+ var methods=getMethods('getter');if(args.length==1&&typeof args[0]=='string'){methods=methods.concat(getMethods('getterSetter'));}
5
+ return($.inArray(method,methods)!=-1);}
6
+ $.widget=function(name,prototype){var namespace=name.split(".")[0];name=name.split(".")[1];$.fn[name]=function(options){var isMethodCall=(typeof options=='string'),args=Array.prototype.slice.call(arguments,1);if(isMethodCall&&options.substring(0,1)=='_'){return this;}
7
+ if(isMethodCall&&getter(namespace,name,options,args)){var instance=$.data(this[0],name);return(instance?instance[options].apply(instance,args):undefined);}
8
+ return this.each(function(){var instance=$.data(this,name);(!instance&&!isMethodCall&&$.data(this,name,new $[namespace][name](this,options)));(instance&&isMethodCall&&$.isFunction(instance[options])&&instance[options].apply(instance,args));});};$[namespace][name]=function(element,options){var self=this;this.widgetName=name;this.widgetEventPrefix=$[namespace][name].eventPrefix||name;this.widgetBaseClass=namespace+'-'+name;this.options=$.extend({},$.widget.defaults,$[namespace][name].defaults,$.metadata&&$.metadata.get(element)[name],options);this.element=$(element).bind('setData.'+name,function(e,key,value){return self._setData(key,value);}).bind('getData.'+name,function(e,key){return self._getData(key);}).bind('remove',function(){return self.destroy();});this._init();};$[namespace][name].prototype=$.extend({},$.widget.prototype,prototype);$[namespace][name].getterSetter='option';};$.widget.prototype={_init:function(){},destroy:function(){this.element.removeData(this.widgetName);},option:function(key,value){var options=key,self=this;if(typeof key=="string"){if(value===undefined){return this._getData(key);}
9
+ options={};options[key]=value;}
10
+ $.each(options,function(key,value){self._setData(key,value);});},_getData:function(key){return this.options[key];},_setData:function(key,value){this.options[key]=value;if(key=='disabled'){this.element[value?'addClass':'removeClass'](this.widgetBaseClass+'-disabled');}},enable:function(){this._setData('disabled',false);},disable:function(){this._setData('disabled',true);},_trigger:function(type,e,data){var eventName=(type==this.widgetEventPrefix?type:this.widgetEventPrefix+type);e=e||$.event.fix({type:eventName,target:this.element[0]});return this.element.triggerHandler(eventName,[e,data],this.options[type]);}};$.widget.defaults={disabled:false};$.ui={plugin:{add:function(module,option,set){var proto=$.ui[module].prototype;for(var i in set){proto.plugins[i]=proto.plugins[i]||[];proto.plugins[i].push([option,set[i]]);}},call:function(instance,name,args){var set=instance.plugins[name];if(!set){return;}
11
+ for(var i=0;i<set.length;i++){if(instance.options[set[i][0]]){set[i][1].apply(instance.element,args);}}}},cssCache:{},css:function(name){if($.ui.cssCache[name]){return $.ui.cssCache[name];}
12
+ var tmp=$('<div class="ui-gen">').addClass(name).css({position:'absolute',top:'-5000px',left:'-5000px',display:'block'}).appendTo('body');$.ui.cssCache[name]=!!((!(/auto|default/).test(tmp.css('cursor'))||(/^[1-9]/).test(tmp.css('height'))||(/^[1-9]/).test(tmp.css('width'))||!(/none/).test(tmp.css('backgroundImage'))||!(/transparent|rgba\(0, 0, 0, 0\)/).test(tmp.css('backgroundColor'))));try{$('body').get(0).removeChild(tmp.get(0));}catch(e){}
13
+ return $.ui.cssCache[name];},disableSelection:function(el){return $(el).attr('unselectable','on').css('MozUserSelect','none').bind('selectstart.ui',function(){return false;});},enableSelection:function(el){return $(el).attr('unselectable','off').css('MozUserSelect','').unbind('selectstart.ui');},hasScroll:function(e,a){if($(e).css('overflow')=='hidden'){return false;}
14
+ var scroll=(a&&a=='left')?'scrollLeft':'scrollTop',has=false;if(e[scroll]>0){return true;}
15
+ e[scroll]=1;has=(e[scroll]>0);e[scroll]=0;return has;}};$.ui.mouse={_mouseInit:function(){var self=this;this.element.bind('mousedown.'+this.widgetName,function(e){return self._mouseDown(e);});if($.browser.msie){this._mouseUnselectable=this.element.attr('unselectable');this.element.attr('unselectable','on');}
16
+ this.started=false;},_mouseDestroy:function(){this.element.unbind('.'+this.widgetName);($.browser.msie&&this.element.attr('unselectable',this._mouseUnselectable));},_mouseDown:function(e){(this._mouseStarted&&this._mouseUp(e));this._mouseDownEvent=e;var self=this,btnIsLeft=(e.which==1),elIsCancel=(typeof this.options.cancel=="string"?$(e.target).parents().add(e.target).filter(this.options.cancel).length:false);if(!btnIsLeft||elIsCancel||!this._mouseCapture(e)){return true;}
17
+ this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){self.mouseDelayMet=true;},this.options.delay);}
18
+ if(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)){this._mouseStarted=(this._mouseStart(e)!==false);if(!this._mouseStarted){e.preventDefault();return true;}}
19
+ this._mouseMoveDelegate=function(e){return self._mouseMove(e);};this._mouseUpDelegate=function(e){return self._mouseUp(e);};$(document).bind('mousemove.'+this.widgetName,this._mouseMoveDelegate).bind('mouseup.'+this.widgetName,this._mouseUpDelegate);return false;},_mouseMove:function(e){if($.browser.msie&&!e.button){return this._mouseUp(e);}
20
+ if(this._mouseStarted){this._mouseDrag(e);return false;}
21
+ if(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,e)!==false);(this._mouseStarted?this._mouseDrag(e):this._mouseUp(e));}
22
+ return!this._mouseStarted;},_mouseUp:function(e){$(document).unbind('mousemove.'+this.widgetName,this._mouseMoveDelegate).unbind('mouseup.'+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._mouseStop(e);}
23
+ return false;},_mouseDistanceMet:function(e){return(Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance);},_mouseDelayMet:function(e){return this.mouseDelayMet;},_mouseStart:function(e){},_mouseDrag:function(e){},_mouseStop:function(e){},_mouseCapture:function(e){return true;}};$.ui.mouse.defaults={cancel:null,distance:1,delay:0};})(jQuery);(function($){$.widget("ui.colorpicker",{_init:function(){this.charMin=65;var o=this.options,self=this,tpl='<div class="ui-colorpicker clearfix"><div class="ui-colorpicker-color"><div><div></div></div></div><div class="ui-colorpicker-hue"><div></div></div><div class="ui-colorpicker-new-color"></div><div class="ui-colorpicker-current-color"></div><div class="ui-colorpicker-hex"><label for="ui-colorpicker-hex" title="hex"></label><input type="text" maxlength="6" size="6" /></div><div class="ui-colorpicker-rgb-r ui-colorpicker-field"><label for="ui-colorpicker-rgb-r"></label><input type="text" maxlength="3" size="2" /><span></span></div><div class="ui-colorpicker-rgb-g ui-colorpicker-field"><label for="ui-colorpicker-rgb-g"></label><input type="text" maxlength="3" size="2" /><span></span></div><div class="ui-colorpicker-rgb-b ui-colorpicker-field"><label for="ui-colorpicker-rgb-b"</label><input type="text" maxlength="3" size="2" /><span></span></div><div class="ui-colorpicker-hsb-h ui-colorpicker-field"><label for="ui-colorpicker-hsb-h"></label><input type="text" maxlength="3" size="2" /><span></span></div><div class="ui-colorpicker-hsb-s ui-colorpicker-field"><label for="ui-colorpicker-hsb-s"></label><input type="text" maxlength="3" size="2" /><span></span></div><div class="ui-colorpicker-hsb-b ui-colorpicker-field"><label for="ui-colorpicker-hsb-b"></label><input type="text" maxlength="3" size="2" /><span></span></div><button class="ui-colorpicker-submit ui-default-state" name="submit" type="button">Done</button></div>';if(typeof o.color=='string'){this.color=this._HexToHSB(o.color);}else if(o.color.r!=undefined&&o.color.g!=undefined&&o.color.b!=undefined){this.color=this._RGBToHSB(o.color);}else if(o.color.h!=undefined&&o.color.s!=undefined&&o.color.b!=undefined){this.color=this._fixHSB(o.color);}else{return this;}
24
+ this.origColor=this.color;this.picker=$(tpl);if(o.flat){this.picker.appendTo(this.element).show();}else{this.picker.appendTo(document.body);}
25
+ this.fields=this.picker.find('input').bind('keydown',function(e){return self._keyDown.call(self,e);}).bind('change',function(e){return self._change.call(self,e);}).bind('blur',function(e){return self._blur.call(self,e);}).bind('focus',function(e){return self._focus.call(self,e);});this.picker.find('span').bind('mousedown',function(e){return self._downIncrement.call(self,e);});this.selector=this.picker.find('div.ui-colorpicker-color').bind('mousedown',function(e){return self._downSelector.call(self,e);});this.selectorIndic=this.selector.find('div div');this.hue=this.picker.find('div.ui-colorpicker-hue div');this.picker.find('div.ui-colorpicker-hue').bind('mousedown',function(e){return self._downHue.call(self,e);});this.newColor=this.picker.find('div.ui-colorpicker-new-color');this.currentColor=this.picker.find('div.ui-colorpicker-current-color');this.picker.find('.ui-colorpicker-submit').bind('mouseenter',function(e){return self._enterSubmit.call(self,e);}).bind('mouseleave',function(e){return self._leaveSubmit.call(self,e);}).bind('click',function(e){return self._clickSubmit.call(self,e);});this._fillRGBFields(this.color);this._fillHSBFields(this.color);this._fillHexFields(this.color);this._setHue(this.color);this._setSelector(this.color);this._setCurrentColor(this.color);this._setNewColor(this.color);if(o.flat){this.picker.css({position:'relative',display:'block'});}else{$(this.element).bind(o.eventName+".colorpicker",function(e){return self._show.call(self,e);});}},destroy:function(){this.picker.remove();this.element.removeData("colorpicker").unbind(".colorpicker");},_fillRGBFields:function(hsb){var rgb=this._HSBToRGB(hsb);this.fields.eq(1).val(rgb.r).end().eq(2).val(rgb.g).end().eq(3).val(rgb.b).end();},_fillHSBFields:function(hsb){this.fields.eq(4).val(hsb.h).end().eq(5).val(hsb.s).end().eq(6).val(hsb.b).end();},_fillHexFields:function(hsb){this.fields.eq(0).val(this._HSBToHex(hsb)).end();},_setSelector:function(hsb){this.selector.css('backgroundColor','#'+this._HSBToHex({h:hsb.h,s:100,b:100}));this.selectorIndic.css({left:parseInt(150*hsb.s/100,10),top:parseInt(150*(100-hsb.b)/100,10)});},_setHue:function(hsb){this.hue.css('top',parseInt(150-150*hsb.h/360,10));},_setCurrentColor:function(hsb){this.currentColor.css('backgroundColor','#'+this._HSBToHex(hsb));},_setNewColor:function(hsb){this.newColor.css('backgroundColor','#'+this._HSBToHex(hsb));},_keyDown:function(e){var pressedKey=e.charCode||e.keyCode||-1;if((pressedKey>=this.charMin&&pressedKey<=90)||pressedKey==32){return false;}},_change:function(e,target){var col;target=target||e.target;if(target.parentNode.className.indexOf('-hex')>0){this.color=col=this._HexToHSB(this.value);this._fillRGBFields(col.color);this._fillHSBFields(col);}else if(target.parentNode.className.indexOf('-hsb')>0){this.color=col=this._fixHSB({h:parseInt(this.fields.eq(4).val(),10),s:parseInt(this.fields.eq(5).val(),10),b:parseInt(this.fields.eq(6).val(),10)});this._fillRGBFields(col);this._fillHexFields(col);}else{this.color=col=this._RGBToHSB(this._fixRGB({r:parseInt(this.fields.eq(1).val(),10),g:parseInt(this.fields.eq(2).val(),10),b:parseInt(this.fields.eq(3).val(),10)}));this._fillHexFields(col);this._fillHSBFields(col);}
26
+ this._setSelector(col);this._setHue(col);this._setNewColor(col);this._trigger('change',e,{options:this.options,hsb:col,hex:this._HSBToHex(col),rgb:this._HSBToRGB(col)});},_blur:function(e){var col=this.color;this._fillRGBFields(col);this._fillHSBFields(col);this._fillHexFields(col);this._setHue(col);this._setSelector(col);this._setNewColor(col);this.fields.parent().removeClass('ui-colorpicker-focus');},_focus:function(e){this.charMin=e.target.parentNode.className.indexOf('-hex')>0?70:65;this.fields.parent().removeClass('ui-colorpicker-focus');$(e.target.parentNode).addClass('ui-colorpicker-focus');},_downIncrement:function(e){var field=$(e.target).parent().find('input').focus(),self=this;this.currentIncrement={el:$(e.target).parent().addClass('ui-colorpicker-slider'),max:e.target.parentNode.className.indexOf('-hsb-h')>0?360:(e.target.parentNode.className.indexOf('-hsb')>0?100:255),y:e.pageY,field:field,val:parseInt(field.val(),10)};$(document).bind('mouseup.cpSlider',function(e){return self._upIncrement.call(self,e);});$(document).bind('mousemove.cpSlider',function(e){return self._moveIncrement.call(self,e);});return false;},_moveIncrement:function(e){this.currentIncrement.field.val(Math.max(0,Math.min(this.currentIncrement.max,parseInt(this.currentIncrement.val+e.pageY-this.currentIncrement.y,10))));this._change.apply(this,[e,this.currentIncrement.field.get(0)]);return false;},_upIncrement:function(e){this.currentIncrement.el.removeClass('ui-colorpicker-slider').find('input').focus();this._change.apply(this,[e,this.currentIncrement.field.get(0)]);$(document).unbind('mouseup.cpSlider');$(document).unbind('mousemove.cpSlider');return false;},_downHue:function(e){this.currentHue={y:this.picker.find('div.ui-colorpicker-hue').offset().top};this._change.apply(this,[e,this.fields.eq(4).val(parseInt(360*(150-Math.max(0,Math.min(150,(e.pageY-this.currentHue.y))))/150,10)).get(0)]);var self=this;$(document).bind('mouseup.cpSlider',function(e){return self._upHue.call(self,e);});$(document).bind('mousemove.cpSlider',function(e){return self._moveHue.call(self,e);});return false;},_moveHue:function(e){this._change.apply(this,[e,this.fields.eq(4).val(parseInt(360*(150-Math.max(0,Math.min(150,(e.pageY-this.currentHue.y))))/150,10)).get(0)]);return false;},_upHue:function(e){$(document).unbind('mouseup.cpSlider');$(document).unbind('mousemove.cpSlider');return false;},_downSelector:function(e){var self=this;this.currentSelector={pos:this.picker.find('div.ui-colorpicker-color').offset()};this._change.apply(this,[e,this.fields.eq(6).val(parseInt(100*(150-Math.max(0,Math.min(150,(e.pageY-this.currentSelector.pos.top))))/150,10)).end().eq(5).val(parseInt(100*(Math.max(0,Math.min(150,(e.pageX-this.currentSelector.pos.left))))/150,10)).get(0)]);$(document).bind('mouseup.cpSlider',function(e){return self._upSelector.call(self,e);});$(document).bind('mousemove.cpSlider',function(e){return self._moveSelector.call(self,e);});return false;},_moveSelector:function(e){this._change.apply(this,[e,this.fields.eq(6).val(parseInt(100*(150-Math.max(0,Math.min(150,(e.pageY-this.currentSelector.pos.top))))/150,10)).end().eq(5).val(parseInt(100*(Math.max(0,Math.min(150,(e.pageX-this.currentSelector.pos.left))))/150,10)).get(0)]);return false;},_upSelector:function(e){$(document).unbind('mouseup.cpSlider');$(document).unbind('mousemove.cpSlider');return false;},_enterSubmit:function(e){this.picker.find('.ui-colorpicker-submit').addClass('ui-colorpicker-focus');},_leaveSubmit:function(e){this.picker.find('.ui-colorpicker-submit').removeClass('ui-colorpicker-focus');},_clickSubmit:function(e){var col=this.color;this.origColor=col;this._setCurrentColor(col);this._trigger("submit",e,{options:this.options,hsb:col,hex:this._HSBToHex(col),rgb:this._HSBToRGB(col)});return false;},_show:function(e){this._trigger("beforeShow",e,{options:this.options,hsb:this.color,hex:this._HSBToHex(this.color),rgb:this._HSBToRGB(this.color)});var pos=this.element.offset();var viewPort=this._getScroll();var top=pos.top+this.element[0].offsetHeight;var left=pos.left;if(top+176>viewPort.t+Math.min(viewPort.h,viewPort.ih)){top-=this.element[0].offsetHeight+176;}
27
+ if(left+356>viewPort.l+Math.min(viewPort.w,viewPort.iw)){left-=356;}
28
+ this.picker.css({left:left+'px',top:top+'px'});if(this._trigger("show",e,{options:this.options,hsb:this.color,hex:this._HSBToHex(this.color),rgb:this._HSBToRGB(this.color)})!=false){this.picker.show();}
29
+ var self=this;$(document).bind('mousedown.colorpicker',function(e){return self._hide.call(self,e);});return false;},_hide:function(e){if(!this._isChildOf(this.picker[0],e.target,this.picker[0])){if(this._trigger("hide",e,{options:this.options,hsb:this.color,hex:this._HSBToHex(this.color),rgb:this._HSBToRGB(this.color)})!=false){this.picker.hide();}
30
+ $(document).unbind('mousedown.colorpicker');}},_isChildOf:function(parentEl,el,container){if(parentEl==el){return true;}
31
+ if(parentEl.contains&&!$.browser.safari){return parentEl.contains(el);}
32
+ if(parentEl.compareDocumentPosition){return!!(parentEl.compareDocumentPosition(el)&16);}
33
+ var prEl=el.parentNode;while(prEl&&prEl!=container){if(prEl==parentEl)
34
+ return true;prEl=prEl.parentNode;}
35
+ return false;},_getScroll:function(){var t,l,w,h,iw,ih;if(document.documentElement){t=document.documentElement.scrollTop;l=document.documentElement.scrollLeft;w=document.documentElement.scrollWidth;h=document.documentElement.scrollHeight;}else{t=document.body.scrollTop;l=document.body.scrollLeft;w=document.body.scrollWidth;h=document.body.scrollHeight;}
36
+ iw=self.innerWidth||document.documentElement.clientWidth||document.body.clientWidth||0;ih=self.innerHeight||document.documentElement.clientHeight||document.body.clientHeight||0;return{t:t,l:l,w:w,h:h,iw:iw,ih:ih};},_fixHSB:function(hsb){return{h:Math.min(360,Math.max(0,hsb.h)),s:Math.min(100,Math.max(0,hsb.s)),b:Math.min(100,Math.max(0,hsb.b))};},_fixRGB:function(rgb){return{r:Math.min(255,Math.max(0,rgb.r)),g:Math.min(255,Math.max(0,rgb.g)),b:Math.min(255,Math.max(0,rgb.b))};},_HexToRGB:function(hex){var hex=parseInt(((hex.indexOf('#')>-1)?hex.substring(1):hex),16);return{r:hex>>16,g:(hex&0x00FF00)>>8,b:(hex&0x0000FF)};},_HexToHSB:function(hex){return this._RGBToHSB(this._HexToRGB(hex));},_RGBToHSB:function(rgb){var hsb={};hsb.b=Math.max(Math.max(rgb.r,rgb.g),rgb.b);hsb.s=(hsb.b<=0)?0:Math.round(100*(hsb.b-Math.min(Math.min(rgb.r,rgb.g),rgb.b))/hsb.b);hsb.b=Math.round((hsb.b/255)*100);if((rgb.r==rgb.g)&&(rgb.g==rgb.b))hsb.h=0;else if(rgb.r>=rgb.g&&rgb.g>=rgb.b)hsb.h=60*(rgb.g-rgb.b)/(rgb.r-rgb.b);else if(rgb.g>=rgb.r&&rgb.r>=rgb.b)hsb.h=60+60*(rgb.g-rgb.r)/(rgb.g-rgb.b);else if(rgb.g>=rgb.b&&rgb.b>=rgb.r)hsb.h=120+60*(rgb.b-rgb.r)/(rgb.g-rgb.r);else if(rgb.b>=rgb.g&&rgb.g>=rgb.r)hsb.h=180+60*(rgb.b-rgb.g)/(rgb.b-rgb.r);else if(rgb.b>=rgb.r&&rgb.r>=rgb.g)hsb.h=240+60*(rgb.r-rgb.g)/(rgb.b-rgb.g);else if(rgb.r>=rgb.b&&rgb.b>=rgb.g)hsb.h=300+60*(rgb.r-rgb.b)/(rgb.r-rgb.g);else hsb.h=0;hsb.h=Math.round(hsb.h);return hsb;},_HSBToRGB:function(hsb){var rgb={};var h=Math.round(hsb.h);var s=Math.round(hsb.s*255/100);var v=Math.round(hsb.b*255/100);if(s==0){rgb.r=rgb.g=rgb.b=v;}else{var t1=v;var t2=(255-s)*v/255;var t3=(t1-t2)*(h%60)/60;if(h==360)h=0;if(h<60){rgb.r=t1;rgb.b=t2;rgb.g=t2+t3;}
37
+ else if(h<120){rgb.g=t1;rgb.b=t2;rgb.r=t1-t3;}
38
+ else if(h<180){rgb.g=t1;rgb.r=t2;rgb.b=t2+t3;}
39
+ else if(h<240){rgb.b=t1;rgb.r=t2;rgb.g=t1-t3;}
40
+ else if(h<300){rgb.b=t1;rgb.g=t2;rgb.r=t2+t3;}
41
+ else if(h<360){rgb.r=t1;rgb.g=t2;rgb.b=t1-t3;}
42
+ else{rgb.r=0;rgb.g=0;rgb.b=0;}}
43
+ return{r:Math.round(rgb.r),g:Math.round(rgb.g),b:Math.round(rgb.b)};},_RGBToHex:function(rgb){var hex=[rgb.r.toString(16),rgb.g.toString(16),rgb.b.toString(16)];$.each(hex,function(nr,val){if(val.length==1){hex[nr]='0'+val;}});return hex.join('');},_HSBToHex:function(hsb){return this._RGBToHex(this._HSBToRGB(hsb));},setColor:function(col){if(typeof col=='string'){col=this._HexToHSB(col);}else if(col.r!=undefined&&col.g!=undefined&&col.b!=undefined){col=this._RGBToHSB(col);}else if(col.h!=undefined&&col.s!=undefined&&col.b!=undefined){col=this._fixHSB(col);}else{return this;}
44
+ this.color=col;this.origColor=col;this._fillRGBFields(col);this._fillHSBFields(col);this._fillHexFields(col);this._setHue(col);this._setSelector(col);this._setCurrentColor(col);this._setNewColor(col);}});$.extend($.ui.colorpicker,{defaults:{eventName:'click',color:'ff0000',flat:false}});})(jQuery);
js/ui.datepicker.css ADDED
@@ -0,0 +1,212 @@
1
+ /* Main Style Sheet for jQuery UI date picker */
2
+ #ui-datepicker-div, .ui-datepicker-inline {
3
+ font-size: 13px;
4
+ padding: 0;
5
+ margin: 0;
6
+ background: #ddd;
7
+ width: 185px;
8
+ }
9
+ #ui-datepicker-div {
10
+ display: none;
11
+ border: 1px solid #3185bb;
12
+ z-index: 9999;
13
+ /*must have*/
14
+ }
15
+ .ui-datepicker-inline {
16
+ float: left;
17
+ display: block;
18
+ border: 0;
19
+ }
20
+ .ui-datepicker-rtl {
21
+ direction: rtl;
22
+ }
23
+ .ui-datepicker-dialog {
24
+ padding: 5px !important;
25
+ border: 4px ridge #ccc!important;
26
+ }
27
+ button.ui-datepicker-trigger {
28
+ width: 25px;
29
+ }
30
+ img.ui-datepicker-trigger {
31
+ margin: 2px;
32
+ vertical-align: middle;
33
+ }
34
+ .ui-datepicker-prompt {
35
+ float: left;
36
+ padding: 2px;
37
+ background: #ddd;
38
+ color: #000;
39
+ }
40
+ * html .ui-datepicker-prompt {
41
+ width: 185px;
42
+ }
43
+ .ui-datepicker-control, .ui-datepicker-links, .ui-datepicker-header, .ui-datepicker {
44
+ clear: both;
45
+ float: left;
46
+ width: 100%;
47
+ color: #fff;
48
+ }
49
+ .ui-datepicker-control {
50
+ background: #21759b;
51
+ padding: 2px 0px;
52
+ }
53
+ .ui-datepicker-links {
54
+ background: #222;
55
+ padding: 2px 0px;
56
+ }
57
+ .ui-datepicker-control, .ui-datepicker-links {
58
+ font-weight: bold;
59
+ font-size: 80%;
60
+ }
61
+ .ui-datepicker-links label {
62
+ /* disabled links */
63
+ padding: 2px 5px;
64
+ color: #888;
65
+ }
66
+ .ui-datepicker-clear, .ui-datepicker-prev {
67
+ float: left;
68
+ width: 34%;
69
+ }
70
+ .ui-datepicker-rtl .ui-datepicker-clear, .ui-datepicker-rtl .ui-datepicker-prev {
71
+ float: right;
72
+ text-align: right;
73
+ }
74
+ .ui-datepicker-current {
75
+ float: left;
76
+ width: 30%;
77
+ text-align: center;
78
+ }
79
+ .ui-datepicker-close, .ui-datepicker-next {
80
+ float: right;
81
+ width: 34%;
82
+ text-align: right;
83
+ }
84
+ .ui-datepicker-rtl .ui-datepicker-close, .ui-datepicker-rtl .ui-datepicker-next {
85
+ float: left;
86
+ text-align: left;
87
+ }
88
+ .ui-datepicker-header {
89
+ padding: 1px 0 3px;
90
+ background: #333;
91
+ text-align: center;
92
+ font-weight: bold;
93
+ height: 1.3em;
94
+ }
95
+ .ui-datepicker-header select {
96
+ background: #333;
97
+ color: #fff;
98
+ border: 0px;
99
+ font-weight: bold;
100
+ }
101
+ .ui-datepicker {
102
+ background: #ccc;
103
+ text-align: center;
104
+ font-size: 100%;
105
+ }
106
+ .ui-datepicker a {
107
+ display: block;
108
+ width: 100%;
109
+ }
110
+ .ui-datepicker-title-row {
111
+ background: #666;
112
+ }
113
+ .ui-datepicker-days-row {
114
+ background: #e6e6e6;
115
+ color: #666;
116
+ }
117
+ .ui-datepicker-week-col {
118
+ background: #666;
119
+ color: #fff;
120
+ }
121
+ .ui-datepicker-days-cell {
122
+ color: #000;
123
+ border: 1px solid #ddd;
124
+ }
125
+ .ui-datepicker-days-cell a {
126
+ display: block;
127
+ }
128
+ .ui-datepicker-week-end-cell {
129
+ background: #e6e6e6;
130
+ }
131
+ .ui-datepicker-title-row .ui-datepicker-week-end-cell {
132
+ background: #666;
133
+ }
134
+ .ui-datepicker-days-cell-over {
135
+ background: #fff;
136
+ border: 1px solid #01355b;
137
+ }
138
+ .ui-datepicker-unselectable {
139
+ color: #888;
140
+ }
141
+ .ui-datepicker-today {
142
+ background: #fcc !important;
143
+ }
144
+ .ui-datepicker-current-day {
145
+ background: #ccc !important;
146
+ }
147
+ .ui-datepicker-status {
148
+ background: #ddd;
149
+ width: 100%;
150
+ font-size: 80%;
151
+ text-align: center;
152
+ }
153
+ /* ________ Datepicker Links _______** Reset link properties and then override them with !important */
154
+ #ui-datepicker-div a, .ui-datepicker-inline a {
155
+ cursor: pointer;
156
+ margin: 0;
157
+ padding: 0;
158
+ background: none;
159
+ color: #000;
160
+ }
161
+ .ui-datepicker-inline .ui-datepicker-links a {
162
+ padding: 0 5px !important;
163
+ }
164
+ .ui-datepicker-control a, .ui-datepicker-links a {
165
+ padding: 2px 5px !important;
166
+ color: #eee !important;
167
+ }
168
+ .ui-datepicker-title-row a {
169
+ color: #eee !important;
170
+ }
171
+ .ui-datepicker-control a:hover {
172
+ background: #fdd !important;
173
+ color: #333 !important;
174
+ }
175
+ .ui-datepicker-links a:hover, .ui-datepicker-title-row a:hover {
176
+ background: #ddd !important;
177
+ color: #333 !important;
178
+ }
179
+ /* ___________ MULTIPLE MONTHS _________*/
180
+ .ui-datepicker-multi .ui-datepicker {
181
+ border: 1px solid #777;
182
+ }
183
+ .ui-datepicker-one-month {
184
+ float: left;
185
+ width: 185px;
186
+ }
187
+ .ui-datepicker-new-row {
188
+ clear: left;
189
+ }
190
+ /* ___________ IE6 IFRAME FIX ________ */
191
+ .ui-datepicker-cover {
192
+ display: none;
193
+ /*sorry for IE5*/
194
+ display
195
+ /**/
196
+ : block;
197
+ /*sorry for IE5*/
198
+ position: absolute;
199
+ /*must have*/
200
+ z-index: -1;
201
+ /*must have*/
202
+ filter: mask();
203
+ /*must have*/
204
+ top: -4px;
205
+ /*must have*/
206
+ left: -4px;
207
+ /*must have*/
208
+ width: 200px;
209
+ /*must have*/
210
+ height: 200px;
211
+ /*must have*/
212
+ }
js/ui.datepicker.js ADDED
@@ -0,0 +1,1718 @@
1
+ /*
2
+ * jQuery UI Datepicker @VERSION
3
+ *
4
+ * Copyright (c) 2006, 2007, 2008 Marc Grabanski
5
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
6
+ * and GPL (GPL-LICENSE.txt) licenses.
7
+ *
8
+ * http://docs.jquery.com/UI/Datepicker
9
+ *
10
+ * Depends:
11
+ * ui.core.js
12
+ *
13
+ * Marc Grabanski (m@marcgrabanski.com) and Keith Wood (kbwood@virginbroadband.com.au).
14
+ */
15
+
16
+ (function($) { // hide the namespace
17
+
18
+ var PROP_NAME = 'datepicker';
19
+
20
+ /* Date picker manager.
21
+ Use the singleton instance of this class, $.datepicker, to interact with the date picker.
22
+ Settings for (groups of) date pickers are maintained in an instance object,
23
+ allowing multiple different settings on the same page. */
24
+
25
+ function Datepicker() {
26
+ this.debug = false; // Change this to true to start debugging
27
+ this._curInst = null; // The current instance in use
28
+ this._disabledInputs = []; // List of date picker inputs that have been disabled
29
+ this._datepickerShowing = false; // True if the popup picker is showing , false if not
30
+ this._inDialog = false; // True if showing within a "dialog", false if not
31
+ this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
32
+ this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
33
+ this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
34
+ this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
35
+ this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
36
+ this._promptClass = 'ui-datepicker-prompt'; // The name of the dialog prompt marker class
37
+ this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
38
+ this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
39
+ this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
40
+ this.regional = []; // Available regional settings, indexed by language code
41
+ this.regional[''] = { // Default regional settings
42
+ clearText: 'Clear', // Display text for clear link
43
+ clearStatus: 'Erase the current date', // Status text for clear link
44
+ closeText: 'Close', // Display text for close link
45
+ closeStatus: 'Close without change', // Status text for close link
46
+ prevText: '&#x3c;Prev', // Display text for previous month link
47
+ prevStatus: 'Show the previous month', // Status text for previous month link
48
+ prevBigText: '&#x3c;&#x3c;', // Display text for previous year link
49
+ prevBigStatus: 'Show the previous year', // Status text for previous year link
50
+ nextText: 'Next&#x3e;', // Display text for next month link
51
+ nextStatus: 'Show the next month', // Status text for next month link
52
+ nextBigText: '&#x3e;&#x3e;', // Display text for next year link
53
+ nextBigStatus: 'Show the next year', // Status text for next year link
54
+ currentText: 'Today', // Display text for current month link
55
+ currentStatus: 'Show the current month', // Status text for current month link
56
+ monthNames: ['January','February','March','April','May','June',
57
+ 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
58
+ monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
59
+ monthStatus: 'Show a different month', // Status text for selecting a month
60
+ yearStatus: 'Show a different year', // Status text for selecting a year
61
+ weekHeader: 'Wk', // Header for the week of the year column
62
+ weekStatus: 'Week of the year', // Status text for the week of the year column
63
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
64
+ dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
65
+ dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
66
+ dayStatus: 'Set DD as first week day', // Status text for the day of the week selection
67
+ dateStatus: 'Select DD, M d', // Status text for the date selection
68
+ dateFormat: 'mm/dd/yy', // See format options on parseDate
69
+ firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
70
+ initStatus: 'Select a date', // Initial Status text on opening
71
+ isRTL: false // True if right-to-left language, false if left-to-right
72
+ };
73
+ this._defaults = { // Global defaults for all the date picker instances
74
+ showOn: 'focus', // 'focus' for popup on focus,
75
+ // 'button' for trigger button, or 'both' for either
76
+ showAnim: 'show', // Name of jQuery animation for popup
77
+ showOptions: {}, // Options for enhanced animations
78
+ defaultDate: null, // Used when field is blank: actual date,
79
+ // +/-number for offset from today, null for today
80
+ appendText: '', // Display text following the input box, e.g. showing the format
81
+ buttonText: '...', // Text for trigger button
82
+ buttonImage: '', // URL for trigger button image
83
+ buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
84
+ closeAtTop: true, // True to have the clear/close at the top,
85
+ // false to have them at the bottom
86
+ mandatory: false, // True to hide the Clear link, false to include it
87
+ hideIfNoPrevNext: false, // True to hide next/previous month links
88
+ // if not applicable, false to just disable them
89
+ navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
90
+ showBigPrevNext: false, // True to show big prev/next links
91
+ gotoCurrent: false, // True if today link goes back to current selection instead
92
+ changeMonth: true, // True if month can be selected directly, false if only prev/next
93
+ changeYear: true, // True if year can be selected directly, false if only prev/next
94
+ showMonthAfterYear: false, // True if the year select precedes month, false for month then year
95
+ yearRange: '-10:+10', // Range of years to display in drop-down,
96
+ // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn)
97
+ changeFirstDay: true, // True to click on day name to change, false to remain as set
98
+ highlightWeek: false, // True to highlight the selected week
99
+ showOtherMonths: false, // True to show dates in other months, false to leave blank
100
+ showWeeks: false, // True to show week of the year, false to omit
101
+ calculateWeek: this.iso8601Week, // How to calculate the week of the year,
102
+ // takes a Date and returns the number of the week for it
103
+ shortYearCutoff: '+10', // Short year values < this are in the current century,
104
+ // > this are in the previous century,
105
+ // string value starting with '+' for current year + value
106
+ showStatus: false, // True to show status bar at bottom, false to not show it
107
+ statusForDate: this.dateStatus, // Function to provide status text for a date -
108
+ // takes date and instance as parameters, returns display text
109
+ minDate: null, // The earliest selectable date, or null for no limit
110
+ maxDate: null, // The latest selectable date, or null for no limit
111
+ duration: 'normal', // Duration of display/closure
112
+ beforeShowDay: null, // Function that takes a date and returns an array with
113
+ // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
114
+ // [2] = cell title (optional), e.g. $.datepicker.noWeekends
115
+ beforeShow: null, // Function that takes an input field and
116
+ // returns a set of custom settings for the date picker
117
+ onSelect: null, // Define a callback function when a date is selected
118
+ onChangeMonthYear: null, // Define a callback function when the month or year is changed
119
+ onClose: null, // Define a callback function when the datepicker is closed
120
+ numberOfMonths: 1, // Number of months to show at a time
121
+ showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
122
+ stepMonths: 1, // Number of months to step back/forward
123
+ stepBigMonths: 12, // Number of months to step back/forward for the big links
124
+ rangeSelect: false, // Allows for selecting a date range on one date picker
125
+ rangeSeparator: ' - ', // Text between two dates in a range
126
+ altField: '', // Selector for an alternate field to store selected dates into
127
+ altFormat: '', // The date format to use for the alternate field
128
+ constrainInput: true // The input is constrained by the current date format
129
+ };
130
+ $.extend(this._defaults, this.regional['']);
131
+ this.dpDiv = $('<div id="' + this._mainDivId + '" style="display: none;"></div>');
132
+ }
133
+
134
+ $.extend(Datepicker.prototype, {
135
+ /* Class name added to elements to indicate already configured with a date picker. */
136
+ markerClassName: 'hasDatepicker',
137
+
138
+ /* Debug logging (if enabled). */
139
+ log: function () {
140
+ if (this.debug)
141
+ console.log.apply('', arguments);
142
+ },
143
+
144
+ /* Override the default settings for all instances of the date picker.
145
+ @param settings object - the new settings to use as defaults (anonymous object)
146
+ @return the manager object */
147
+ setDefaults: function(settings) {
148
+ extendRemove(this._defaults, settings || {});
149
+ return this;
150
+ },
151
+
152
+ /* Attach the date picker to a jQuery selection.
153
+ @param target element - the target input field or division or span
154
+ @param settings object - the new settings to use for this date picker instance (anonymous) */
155
+ _attachDatepicker: function(target, settings) {
156
+ // check for settings on the control itself - in namespace 'date:'
157
+ var inlineSettings = null;
158
+ for (attrName in this._defaults) {
159
+ var attrValue = target.getAttribute('date:' + attrName);
160
+ if (attrValue) {
161
+ inlineSettings = inlineSettings || {};
162
+ try {
163
+ inlineSettings[attrName] = eval(attrValue);
164
+ } catch (err) {
165
+ inlineSettings[attrName] = attrValue;
166
+ }
167
+ }
168
+ }
169
+ var nodeName = target.nodeName.toLowerCase();
170
+ var inline = (nodeName == 'div' || nodeName == 'span');
171
+ if (!target.id)
172
+ target.id = 'dp' + (++this.uuid);
173
+ var inst = this._newInst($(target), inline);
174
+ inst.settings = $.extend({}, settings || {}, inlineSettings || {});
175
+ if (nodeName == 'input') {
176
+ this._connectDatepicker(target, inst);
177
+ } else if (inline) {
178
+ this._inlineDatepicker(target, inst);
179
+ }
180
+ },
181
+
182
+ /* Create a new instance object. */
183
+ _newInst: function(target, inline) {
184
+ var id = target[0].id.replace(/([:\[\]\.])/g, '\\\\$1'); // escape jQuery meta chars
185
+ return {id: id, input: target, // associated target
186
+ selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
187
+ drawMonth: 0, drawYear: 0, // month being drawn
188
+ inline: inline, // is datepicker inline or not
189
+ dpDiv: (!inline ? this.dpDiv : // presentation div
190
+ $('<div class="' + this._inlineClass + '"></div>'))};
191
+ },
192
+
193
+ /* Attach the date picker to an input field. */
194
+ _connectDatepicker: function(target, inst) {
195
+ var input = $(target);
196
+ if (input.hasClass(this.markerClassName))
197
+ return;
198
+ var appendText = this._get(inst, 'appendText');
199
+ var isRTL = this._get(inst, 'isRTL');
200
+ if (appendText)
201
+ input[isRTL ? 'before' : 'after']('<span class="' + this._appendClass + '">' + appendText + '</span>');
202
+ var showOn = this._get(inst, 'showOn');
203
+ if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
204
+ input.focus(this._showDatepicker);
205
+ if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
206
+ var buttonText = this._get(inst, 'buttonText');
207
+ var buttonImage = this._get(inst, 'buttonImage');
208
+ var trigger = $(this._get(inst, 'buttonImageOnly') ?
209
+ $('<img/>').addClass(this._triggerClass).
210
+ attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
211
+ $('<button type="button"></button>').addClass(this._triggerClass).
212
+ html(buttonImage == '' ? buttonText : $('<img/>').attr(
213
+ { src:buttonImage, alt:buttonText, title:buttonText })));
214
+ input[isRTL ? 'before' : 'after'](trigger);
215
+ trigger.click(function() {
216
+ if ($.datepicker._datepickerShowing && $.datepicker._lastInput == target)
217
+ $.datepicker._hideDatepicker();
218
+ else
219
+ $.datepicker._showDatepicker(target);
220
+ return false;
221
+ });
222
+ }
223
+ input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).
224
+ bind("setData.datepicker", function(event, key, value) {
225
+ inst.settings[key] = value;
226
+ }).bind("getData.datepicker", function(event, key) {
227
+ return this._get(inst, key);
228
+ });
229
+ $.data(target, PROP_NAME, inst);
230
+ },
231
+
232
+ /* Attach an inline date picker to a div. */
233
+ _inlineDatepicker: function(target, inst) {
234
+ var divSpan = $(target);
235
+ if (divSpan.hasClass(this.markerClassName))
236
+ return;
237
+ divSpan.addClass(this.markerClassName).append(inst.dpDiv).
238
+ bind("setData.datepicker", function(event, key, value){
239
+ inst.settings[key] = value;
240
+ }).bind("getData.datepicker", function(event, key){
241
+ return this._get(inst, key);
242
+ });
243
+ $.data(target, PROP_NAME, inst);
244
+ this._setDate(inst, this._getDefaultDate(inst));
245
+ this._updateDatepicker(inst);
246
+ },
247
+
248
+ /* Tidy up after displaying the date picker. */
249
+ _inlineShow: function(inst) {
250
+ var numMonths = this._getNumberOfMonths(inst); // fix width for dynamic number of date pickers
251
+ inst.dpDiv.width(numMonths[1] * $('.ui-datepicker', inst.dpDiv[0]).width());
252
+ },
253
+
254
+ /* Pop-up the date picker in a "dialog" box.
255
+ @param input element - ignored
256
+ @param dateText string - the initial date to display (in the current format)
257
+ @param onSelect function - the function(dateText) to call when a date is selected
258
+ @param settings object - update the dialog date picker instance's settings (anonymous object)
259
+ @param pos int[2] - coordinates for the dialog's position within the screen or
260
+ event - with x/y coordinates or
261
+ leave empty for default (screen centre)
262
+ @return the manager object */
263
+ _dialogDatepicker: function(input, dateText, onSelect, settings, pos) {
264
+ var inst = this._dialogInst; // internal instance
265
+ if (!inst) {
266
+ var id = 'dp' + (++this.uuid);
267
+ this._dialogInput = $('<input type="text" id="' + id +
268
+ '" size="1" style="position: absolute; top: -100px;"/>');
269
+ this._dialogInput.keydown(this._doKeyDown);
270
+ $('body').append(this._dialogInput);
271
+ inst = this._dialogInst = this._newInst(this._dialogInput, false);
272
+ inst.settings = {};
273
+ $.data(this._dialogInput[0], PROP_NAME, inst);
274
+ }
275
+ extendRemove(inst.settings, settings || {});
276
+ this._dialogInput.val(dateText);
277
+
278
+ this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
279
+ if (!this._pos) {
280
+ var browserWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
281
+ var browserHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
282
+ var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
283
+ var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
284
+ this._pos = // should use actual width/height below
285
+ [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
286
+ }
287
+
288
+ // move input on screen for focus, but hidden behind dialog
289
+ this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px');
290
+ inst.settings.onSelect = onSelect;
291
+ this._inDialog = true;
292
+ this.dpDiv.addClass(this._dialogClass);
293
+ this._showDatepicker(this._dialogInput[0]);
294
+ if ($.blockUI)
295
+ $.blockUI(this.dpDiv);
296
+ $.data(this._dialogInput[0], PROP_NAME, inst);
297
+ return this;
298
+ },
299
+
300
+ /* Detach a datepicker from its control.
301
+ @param target element - the target input field or division or span */
302
+ _destroyDatepicker: function(target) {
303
+ var $target = $(target);
304
+ if (!$target.hasClass(this.markerClassName)) {
305
+ return;
306
+ }
307
+ var nodeName = target.nodeName.toLowerCase();
308
+ $.removeData(target, PROP_NAME);
309
+ if (nodeName == 'input') {
310
+ $target.siblings('.' + this._appendClass).remove().end().
311
+ siblings('.' + this._triggerClass).remove().end().
312
+ removeClass(this.markerClassName).
313
+ unbind('focus', this._showDatepicker).
314
+ unbind('keydown', this._doKeyDown).
315
+ unbind('keypress', this._doKeyPress);
316
+ } else if (nodeName == 'div' || nodeName == 'span')
317
+ $target.removeClass(this.markerClassName).empty();
318
+ },
319
+
320
+ /* Enable the date picker to a jQuery selection.
321
+ @param target element - the target input field or division or span */
322
+ _enableDatepicker: function(target) {
323
+ var $target = $(target);
324
+ if (!$target.hasClass(this.markerClassName)) {
325
+ return;
326
+ }
327
+ var nodeName = target.nodeName.toLowerCase();
328
+ if (nodeName == 'input') {
329
+ target.disabled = false;
330
+ $target.siblings('button.' + this._triggerClass).
331
+ each(function() { this.disabled = false; }).end().
332
+ siblings('img.' + this._triggerClass).
333
+ css({opacity: '1.0', cursor: ''});
334
+ }
335
+ else if (nodeName == 'div' || nodeName == 'span') {
336
+ $target.children('.' + this._disableClass).remove();
337
+ }
338
+ this._disabledInputs = $.map(this._disabledInputs,
339
+ function(value) { return (value == target ? null : value); }); // delete entry
340
+ },
341
+
342
+ /* Disable the date picker to a jQuery selection.
343
+ @param target element - the target input field or division or span */
344
+ _disableDatepicker: function(target) {
345
+ var $target = $(target);
346
+ if (!$target.hasClass(this.markerClassName)) {
347
+ return;
348
+ }
349
+ var nodeName = target.nodeName.toLowerCase();
350
+ if (nodeName == 'input') {
351
+ target.disabled = true;
352
+ $target.siblings('button.' + this._triggerClass).
353
+ each(function() { this.disabled = true; }).end().
354
+ siblings('img.' + this._triggerClass).
355
+ css({opacity: '0.5', cursor: 'default'});
356
+ }
357
+ else if (nodeName == 'div' || nodeName == 'span') {
358
+ var inline = $target.children('.' + this._inlineClass);
359
+ var offset = inline.offset();
360
+ var relOffset = {left: 0, top: 0};
361
+ inline.parents().each(function() {
362
+ if ($(this).css('position') == 'relative') {
363
+ relOffset = $(this).offset();
364
+ return false;
365
+ }
366
+ });
367
+ $target.prepend('<div class="' + this._disableClass + '" style="' +
368
+ ($.browser.msie ? 'background-color: transparent; ' : '') +
369
+ 'width: ' + inline.width() + 'px; height: ' + inline.height() +
370
+ 'px; left: ' + (offset.left - relOffset.left) +
371
+ 'px; top: ' + (offset.top - relOffset.top) + 'px;"></div>');
372
+ }
373
+ this._disabledInputs = $.map(this._disabledInputs,
374
+ function(value) { return (value == target ? null : value); }); // delete entry
375
+ this._disabledInputs[this._disabledInputs.length] = target;
376
+ },
377
+
378
+ /* Is the first field in a jQuery collection disabled as a datepicker?
379
+ @param target element - the target input field or division or span
380
+ @return boolean - true if disabled, false if enabled */
381
+ _isDisabledDatepicker: function(target) {
382
+ if (!target)
383
+ return false;
384
+ for (var i = 0; i < this._disabledInputs.length; i++) {
385
+ if (this._disabledInputs[i] == target)
386
+ return true;
387
+ }
388
+ return false;
389
+ },
390
+
391
+ /* Retrieve the instance data for the target control.
392
+ @param target element - the target input field or division or span
393
+ @return object - the associated instance data
394
+ @throws error if a jQuery problem getting data */
395
+ _getInst: function(target) {
396
+ try {
397
+ return $.data(target, PROP_NAME);
398
+ }
399
+ catch (err) {
400
+ throw 'Missing instance data for this datepicker';
401
+ }
402
+ },
403
+
404
+ /* Update the settings for a date picker attached to an input field or division.
405
+ @param target element - the target input field or division or span
406
+ @param name object - the new settings to update or
407
+ string - the name of the setting to change or
408
+ @param value any - the new value for the setting (omit if above is an object) */
409
+ _optionDatepicker: function(target, name, value) {
410
+ var settings = name || {};
411
+ if (typeof name == 'string') {
412
+ settings = {};
413
+ settings[name] = value;
414
+ }
415
+ var inst = this._getInst(target);
416
+ if (inst) {
417
+ if (this._curInst == inst) {
418
+ this._hideDatepicker(null);
419
+ }
420
+ extendRemove(inst.settings, settings);
421
+ var date = new Date();
422
+ extendRemove(inst, {rangeStart: null, // start of range
423
+ endDay: null, endMonth: null, endYear: null, // end of range
424
+ selectedDay: date.getDate(), selectedMonth: date.getMonth(),
425
+ selectedYear: date.getFullYear(), // starting point
426
+ currentDay: date.getDate(), currentMonth: date.getMonth(),
427
+ currentYear: date.getFullYear(), // current selection
428
+ drawMonth: date.getMonth(), drawYear: date.getFullYear()}); // month being drawn
429
+ this._updateDatepicker(inst);
430
+ }
431
+ },
432
+
433
+ // change method deprecated
434
+ _changeDatepicker: this._optionDatepicker,
435
+
436
+ /* Redraw the date picker attached to an input field or division.
437
+ @param target element - the target input field or division or span */
438
+ _refreshDatepicker: function(target) {
439
+ var inst = this._getInst(target);
440
+ if (inst) {
441
+ this._updateDatepicker(inst);
442
+ }
443
+ },
444
+
445
+ /* Set the dates for a jQuery selection.
446
+ @param target element - the target input field or division or span
447
+ @param date Date - the new date
448
+ @param endDate Date - the new end date for a range (optional) */
449
+ _setDateDatepicker: function(target, date, endDate) {
450
+ var inst = this._getInst(target);
451
+ if (inst) {
452
+ this._setDate(inst, date, endDate);
453
+ this._updateDatepicker(inst);
454
+ this._updateAlternate(inst);
455
+ }
456
+ },
457
+
458
+ /* Get the date(s) for the first entry in a jQuery selection.
459
+ @param target element - the target input field or division or span
460
+ @return Date - the current date or
461
+ Date[2] - the current dates for a range */
462
+ _getDateDatepicker: function(target) {
463
+ var inst = this._getInst(target);
464
+ if (inst && !inst.inline)
465
+ this._setDateFromField(inst);
466
+ return (inst ? this._getDate(inst) : null);
467
+ },
468
+
469
+ /* Handle keystrokes. */
470
+ _doKeyDown: function(e) {
471
+ var inst = $.datepicker._getInst(e.target);
472
+ var handled = true;
473
+ if ($.datepicker._datepickerShowing)
474
+ switch (e.keyCode) {
475
+ case 9: $.datepicker._hideDatepicker(null, '');
476
+ break; // hide on tab out
477
+ case 13: if ($('td.ui-datepicker-days-cell-over', inst.dpDiv)[0])
478
+ $.datepicker._selectDay(e.target, inst.selectedMonth, inst.selectedYear,
479
+ $('td.ui-datepicker-days-cell-over', inst.dpDiv)[0]);
480
+ return false; // don't submit the form
481
+ break; // select the value on enter
482
+ case 27: $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
483
+ break; // hide on escape
484
+ case 33: $.datepicker._adjustDate(e.target, (e.ctrlKey ?
485
+ -$.datepicker._get(inst, 'stepBigMonths') :
486
+ -$.datepicker._get(inst, 'stepMonths')), 'M');
487
+ break; // previous month/year on page up/+ ctrl
488
+ case 34: $.datepicker._adjustDate(e.target, (e.ctrlKey ?
489
+ +$.datepicker._get(inst, 'stepBigMonths') :
490
+ +$.datepicker._get(inst, 'stepMonths')), 'M');
491
+ break; // next month/year on page down/+ ctrl
492
+ case 35: if (e.ctrlKey || e.metaKey) $.datepicker._clearDate(e.target);
493
+ handled = e.ctrlKey;
494
+ break; // clear on ctrl or command +end
495
+ case 36: if (e.ctrlKey || e.metaKey) $.datepicker._gotoToday(e.target);
496
+ handled = e.ctrlKey;
497
+ break; // current on ctrl or command +home
498
+ case 37: if (e.ctrlKey || e.metaKey) $.datepicker._adjustDate(e.target, -1, 'D');
499
+ handled = e.ctrlKey;
500
+ // -1 day on ctrl or command +left
501
+ if (e.originalEvent.altKey) $.datepicker._adjustDate(e.target, (e.ctrlKey ?
502
+ -$.datepicker._get(inst, 'stepBigMonths') :
503
+ -$.datepicker._get(inst, 'stepMonths')), 'M');
504
+ // next month/year on alt +left on Mac
505
+ break;
506
+ case 38: if (e.ctrlKey || e.metaKey) $.datepicker._adjustDate(e.target, -7, 'D');
507
+ handled = e.ctrlKey;
508
+ break; // -1 week on ctrl or command +up
509
+ case 39: if (e.ctrlKey || e.metaKey) $.datepicker._adjustDate(e.target, +1, 'D');
510
+ handled = e.ctrlKey;
511
+ // +1 day on ctrl or command +right
512
+ if (e.originalEvent.altKey) $.datepicker._adjustDate(e.target, (e.ctrlKey ?
513
+ +$.datepicker._get(inst, 'stepBigMonths') :
514
+ +$.datepicker._get(inst, 'stepMonths')), 'M');
515
+ // next month/year on alt +right
516
+ break;
517
+ case 40: if (e.ctrlKey || e.metaKey) $.datepicker._adjustDate(e.target, +7, 'D');
518
+ handled = e.ctrlKey;
519
+ break; // +1 week on ctrl or command +down
520
+ default: handled = false;
521
+ }
522
+ else if (e.keyCode == 36 && e.ctrlKey) // display the date picker on ctrl+home
523
+ $.datepicker._showDatepicker(this);
524
+ else
525
+ handled = false;
526
+ if (handled) {
527
+ e.preventDefault();
528
+ e.stopPropagation();
529
+ }
530
+ },
531
+
532
+ /* Filter entered characters - based on date format. */
533
+ _doKeyPress: function(e) {
534
+ var inst = $.datepicker._getInst(e.target);
535
+ if ($.datepicker._get(inst, 'constrainInput')) {
536
+ var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
537
+ var chr = String.fromCharCode(e.charCode == undefined ? e.keyCode : e.charCode);
538
+ return e.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
539
+ }
540
+ },
541
+
542
+ /* Pop-up the date picker for a given input field.
543
+ @param input element - the input field attached to the date picker or
544
+ event - if triggered by focus */
545
+ _showDatepicker: function(input) {
546
+ input = input.target || input;
547
+ if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
548
+ input = $('input', input.parentNode)[0];
549
+ if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
550
+ return;
551
+ var inst = $.datepicker._getInst(input);
552
+ var beforeShow = $.datepicker._get(inst, 'beforeShow');
553
+ extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
554
+ $.datepicker._hideDatepicker(null, '');
555
+ $.datepicker._lastInput = input;
556
+ $.datepicker._setDateFromField(inst);
557
+ if ($.datepicker._inDialog) // hide cursor
558
+ input.value = '';
559
+ if (!$.datepicker._pos) { // position below input
560
+ $.datepicker._pos = $.datepicker._findPos(input);
561
+ $.datepicker._pos[1] += input.offsetHeight; // add the height
562
+ }
563
+ var isFixed = false;
564
+ $(input).parents().each(function() {
565
+ isFixed |= $(this).css('position') == 'fixed';
566
+ return !isFixed;
567
+ });
568
+ if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
569
+ $.datepicker._pos[0] -= document.documentElement.scrollLeft;
570
+ $.datepicker._pos[1] -= document.documentElement.scrollTop;
571
+ }
572
+ var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
573
+ $.datepicker._pos = null;
574
+ inst.rangeStart = null;
575
+ // determine sizing offscreen
576
+ inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
577
+ $.datepicker._updateDatepicker(inst);
578
+ // fix width for dynamic number of date pickers
579
+ inst.dpDiv.width($.datepicker._getNumberOfMonths(inst)[1] *
580
+ $('.ui-datepicker', inst.dpDiv[0])[0].offsetWidth);
581
+ // and adjust position before showing
582
+ offset = $.datepicker._checkOffset(inst, offset, isFixed);
583
+ inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
584
+ 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
585
+ left: offset.left + 'px', top: offset.top + 'px'});
586
+ if (!inst.inline) {
587
+ var showAnim = $.datepicker._get(inst, 'showAnim') || 'show';
588
+ var duration = $.datepicker._get(inst, 'duration');
589
+ var postProcess = function() {
590
+ $.datepicker._datepickerShowing = true;
591
+ if ($.browser.msie && parseInt($.browser.version,10) < 7) // fix IE < 7 select problems
592
+ $('iframe.ui-datepicker-cover').css({width: inst.dpDiv.width() + 4,
593
+ height: inst.dpDiv.height() + 4});
594
+ };
595
+ if ($.effects && $.effects[showAnim])
596
+ inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
597
+ else
598
+ inst.dpDiv[showAnim](duration, postProcess);
599
+ if (duration == '')
600
+ postProcess();
601
+ if (inst.input[0].type != 'hidden')
602
+ inst.input[0].focus();
603
+ $.datepicker._curInst = inst;
604
+ }
605
+ },
606
+
607
+ /* Generate the date picker content. */
608
+ _updateDatepicker: function(inst) {
609
+ var dims = {width: inst.dpDiv.width() + 4,
610
+ height: inst.dpDiv.height() + 4};
611
+ inst.dpDiv.empty().append(this._generateHTML(inst)).
612
+ find('iframe.ui-datepicker-cover').
613
+ css({width: dims.width, height: dims.height});
614
+ var numMonths = this._getNumberOfMonths(inst);
615
+ inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
616
+ 'Class']('ui-datepicker-multi');
617
+ inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
618
+ 'Class']('ui-datepicker-rtl');
619
+ if (inst.input && inst.input[0].type != 'hidden' && inst == $.datepicker._curInst)
620
+ $(inst.input[0]).focus();
621
+ },
622
+
623
+ /* Check positioning to remain on screen. */
624
+ _checkOffset: function(inst, offset, isFixed) {
625
+ var pos = inst.input ? this._findPos(inst.input[0]) : null;
626
+ var browserWidth = window.innerWidth || (document.documentElement ?
627
+ document.documentElement.clientWidth : document.body.clientWidth);
628
+ var browserHeight = window.innerHeight || (document.documentElement ?
629
+ document.documentElement.clientHeight : document.body.clientHeight);
630
+ var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
631
+ var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
632
+ // reposition date picker horizontally if outside the browser window
633
+ if (this._get(inst, 'isRTL') || (offset.left + inst.dpDiv.width() - scrollX) > browserWidth)
634
+ offset.left = Math.max((isFixed ? 0 : scrollX),
635
+ pos[0] + (inst.input ? inst.input.width() : 0) - (isFixed ? scrollX : 0) - inst.dpDiv.width() -
636
+ (isFixed && $.browser.opera ? document.documentElement.scrollLeft : 0));
637
+ else
638
+ offset.left -= (isFixed ? scrollX : 0);
639
+ // reposition date picker vertically if outside the browser window
640
+ if ((offset.top + inst.dpDiv.height() - scrollY) > browserHeight)
641
+ offset.top = Math.max((isFixed ? 0 : scrollY),
642
+ pos[1] - (isFixed ? scrollY : 0) - (this._inDialog ? 0 : inst.dpDiv.height()) -
643
+ (isFixed && $.browser.opera ? document.documentElement.scrollTop : 0));
644
+ else
645
+ offset.top -= (isFixed ? scrollY : 0);
646
+ return offset;
647
+ },
648
+
649
+ /* Find an object's position on the screen. */
650
+ _findPos: function(obj) {
651
+ while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
652
+ obj = obj.nextSibling;
653
+ }
654
+ var position = $(obj).offset();
655
+ return [position.left, position.top];
656
+ },
657
+
658
+ /* Hide the date picker from view.
659
+ @param input element - the input field attached to the date picker
660
+ @param duration string - the duration over which to close the date picker */
661
+ _hideDatepicker: function(input, duration) {
662
+ var inst = this._curInst;
663
+ if (!inst || (input && inst != $.data(input, PROP_NAME)))
664
+ return;
665
+ var rangeSelect = this._get(inst, 'rangeSelect');
666
+ if (rangeSelect && inst.stayOpen)
667
+ this._selectDate('#' + inst.id, this._formatDate(inst,
668
+ inst.currentDay, inst.currentMonth, inst.currentYear));
669
+ inst.stayOpen = false;
670
+ if (this._datepickerShowing) {
671
+ duration = (duration != null ? duration : this._get(inst, 'duration'));
672
+ var showAnim = this._get(inst, 'showAnim');
673
+ var postProcess = function() {
674
+ $.datepicker._tidyDialog(inst);
675
+ };
676
+ if (duration != '' && $.effects && $.effects[showAnim])
677
+ inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'),
678
+ duration, postProcess);
679
+ else
680
+ inst.dpDiv[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' :
681
+ (showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess);
682
+ if (duration == '')
683
+ this._tidyDialog(inst);
684
+ var onClose = this._get(inst, 'onClose');
685
+ if (onClose)
686
+ onClose.apply((inst.input ? inst.input[0] : null),
687
+ [(inst.input ? inst.input.val() : ''), inst]); // trigger custom callback
688
+ this._datepickerShowing = false;
689
+ this._lastInput = null;
690
+ inst.settings.prompt = null;
691
+ if (this._inDialog) {
692
+ this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
693
+ if ($.blockUI) {
694
+ $.unblockUI();
695
+ $('body').append(this.dpDiv);
696
+ }
697
+ }
698
+ this._inDialog = false;
699
+ }
700
+ this._curInst = null;
701
+ },
702
+
703
+ /* Tidy up after a dialog display. */
704
+ _tidyDialog: function(inst) {
705
+ inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker');
706
+ $('.' + this._promptClass, inst.dpDiv).remove();
707
+ },
708
+
709
+ /* Close date picker if clicked elsewhere. */
710
+ _checkExternalClick: function(event) {
711
+ if (!$.datepicker._curInst)
712
+ return;
713
+ var $target = $(event.target);
714
+ if (($target.parents('#' + $.datepicker._mainDivId).length == 0) &&
715
+ !$target.hasClass($.datepicker.markerClassName) &&
716
+ !$target.hasClass($.datepicker._triggerClass) &&
717
+ $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
718
+ $.datepicker._hideDatepicker(null, '');
719
+ },
720
+
721
+ /* Adjust one of the date sub-fields. */
722
+ _adjustDate: function(id, offset, period) {
723
+ var target = $(id);
724
+ var inst = this._getInst(target[0]);
725
+ this._adjustInstDate(inst, offset, period);
726
+ this._updateDatepicker(inst);
727
+ },
728
+
729
+ /* Action for current link. */
730
+ _gotoToday: function(id) {
731
+ var target = $(id);
732
+ var inst = this._getInst(target[0]);
733
+ if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
734
+ inst.selectedDay = inst.currentDay;
735
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth;
736
+ inst.drawYear = inst.selectedYear = inst.currentYear;
737
+ }
738
+ else {
739
+ var date = new Date();
740
+ inst.selectedDay = date.getDate();
741
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
742
+ inst.drawYear = inst.selectedYear = date.getFullYear();
743
+ }
744
+ this._notifyChange(inst);
745
+ this._adjustDate(target);
746
+ },
747
+
748
+ /* Action for selecting a new month/year. */
749
+ _selectMonthYear: function(id, select, period) {
750
+ var target = $(id);
751
+ var inst = this._getInst(target[0]);
752
+ inst._selectingMonthYear = false;
753
+ inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
754
+ inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
755
+ parseInt(select.options[select.selectedIndex].value,10);
756
+ this._notifyChange(inst);
757
+ this._adjustDate(target);
758
+ },
759
+
760
+ /* Restore input focus after not changing month/year. */
761
+ _clickMonthYear: function(id) {
762
+ var target = $(id);
763
+ var inst = this._getInst(target[0]);
764
+ if (inst.input && inst._selectingMonthYear && !$.browser.msie)
765
+ inst.input[0].focus();
766
+ inst._selectingMonthYear = !inst._selectingMonthYear;
767
+ },
768
+
769
+ /* Action for changing the first week day. */
770
+ _changeFirstDay: function(id, day) {
771
+ var target = $(id);
772
+ var inst = this._getInst(target[0]);
773
+ inst.settings.firstDay = day;
774
+ this._updateDatepicker(inst);
775
+ },
776
+
777
+ /* Action for selecting a day. */
778
+ _selectDay: function(id, month, year, td) {
779
+ if ($(td).hasClass(this._unselectableClass))
780
+ return;
781
+ var target = $(id);
782
+ var inst = this._getInst(target[0]);
783
+ var rangeSelect = this._get(inst, 'rangeSelect');
784
+ if (rangeSelect) {
785
+ inst.stayOpen = !inst.stayOpen;
786
+ if (inst.stayOpen) {
787
+ $('.ui-datepicker td', inst.dpDiv).removeClass(this._currentClass);
788
+ $(td).addClass(this._currentClass);
789
+ }
790
+ }
791
+ inst.selectedDay = inst.currentDay = $('a', td).html();
792
+ inst.selectedMonth = inst.currentMonth = month;
793
+ inst.selectedYear = inst.currentYear = year;
794
+ if (inst.stayOpen) {
795
+ inst.endDay = inst.endMonth = inst.endYear = null;
796
+ }
797
+ else if (rangeSelect) {
798
+ inst.endDay = inst.currentDay;
799
+ inst.endMonth = inst.currentMonth;
800
+ inst.endYear = inst.currentYear;
801
+ }
802
+ this._selectDate(id, this._formatDate(inst,
803
+ inst.currentDay, inst.currentMonth, inst.currentYear));
804
+ if (inst.stayOpen) {
805
+ inst.rangeStart = new Date(inst.currentYear, inst.currentMonth, inst.currentDay);
806
+ this._updateDatepicker(inst);
807
+ }
808
+ else if (rangeSelect) {
809
+ inst.selectedDay = inst.currentDay = inst.rangeStart.getDate();
810
+ inst.selectedMonth = inst.currentMonth = inst.rangeStart.getMonth();
811
+ inst.selectedYear = inst.currentYear = inst.rangeStart.getFullYear();
812
+ inst.rangeStart = null;
813
+ if (inst.inline)
814
+ this._updateDatepicker(inst);
815
+ }
816
+ },
817
+
818
+ /* Erase the input field and hide the date picker. */
819
+ _clearDate: function(id) {
820
+ var target = $(id);
821
+ var inst = this._getInst(target[0]);
822
+ if (this._get(inst, 'mandatory'))
823
+ return;
824
+ inst.stayOpen = false;
825
+ inst.endDay = inst.endMonth = inst.endYear = inst.rangeStart = null;
826
+ this._selectDate(target, '');
827
+ },
828
+
829
+ /* Update the input field with the selected date. */
830
+ _selectDate: function(id, dateStr) {
831
+ var target = $(id);
832
+ var inst = this._getInst(target[0]);
833
+ dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
834
+ if (this._get(inst, 'rangeSelect') && dateStr)
835
+ dateStr = (inst.rangeStart ? this._formatDate(inst, inst.rangeStart) :
836
+ dateStr) + this._get(inst, 'rangeSeparator') + dateStr;
837
+ if (inst.input)
838
+ inst.input.val(dateStr);
839
+ this._updateAlternate(inst);
840
+ var onSelect = this._get(inst, 'onSelect');
841
+ if (onSelect)
842
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
843
+ else if (inst.input)
844
+ inst.input.trigger('change'); // fire the change event
845
+ if (inst.inline)
846
+ this._updateDatepicker(inst);
847
+ else if (!inst.stayOpen) {
848
+ this._hideDatepicker(null, this._get(inst, 'duration'));
849
+ this._lastInput = inst.input[0];
850
+ if (typeof(inst.input[0]) != 'object')
851
+ inst.input[0].focus(); // restore focus
852
+ this._lastInput = null;
853
+ }
854
+ },
855
+
856
+ /* Update any alternate field to synchronise with the main field. */
857
+ _updateAlternate: function(inst) {
858
+ var altField = this._get(inst, 'altField');
859
+ if (altField) { // update alternate field too
860
+ var altFormat = this._get(inst, 'altFormat');
861
+ var date = this._getDate(inst);
862
+ dateStr = (isArray(date) ? (!date[0] && !date[1] ? '' :
863
+ this.formatDate(altFormat, date[0], this._getFormatConfig(inst)) +
864
+ this._get(inst, 'rangeSeparator') + this.formatDate(
865
+ altFormat, date[1] || date[0], this._getFormatConfig(inst))) :
866
+ this.formatDate(altFormat, date, this._getFormatConfig(inst)));
867
+ $(altField).each(function() { $(this).val(dateStr); });
868
+ }
869
+ },
870
+
871
+ /* Set as beforeShowDay function to prevent selection of weekends.
872
+ @param date Date - the date to customise
873
+ @return [boolean, string] - is this date selectable?, what is its CSS class? */
874
+ noWeekends: function(date) {
875
+ var day = date.getDay();
876
+ return [(day > 0 && day < 6), ''];
877
+ },
878
+
879
+ /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
880
+ @param date Date - the date to get the week for
881
+ @return number - the number of the week within the year that contains this date */
882
+ iso8601Week: function(date) {
883
+ var checkDate = new Date(date.getFullYear(), date.getMonth(), date.getDate(),
884
+ (date.getTimezoneOffset() / -60));
885
+ var firstMon = new Date(checkDate.getFullYear(), 1 - 1, 4); // First week always contains 4 Jan
886
+ var firstDay = firstMon.getDay() || 7; // Day of week: Mon = 1, ..., Sun = 7
887
+ firstMon.setDate(firstMon.getDate() + 1 - firstDay); // Preceding Monday
888
+ if (firstDay < 4 && checkDate < firstMon) { // Adjust first three days in year if necessary
889
+ checkDate.setDate(checkDate.getDate() - 3); // Generate for previous year
890
+ return $.datepicker.iso8601Week(checkDate);
891
+ } else if (checkDate > new Date(checkDate.getFullYear(), 12 - 1, 28)) { // Check last three days in year
892
+ firstDay = new Date(checkDate.getFullYear() + 1, 1 - 1, 4).getDay() || 7;
893
+ if (firstDay > 4 && (checkDate.getDay() || 7) < firstDay - 3) { // Adjust if necessary
894
+ return 1;
895
+ }
896
+ }
897
+ return Math.floor(((checkDate - firstMon) / 86400000) / 7) + 1; // Weeks to given date
898
+ },
899
+
900
+ /* Provide status text for a particular date.
901
+ @param date the date to get the status for
902
+ @param inst the current datepicker instance
903
+ @return the status display text for this date */
904
+ dateStatus: function(date, inst) {
905
+ return $.datepicker.formatDate($.datepicker._get(inst, 'dateStatus'),
906
+ date, $.datepicker._getFormatConfig(inst));
907
+ },
908
+
909
+ /* Parse a string value into a date object.
910
+ See formatDate below for the possible formats.
911
+
912
+ @param format string - the expected format of the date
913
+ @param value string - the date in the above format
914
+ @param settings Object - attributes include:
915
+ shortYearCutoff number - the cutoff year for determining the century (optional)
916
+ dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
917
+ dayNames string[7] - names of the days from Sunday (optional)
918
+ monthNamesShort string[12] - abbreviated names of the months (optional)
919
+ monthNames string[12] - names of the months (optional)
920
+ @return Date - the extracted date value or null if value is blank */
921
+ parseDate: function (format, value, settings) {
922
+ if (format == null || value == null)
923
+ throw 'Invalid arguments';
924
+ value = (typeof value == 'object' ? value.toString() : value + '');
925
+ if (value == '')
926
+ return null;
927
+ var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
928
+ var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
929
+ var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
930
+ var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
931
+ var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
932
+ var year = -1;
933
+ var month = -1;
934
+ var day = -1;
935
+ var doy = -1;
936
+ var literal = false;
937
+ // Check whether a format character is doubled
938
+ var lookAhead = function(match) {
939
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
940
+ if (matches)
941
+ iFormat++;
942
+ return matches;
943
+ };
944
+ // Extract a number from the string value
945
+ var getNumber = function(match) {
946
+ lookAhead(match);
947
+ var origSize = (match == '@' ? 14 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2)));
948
+ var size = origSize;
949
+ var num = 0;
950
+ while (size > 0 && iValue < value.length &&
951
+ value.charAt(iValue) >= '0' && value.charAt(iValue) <= '9') {
952
+ num = num * 10 + parseInt(value.charAt(iValue++),10);
953
+ size--;
954
+ }
955
+ if (size == origSize)
956
+ throw 'Missing number at position ' + iValue;
957
+ return num;
958
+ };
959
+ // Extract a name from the string value and convert to an index
960
+ var getName = function(match, shortNames, longNames) {
961
+ var names = (lookAhead(match) ? longNames : shortNames);
962
+ var size = 0;
963
+ for (var j = 0; j < names.length; j++)
964
+ size = Math.max(size, names[j].length);
965
+ var name = '';
966
+ var iInit = iValue;
967
+ while (size > 0 && iValue < value.length) {
968
+ name += value.charAt(iValue++);
969
+ for (var i = 0; i < names.length; i++)
970
+ if (name == names[i])
971
+ return i + 1;
972
+ size--;
973
+ }
974
+ throw 'Unknown name at position ' + iInit;
975
+ };
976
+ // Confirm that a literal character matches the string value
977
+ var checkLiteral = function() {
978
+ if (value.charAt(iValue) != format.charAt(iFormat))
979
+ throw 'Unexpected literal at position ' + iValue;
980
+ iValue++;
981
+ };
982
+ var iValue = 0;
983
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
984
+ if (literal)
985
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
986
+ literal = false;
987
+ else
988
+ checkLiteral();
989
+ else
990
+ switch (format.charAt(iFormat)) {
991
+ case 'd':
992
+ day = getNumber('d');
993
+ break;
994
+ case 'D':
995
+ getName('D', dayNamesShort, dayNames);
996
+ break;
997
+ case 'o':
998
+ doy = getNumber('o');
999
+ break;
1000
+ case 'm':
1001
+ month = getNumber('m');
1002
+ break;
1003
+ case 'M':
1004
+ month = getName('M', monthNamesShort, monthNames);
1005
+ break;
1006
+ case 'y':
1007
+ year = getNumber('y');
1008
+ break;
1009
+ case '@':
1010
+ var date = new Date(getNumber('@'));
1011
+ year = date.getFullYear();
1012
+ month = date.getMonth() + 1;
1013
+ day = date.getDate();
1014
+ break;
1015
+ case "'":
1016
+ if (lookAhead("'"))
1017
+ checkLiteral();
1018
+ else
1019
+ literal = true;
1020
+ break;
1021
+ default:
1022
+ checkLiteral();
1023
+ }
1024
+ }
1025
+ if (year < 100)
1026
+ year += new Date().getFullYear() - new Date().getFullYear() % 100 +
1027
+ (year <= shortYearCutoff ? 0 : -100);
1028
+ if (doy > -1) {
1029
+ month = 1;
1030
+ day = doy;
1031
+ do {
1032
+ var dim = this._getDaysInMonth(year, month - 1);
1033
+ if (day <= dim)
1034
+ break;
1035
+ month++;
1036
+ day -= dim;
1037
+ } while (true);
1038
+ }
1039
+ var date = new Date(year, month - 1, day);
1040
+ if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
1041
+ throw 'Invalid date'; // E.g. 31/02/*
1042
+ return date;
1043
+ },
1044
+
1045
+ /* Standard date formats. */
1046
+ ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
1047
+ COOKIE: 'D, dd M yy',
1048
+ ISO_8601: 'yy-mm-dd',
1049
+ RFC_822: 'D, d M y',
1050
+ RFC_850: 'DD, dd-M-y',
1051
+ RFC_1036: 'D, d M y',
1052
+ RFC_1123: 'D, d M yy',
1053
+ RFC_2822: 'D, d M yy',
1054
+ RSS: 'D, d M y', // RFC 822
1055
+ TIMESTAMP: '@',
1056
+ W3C: 'yy-mm-dd', // ISO 8601
1057
+
1058
+ /* Format a date object into a string value.
1059
+ The format can be combinations of the following:
1060
+ d - day of month (no leading zero)
1061
+ dd - day of month (two digit)
1062
+ o - day of year (no leading zeros)
1063
+ oo - day of year (three digit)
1064
+ D - day name short
1065
+ DD - day name long
1066
+ m - month of year (no leading zero)
1067
+ mm - month of year (two digit)
1068
+ M - month name short
1069
+ MM - month name long
1070
+ y - year (two digit)
1071
+ yy - year (four digit)
1072
+ @ - Unix timestamp (ms since 01/01/1970)
1073
+ '...' - literal text
1074
+ '' - single quote
1075
+
1076
+ @param format string - the desired format of the date
1077
+ @param date Date - the date value to format
1078
+ @param settings Object - attributes include:
1079
+ dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
1080
+ dayNames string[7] - names of the days from Sunday (optional)
1081
+ monthNamesShort string[12] - abbreviated names of the months (optional)
1082
+ monthNames string[12] - names of the months (optional)
1083
+ @return string - the date in the above format */
1084
+ formatDate: function (format, date, settings) {
1085
+ if (!date)
1086
+ return '';
1087
+ var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
1088
+ var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
1089
+ var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
1090
+ var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
1091
+ // Check whether a format character is doubled
1092
+ var lookAhead = function(match) {
1093
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
1094
+ if (matches)
1095
+ iFormat++;
1096
+ return matches;
1097
+ };
1098
+ // Format a number, with leading zero if necessary
1099
+ var formatNumber = function(match, value, len) {
1100
+ var num = '' + value;
1101
+ if (lookAhead(match))
1102
+ while (num.length < len)
1103
+ num = '0' + num;
1104
+ return num;
1105
+ };
1106
+ // Format a name, short or long as requested
1107
+ var formatName = function(match, value, shortNames, longNames) {
1108
+ return (lookAhead(match) ? longNames[value] : shortNames[value]);
1109
+ };
1110
+ var output = '';
1111
+ var literal = false;
1112
+ if (date)
1113
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
1114
+ if (literal)
1115
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
1116
+ literal = false;
1117
+ else
1118
+ output += format.charAt(iFormat);
1119
+ else
1120
+ switch (format.charAt(iFormat)) {
1121
+ case 'd':
1122
+ output += formatNumber('d', date.getDate(), 2);
1123
+ break;
1124
+ case 'D':
1125
+ output += formatName('D', date.getDay(), dayNamesShort, dayNames);
1126
+ break;
1127
+ case 'o':
1128
+ var doy = date.getDate();
1129
+ for (var m = date.getMonth() - 1; m >= 0; m--)
1130
+ doy += this._getDaysInMonth(date.getFullYear(), m);
1131
+ output += formatNumber('o', doy, 3);
1132
+ break;
1133
+ case 'm':
1134
+ output += formatNumber('m', date.getMonth() + 1, 2);
1135
+ break;
1136
+ case 'M':
1137
+ output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
1138
+ break;
1139
+ case 'y':
1140
+ output += (lookAhead('y') ? date.getFullYear() :
1141
+ (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
1142
+ break;
1143
+ case '@':
1144
+ output += date.getTime();
1145
+ break;
1146
+ case "'":
1147
+ if (lookAhead("'"))
1148
+ output += "'";
1149
+ else
1150
+ literal = true;
1151
+ break;
1152
+ default:
1153
+ output += format.charAt(iFormat);
1154
+ }
1155
+ }
1156
+ return output;
1157
+ },
1158
+
1159
+ /* Extract all possible characters from the date format. */
1160
+ _possibleChars: function (format) {
1161
+ var chars = '';
1162
+ var literal = false;
1163
+ for (var iFormat = 0; iFormat < format.length; iFormat++)
1164
+ if (literal)
1165
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
1166
+ literal = false;
1167
+ else
1168
+ chars += format.charAt(iFormat);
1169
+ else
1170
+ switch (format.charAt(iFormat)) {
1171
+ case 'd': case 'm': case 'y': case '@':
1172
+ chars += '0123456789';
1173
+ break;
1174
+ case 'D': case 'M':
1175
+ return null; // Accept anything
1176
+ case "'":
1177
+ if (lookAhead("'"))
1178
+ chars += "'";
1179
+ else
1180
+ literal = true;
1181
+ break;
1182
+ default:
1183
+ chars += format.charAt(iFormat);
1184
+ }
1185
+ return chars;
1186
+ },
1187
+
1188
+ /* Get a setting value, defaulting if necessary. */
1189
+ _get: function(inst, name) {
1190
+ return inst.settings[name] !== undefined ?
1191
+ inst.settings[name] : this._defaults[name];
1192
+ },
1193
+
1194
+ /* Parse existing date and initialise date picker. */
1195
+ _setDateFromField: function(inst) {
1196
+ var dateFormat = this._get(inst, 'dateFormat');
1197
+ var dates = inst.input ? inst.input.val().split(this._get(inst, 'rangeSeparator')) : null;
1198
+ inst.endDay = inst.endMonth = inst.endYear = null;
1199
+ var date = defaultDate = this._getDefaultDate(inst);
1200
+ if (dates.length > 0) {
1201
+ var settings = this._getFormatConfig(inst);
1202
+ if (dates.length > 1) {
1203
+ date = this.parseDate(dateFormat, dates[1], settings) || defaultDate;
1204
+ inst.endDay = date.getDate();
1205
+ inst.endMonth = date.getMonth();
1206
+ inst.endYear = date.getFullYear();
1207
+ }
1208
+ try {
1209
+ date = this.parseDate(dateFormat, dates[0], settings) || defaultDate;
1210
+ } catch (e) {
1211
+ this.log(e);
1212
+ date = defaultDate;
1213
+ }
1214
+ }
1215
+ inst.selectedDay = date.getDate();
1216
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
1217
+ inst.drawYear = inst.selectedYear = date.getFullYear();
1218
+ inst.currentDay = (dates[0] ? date.getDate() : 0);
1219
+ inst.currentMonth = (dates[0] ? date.getMonth() : 0);
1220
+ inst.currentYear = (dates[0] ? date.getFullYear() : 0);
1221
+ this._adjustInstDate(inst);
1222
+ },
1223
+
1224
+ /* Retrieve the default date shown on opening. */
1225
+ _getDefaultDate: function(inst) {
1226
+ var date = this._determineDate(this._get(inst, 'defaultDate'), new Date());
1227
+ var minDate = this._getMinMaxDate(inst, 'min', true);
1228
+ var maxDate = this._getMinMaxDate(inst, 'max');
1229
+ date = (minDate && date < minDate ? minDate : date);
1230
+ date = (maxDate && date > maxDate ? maxDate : date);
1231
+ return date;
1232
+ },
1233
+
1234
+ /* A date may be specified as an exact value or a relative one. */
1235
+ _determineDate: function(date, defaultDate) {
1236
+ var offsetNumeric = function(offset) {
1237
+ var date = new Date();
1238
+ date.setUTCDate(date.getUTCDate() + offset);
1239
+ return date;
1240
+ };
1241
+ var offsetString = function(offset, getDaysInMonth) {
1242
+ var date = new Date();
1243
+ var year = date.getFullYear();
1244
+ var month = date.getMonth();
1245
+ var day = date.getDate();
1246
+ var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
1247
+ var matches = pattern.exec(offset);
1248
+ while (matches) {
1249
+ switch (matches[2] || 'd') {
1250
+ case 'd' : case 'D' :
1251
+ day += parseInt(matches[1],10); break;
1252
+ case 'w' : case 'W' :
1253
+ day += parseInt(matches[1],10) * 7; break;
1254
+ case 'm' : case 'M' :
1255
+ month += parseInt(matches[1],10);
1256
+ day = Math.min(day, getDaysInMonth(year, month));
1257
+ break;
1258
+ case 'y': case 'Y' :
1259
+ year += parseInt(matches[1],10);
1260
+ day = Math.min(day, getDaysInMonth(year, month));
1261
+ break;
1262
+ }
1263
+ matches = pattern.exec(offset);
1264
+ }
1265
+ return new Date(year, month, day);
1266
+ };
1267
+ date = (date == null ? defaultDate :
1268
+ (typeof date == 'string' ? offsetString(date, this._getDaysInMonth) :
1269
+ (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
1270
+ return (date && date.toString() == 'Invalid Date' ? defaultDate : date);
1271
+ },
1272
+
1273
+ /* Set the date(s) directly. */
1274
+ _setDate: function(inst, date, endDate) {
1275
+ var clear = !(date);
1276
+ var origMonth = inst.selectedMonth;
1277
+ var origYear = inst.selectedYear;
1278
+ date = this._determineDate(date, new Date());
1279
+ inst.selectedDay = inst.currentDay = date.getDate();
1280
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
1281
+ inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
1282
+ if (this._get(inst, 'rangeSelect')) {
1283
+ if (endDate) {
1284
+ endDate = this._determineDate(endDate, null);
1285
+ inst.endDay = endDate.getDate();
1286
+ inst.endMonth = endDate.getMonth();
1287
+ inst.endYear = endDate.getFullYear();
1288
+ } else {
1289
+ inst.endDay = inst.currentDay;
1290
+ inst.endMonth = inst.currentMonth;
1291
+ inst.endYear = inst.currentYear;
1292
+ }
1293
+ }
1294
+ if (origMonth != inst.selectedMonth || origYear != inst.selectedYear)
1295
+ this._notifyChange(inst);
1296
+ this._adjustInstDate(inst);
1297
+ if (inst.input)
1298
+ inst.input.val(clear ? '' : this._formatDate(inst) +
1299
+ (!this._get(inst, 'rangeSelect') ? '' : this._get(inst, 'rangeSeparator') +
1300
+ this._formatDate(inst, inst.endDay, inst.endMonth, inst.endYear)));
1301
+ },
1302
+
1303
+ /* Retrieve the date(s) directly. */
1304
+ _getDate: function(inst) {
1305
+ var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
1306
+ new Date(inst.currentYear, inst.currentMonth, inst.currentDay));
1307
+ if (this._get(inst, 'rangeSelect')) {
1308
+ return [inst.rangeStart || startDate,
1309
+ (!inst.endYear ? inst.rangeStart || startDate :
1310
+ new Date(inst.endYear, inst.endMonth, inst.endDay))];
1311
+ } else
1312
+ return startDate;
1313
+ },
1314
+
1315
+ /* Generate the HTML for the current state of the date picker. */
1316
+ _generateHTML: function(inst) {
1317
+ var today = new Date();
1318
+ today = new Date(today.getFullYear(), today.getMonth(), today.getDate()); // clear time
1319
+ var showStatus = this._get(inst, 'showStatus');
1320
+ var initStatus = this._get(inst, 'initStatus') || '&#xa0;';
1321
+ var isRTL = this._get(inst, 'isRTL');
1322
+ // build the date picker HTML
1323
+ var clear = (this._get(inst, 'mandatory') ? '' :
1324
+ '<div class="ui-datepicker-clear"><a onclick="jQuery.datepicker._clearDate(\'#' + inst.id + '\');"' +
1325
+ this._addStatus(showStatus, inst.id, this._get(inst, 'clearStatus'), initStatus) + '>' +
1326
+ this._get(inst, 'clearText') + '</a></div>');
1327
+ var controls = '<div class="ui-datepicker-control">' + (isRTL ? '' : clear) +
1328
+ '<div class="ui-datepicker-close"><a onclick="jQuery.datepicker._hideDatepicker();"' +
1329
+ this._addStatus(showStatus, inst.id, this._get(inst, 'closeStatus'), initStatus) + '>' +
1330
+ this._get(inst, 'closeText') + '</a></div>' + (isRTL ? clear : '') + '</div>';
1331
+ var prompt = this._get(inst, 'prompt');
1332
+ var closeAtTop = this._get(inst, 'closeAtTop');
1333
+ var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
1334
+ var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
1335
+ var showBigPrevNext = this._get(inst, 'showBigPrevNext');
1336
+ var numMonths = this._getNumberOfMonths(inst);
1337
+ var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
1338
+ var stepMonths = this._get(inst, 'stepMonths');
1339
+ var stepBigMonths = this._get(inst, 'stepBigMonths');
1340
+ var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
1341
+ var currentDate = (!inst.currentDay ? new Date(9999, 9, 9) :
1342
+ new Date(inst.currentYear, inst.currentMonth, inst.currentDay));
1343
+ var minDate = this._getMinMaxDate(inst, 'min', true);
1344
+ var maxDate = this._getMinMaxDate(inst, 'max');
1345
+ var drawMonth = inst.drawMonth - showCurrentAtPos;
1346
+ var drawYear = inst.drawYear;
1347
+ if (drawMonth < 0) {
1348
+ drawMonth += 12;
1349
+ drawYear--;
1350
+ }
1351
+ if (maxDate) {
1352
+ var maxDraw = new Date(maxDate.getFullYear(),
1353
+ maxDate.getMonth() - numMonths[1] + 1, maxDate.getDate());
1354
+ maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
1355
+ while (new Date(drawYear, drawMonth, 1) > maxDraw) {
1356
+ drawMonth--;
1357
+ if (drawMonth < 0) {
1358
+ drawMonth = 11;
1359
+ drawYear--;
1360
+ }
1361
+ }
1362
+ }
1363
+ // controls and links
1364
+ var prevText = this._get(inst, 'prevText');
1365
+ prevText = (!navigationAsDateFormat ? prevText : this.formatDate(
1366
+ prevText, new Date(drawYear, drawMonth - stepMonths, 1), this._getFormatConfig(inst)));
1367
+ var prevBigText = (showBigPrevNext ? this._get(inst, 'prevBigText') : '');
1368
+ prevBigText = (!navigationAsDateFormat ? prevBigText : this.formatDate(
1369
+ prevBigText, new Date(drawYear, drawMonth - stepBigMonths, 1), this._getFormatConfig(inst)));
1370
+ var prev = '<div class="ui-datepicker-prev">' + (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
1371
+ (showBigPrevNext ? '<a onclick="jQuery.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepBigMonths + ', \'M\');"' +
1372
+ this._addStatus(showStatus, inst.id, this._get(inst, 'prevBigStatus'), initStatus) + '>' + prevBigText + '</a>' : '') +
1373
+ '<a onclick="jQuery.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
1374
+ this._addStatus(showStatus, inst.id, this._get(inst, 'prevStatus'), initStatus) + '>' + prevText + '</a>' :
1375
+ (hideIfNoPrevNext ? '' : '<label>' + prevBigText + '</label><label>' + prevText + '</label>')) + '</div>';
1376
+ var nextText = this._get(inst, 'nextText');
1377
+ nextText = (!navigationAsDateFormat ? nextText : this.formatDate(
1378
+ nextText, new Date(drawYear, drawMonth + stepMonths, 1), this._getFormatConfig(inst)));
1379
+ var nextBigText = (showBigPrevNext ? this._get(inst, 'nextBigText') : '');
1380
+ nextBigText = (!navigationAsDateFormat ? nextBigText : this.formatDate(
1381
+ nextBigText, new Date(drawYear, drawMonth + stepBigMonths, 1), this._getFormatConfig(inst)));
1382
+ var next = '<div class="ui-datepicker-next">' + (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
1383
+ '<a onclick="jQuery.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
1384
+ this._addStatus(showStatus, inst.id, this._get(inst, 'nextStatus'), initStatus) + '>' + nextText + '</a>' +
1385
+ (showBigPrevNext ? '<a onclick="jQuery.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepBigMonths + ', \'M\');"' +
1386
+ this._addStatus(showStatus, inst.id, this._get(inst, 'nextBigStatus'), initStatus) + '>' + nextBigText + '</a>' : '') :
1387
+ (hideIfNoPrevNext ? '' : '<label>' + nextText + '</label><label>' + nextBigText + '</label>')) + '</div>';
1388
+ var currentText = this._get(inst, 'currentText');
1389
+ var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
1390
+ currentText = (!navigationAsDateFormat ? currentText :
1391