zebra-datepicker-rails 1.9.5 → 1.9.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Rakefile +10 -9
- data/lib/zebra-datepicker-rails/version.rb +1 -1
- data/vendor/assets/images/zebra-datepicker/bootstrap/icons.png +0 -0
- data/vendor/assets/images/zebra-datepicker/default/icons.png +0 -0
- data/vendor/assets/images/zebra-datepicker/metallic/icons.png +0 -0
- data/vendor/assets/javascripts/zebra-datepicker/zebra_datepicker.js +3690 -1
- data/vendor/assets/stylesheets/zebra-datepicker/bootstrap.scss +168 -91
- data/vendor/assets/stylesheets/zebra-datepicker/default.scss +203 -98
- data/vendor/assets/stylesheets/zebra-datepicker/metallic.scss +201 -102
- metadata +6 -10
- data/vendor/assets/images/zebra-datepicker/calendar-disabled.png +0 -0
- data/vendor/assets/images/zebra-datepicker/calendar.png +0 -0
- data/vendor/assets/images/zebra-datepicker/metallic/default-date.png +0 -0
- data/vendor/assets/images/zebra-datepicker/metallic/disabled-date.png +0 -0
- data/vendor/assets/images/zebra-datepicker/metallic/header.png +0 -0
- data/vendor/assets/images/zebra-datepicker/metallic/selected-date.png +0 -0
- data/vendor/assets/javascripts/zebra-datepicker/zebra_datepicker.src.js +0 -3229
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d6273b6b21ad75b9b6225fc2965a7c8a8785cb1a66879e3addc9884bd30ea1df
|
4
|
+
data.tar.gz: 8f8629963e0daac76127243e7c27d53a9a2d5d4f1cf3335f859f33b3e55b3a59
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98d73cad37adfb4db95f145c10e9c506a4069476dbb750658b0d54e08e53d4b2f4fbf11f00d61cf5112e147959fcad2af7218a705b4b6192e7794eed3039f703
|
7
|
+
data.tar.gz: 274d1a1966d1516d2c2d522199853ce993e6915062f0273098de9fbdee06ed2887dd1adfb297d6e2c41a2b12b658f5fdaa4abafd6ec5784fe38146aa75f76ff9
|
data/Rakefile
CHANGED
@@ -4,7 +4,8 @@ desc "Change css url calls to use sass-rails' asset-url"
|
|
4
4
|
task :change_css_url do
|
5
5
|
Dir.chdir('vendor/assets/stylesheets/zebra-datepicker/')
|
6
6
|
Dir.glob('*.scss').each do |filename|
|
7
|
-
|
7
|
+
template = File.basename(filename, '.scss')
|
8
|
+
content = File.read(filename).gsub!(' url("', ' asset-url("zebra-datepicker/' + template + '/')
|
8
9
|
file = File.open(filename, 'w')
|
9
10
|
file.write(content)
|
10
11
|
file.close
|
@@ -14,17 +15,17 @@ end
|
|
14
15
|
desc 'Copy Assets from Zebra_Datepicker'
|
15
16
|
task :copy do
|
16
17
|
{
|
17
|
-
'
|
18
|
-
'
|
19
|
-
'
|
18
|
+
'dist/css/bootstrap/zebra_datepicker.css' => 'vendor/assets/stylesheets/zebra-datepicker/bootstrap.scss',
|
19
|
+
'dist/css/default/zebra_datepicker.css' => 'vendor/assets/stylesheets/zebra-datepicker/default.scss',
|
20
|
+
'dist/css/metallic/zebra_datepicker.css' => 'vendor/assets/stylesheets/zebra-datepicker/metallic.scss',
|
20
21
|
|
21
|
-
'
|
22
|
-
'
|
23
|
-
'
|
22
|
+
'dist/css/bootstrap/icons.png' => 'vendor/assets/images/zebra-datepicker/bootstrap/icons.png',
|
23
|
+
'dist/css/default/icons.png' => 'vendor/assets/images/zebra-datepicker/default/icons.png',
|
24
|
+
'dist/css/metallic/icons.png' => 'vendor/assets/images/zebra-datepicker/metallic/icons.png',
|
24
25
|
|
25
|
-
'
|
26
|
-
'public/javascript/zebra_datepicker.src.js' => 'vendor/assets/javascripts/zebra-datepicker/'
|
26
|
+
'dist/zebra_datepicker.src.js' => 'vendor/assets/javascripts/zebra-datepicker/zebra_datepicker.js'
|
27
27
|
}.each do |src, dest|
|
28
|
+
FileUtils.mkdir_p File.dirname(dest)
|
28
29
|
FileUtils.cp_r("Zebra_Datepicker/#{src}", dest)
|
29
30
|
end
|
30
31
|
end
|
Binary file
|
Binary file
|
Binary file
|
@@ -1 +1,3690 @@
|
|
1
|
-
!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a){"use strict";a.Zebra_DatePicker=function(b,c){var d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q={always_visible:!1,container:a("body"),custom_classes:!1,days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],days_abbr:!1,default_position:"above",direction:0,disabled_dates:!1,enabled_dates:!1,first_day_of_week:1,format:"Y-m-d",header_captions:{days:"F, Y",months:"Y",years:"Y1 - Y2"},header_navigation:["«","»"],icon_position:"right",inside:!0,lang_clear_date:"Clear date",months:["January","February","March","April","May","June","July","August","September","October","November","December"],months_abbr:!1,offset:[5,-5],open_icon_only:!1,pair:!1,readonly_element:!0,select_other_months:!1,show_clear_date:0,show_icon:!0,show_other_months:!0,show_select_today:"Today",show_week_number:!1,start_date:!1,strict:!1,view:"days",weekend_days:[0,6],zero_pad:!1,onChange:null,onClear:null,onOpen:null,onClose:null,onSelect:null},R={},S=this;S.settings={};var T=a(b),U=function(b){if(N=Math.floor(65536*(1+Math.random())).toString(16),!b){S.settings=a.extend({},Q,c),R.readonly=T.attr("readonly"),R.style=T.attr("style");for(var y in T.data())0===y.indexOf("zdp_")&&(y=y.replace(/^zdp\_/,""),void 0!==Q[y]&&(S.settings[y]="pair"==y?a(T.data("zdp_"+y)):T.data("zdp_"+y)))}S.settings.readonly_element&&T.attr("readonly","readonly");var E={days:["d","j","D"],months:["F","m","M","n","t"],years:["o","Y","y"]},F=!1,G=!1,U=!1,X=null;for(X in E)a.each(E[X],function(a,b){S.settings.format.indexOf(b)>-1&&("days"==X?F=!0:"months"==X?G=!0:"years"==X&&(U=!0))});H=F&&G&&U?["years","months","days"]:!F&&G&&U?["years","months"]:F&&G&&!U?["months","days"]:F||G||!U?F||!G||U?["years","months","days"]:["months"]:["years"],-1==a.inArray(S.settings.view,H)&&(S.settings.view=H[H.length-1]),x=[],w=[],O={},P=[];var Y;for(var Z in S.settings.custom_classes)S.settings.custom_classes.hasOwnProperty(Z)&&P.push(Z);for(var $=0;$<2+P.length;$++)Y=0===$?S.settings.disabled_dates:1==$?S.settings.enabled_dates:S.settings.custom_classes[P[$-2]],a.isArray(Y)&&Y.length>0&&a.each(Y,function(){for(var b=this.split(" "),c=0;4>c;c++){b[c]||(b[c]="*"),b[c]=b[c].indexOf(",")>-1?b[c].split(","):new Array(b[c]);for(var d=0;d<b[c].length;d++)if(b[c][d].indexOf("-")>-1){var e=b[c][d].match(/^([0-9]+)\-([0-9]+)/);if(null!==e){for(var f=ja(e[1]);f<=ja(e[2]);f++)-1==a.inArray(f,b[c])&&b[c].push(f+"");b[c].splice(d,1)}}for(d=0;d<b[c].length;d++)b[c][d]=isNaN(ja(b[c][d]))?b[c][d]:ja(b[c][d])}0===$?x.push(b):1==$?w.push(b):(void 0===O[P[$-2]]&&(O[P[$-2]]=[]),O[P[$-2]].push(b))});var _,aa,ba=new Date,ea=S.settings.reference_date?S.settings.reference_date:T.data("zdp_reference_date")&&void 0!==T.data("zdp_reference_date")?T.data("zdp_reference_date"):ba;if(z=void 0,A=void 0,o=ea.getMonth(),l=ba.getMonth(),p=ea.getFullYear(),m=ba.getFullYear(),q=ea.getDate(),n=ba.getDate(),S.settings.direction===!0)z=ea;else if(S.settings.direction===!1)A=ea,D=A.getMonth(),C=A.getFullYear(),B=A.getDate();else if(!a.isArray(S.settings.direction)&&da(S.settings.direction)&&ja(S.settings.direction)>0||a.isArray(S.settings.direction)&&((_=V(S.settings.direction[0]))||S.settings.direction[0]===!0||da(S.settings.direction[0])&&S.settings.direction[0]>0)&&((aa=V(S.settings.direction[1]))||S.settings.direction[1]===!1||da(S.settings.direction[1])&&S.settings.direction[1]>=0))z=_?_:new Date(p,o,q+ja(a.isArray(S.settings.direction)?S.settings.direction[0]===!0?0:S.settings.direction[0]:S.settings.direction)),o=z.getMonth(),p=z.getFullYear(),q=z.getDate(),aa&&+aa>=+z?A=aa:!aa&&S.settings.direction[1]!==!1&&a.isArray(S.settings.direction)&&(A=new Date(p,o,q+ja(S.settings.direction[1]))),A&&(D=A.getMonth(),C=A.getFullYear(),B=A.getDate());else if(!a.isArray(S.settings.direction)&&da(S.settings.direction)&&ja(S.settings.direction)<0||a.isArray(S.settings.direction)&&(S.settings.direction[0]===!1||da(S.settings.direction[0])&&S.settings.direction[0]<0)&&((_=V(S.settings.direction[1]))||da(S.settings.direction[1])&&S.settings.direction[1]>=0))A=new Date(p,o,q+ja(a.isArray(S.settings.direction)?S.settings.direction[0]===!1?0:S.settings.direction[0]:S.settings.direction)),D=A.getMonth(),C=A.getFullYear(),B=A.getDate(),_&&+A>+_?z=_:!_&&a.isArray(S.settings.direction)&&(z=new Date(C,D,B-ja(S.settings.direction[1]))),z&&(o=z.getMonth(),p=z.getFullYear(),q=z.getDate());else if(a.isArray(S.settings.disabled_dates)&&S.settings.disabled_dates.length>0)for(var ha in x)if("*"==x[ha][0]&&"*"==x[ha][1]&&"*"==x[ha][2]&&"*"==x[ha][3]){var la=[];if(a.each(w,function(){var a=this;"*"!=a[2][0]&&la.push(parseInt(a[2][0]+("*"==a[1][0]?"12":ia(a[1][0],2))+("*"==a[0][0]?"*"==a[1][0]?"31":new Date(a[2][0],a[1][0],0).getDate():ia(a[0][0],2)),10))}),la.sort(),la.length>0){var na=(la[0]+"").match(/([0-9]{4})([0-9]{2})([0-9]{2})/);p=parseInt(na[1],10),o=parseInt(na[2],10)-1,q=parseInt(na[3],10)}break}if(ca(p,o,q)){for(;ca(p);)z?(p++,o=0):(p--,o=11);for(;ca(p,o);)z?(o++,q=1):(o--,q=new Date(p,o+1,0).getDate()),o>11?(p++,o=0,q=1):0>o&&(p--,o=11,q=new Date(p,o+1,0).getDate());for(;ca(p,o,q);)z?q++:q--,ba=new Date(p,o,q),p=ba.getFullYear(),o=ba.getMonth(),q=ba.getDate();ba=new Date(p,o,q),p=ba.getFullYear(),o=ba.getMonth(),q=ba.getDate()}var oa=V(T.val()||(S.settings.start_date?S.settings.start_date:""));if(oa&&S.settings.strict&&ca(oa.getFullYear(),oa.getMonth(),oa.getDate())&&T.val(""),b||void 0===z&&void 0===oa||ka(void 0!==oa?oa:z),!S.settings.always_visible){if(!b){if(S.settings.show_icon){"firefox"==ma.name&&T.is('input[type="text"]')&&"inline"==T.css("display")&&T.css("display","inline-block");var pa=a('<span class="Zebra_DatePicker_Icon_Wrapper"></span>').css({display:T.css("display"),position:"static"==T.css("position")?"relative":T.css("position"),"float":T.css("float"),top:T.css("top"),right:T.css("right"),bottom:T.css("bottom"),left:T.css("left")});"block"==T.css("display")&&pa.css("width",T.outerWidth(!0)),T.wrap(pa).css({position:"relative",top:"auto",right:"auto",bottom:"auto",left:"auto"}),f=a('<button type="button" class="Zebra_DatePicker_Icon'+("disabled"==T.attr("disabled")?" Zebra_DatePicker_Icon_Disabled":"")+'">Pick a date</button>'),S.icon=f,I=S.settings.open_icon_only?f:f.add(T)}else I=T;I.bind("click.Zebra_DatePicker_"+N,function(a){a.preventDefault(),T.attr("disabled")||(e.hasClass("dp_visible")?S.hide():S.show())}),!S.settings.readonly_element&&S.settings.pair&&T.bind("blur.Zebra_DatePicker_"+N,function(){var b;(b=V(a(this).val()))&&!ca(b.getFullYear(),b.getMonth(),b.getDate())&&ka(b)}),void 0!==f&&f.insertAfter(T)}if(void 0!==f){f.attr("style",""),S.settings.inside&&f.addClass("Zebra_DatePicker_Icon_Inside_"+("right"==S.settings.icon_position?"Right":"Left"));var qa=T.outerWidth(),ra=T.outerHeight(),sa=parseInt(T.css("marginLeft"),10)||0,ta=parseInt(T.css("marginTop"),10)||0,ua=(f.outerWidth(),f.outerHeight()),va=parseInt(f.css("marginLeft"),10)||0;parseInt(f.css("marginRight"),10)||0;S.settings.inside?(f.css("top",ta+(ra-ua)/2),"right"==S.settings.icon_position?f.css("right",0):f.css("left",0)):f.css({top:ta+(ra-ua)/2,left:sa+qa+va}),f.removeClass(" Zebra_DatePicker_Icon_Disabled"),"disabled"==T.attr("disabled")&&f.addClass("Zebra_DatePicker_Icon_Disabled")}}if(L=S.settings.show_select_today!==!1&&a.inArray("days",H)>-1&&!ca(m,l,n)?S.settings.show_select_today:!1,b)return a(".dp_previous",e).html(S.settings.header_navigation[0]),a(".dp_next",e).html(S.settings.header_navigation[1]),a(".dp_clear",e).html(S.settings.lang_clear_date),void a(".dp_today",e).html(S.settings.show_select_today);a(window).bind("resize.Zebra_DatePicker_"+N+", orientationchange.Zebra_DatePicker_"+N,function(){S.hide(),void 0!==f&&(clearTimeout(M),M=setTimeout(function(){S.update()},100))});var wa='<div class="Zebra_DatePicker"><table class="dp_header"><tr><td class="dp_previous">'+S.settings.header_navigation[0]+'</td><td class="dp_caption"> </td><td class="dp_next">'+S.settings.header_navigation[1]+'</td></tr></table><table class="dp_daypicker"></table><table class="dp_monthpicker"></table><table class="dp_yearpicker"></table><table class="dp_footer"><tr><td class="dp_today"'+(S.settings.show_clear_date!==!1?' style="width:50%"':"")+">"+L+'</td><td class="dp_clear"'+(L!==!1?' style="width:50%"':"")+">"+S.settings.lang_clear_date+"</td></tr></table></div>";e=a(wa),S.datepicker=e,g=a("table.dp_header",e),h=a("table.dp_daypicker",e),i=a("table.dp_monthpicker",e),j=a("table.dp_yearpicker",e),K=a("table.dp_footer",e),J=a("td.dp_today",K),k=a("td.dp_clear",K),S.settings.always_visible?T.attr("disabled")||(S.settings.always_visible.append(e),S.show()):S.settings.container.append(e),e.delegate("td:not(.dp_disabled, .dp_weekend_disabled, .dp_not_in_month, .dp_week_number)","mouseover",function(){a(this).addClass("dp_hover")}).delegate("td:not(.dp_disabled, .dp_weekend_disabled, .dp_not_in_month, .dp_week_number)","mouseout",function(){a(this).removeClass("dp_hover")}),W(a("td",g)),a(".dp_previous",g).bind("click",function(){"months"==d?s--:"years"==d?s-=12:--r<0&&(r=11,s--),fa()}),a(".dp_caption",g).bind("click",function(){d="days"==d?a.inArray("months",H)>-1?"months":a.inArray("years",H)>-1?"years":"days":"months"==d?a.inArray("years",H)>-1?"years":a.inArray("days",H)>-1?"days":"months":a.inArray("days",H)>-1?"days":a.inArray("months",H)>-1?"months":"years",fa()}),a(".dp_next",g).bind("click",function(){"months"==d?s++:"years"==d?s+=12:12==++r&&(r=0,s++),fa()}),h.delegate("td:not(.dp_disabled, .dp_weekend_disabled, .dp_not_in_month, .dp_week_number)","click",function(){S.settings.select_other_months&&a(this).attr("class")&&null!==(na=a(this).attr("class").match(/date\_([0-9]{4})(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])/))?ga(na[1],na[2]-1,na[3],"days",a(this)):ga(s,r,ja(a(this).html()),"days",a(this))}),i.delegate("td:not(.dp_disabled)","click",function(){var b=a(this).attr("class").match(/dp\_month\_([0-9]+)/);r=ja(b[1]),-1==a.inArray("days",H)?ga(s,r,1,"months",a(this)):(d="days",S.settings.always_visible&&T.val(""),fa())}),j.delegate("td:not(.dp_disabled)","click",function(){s=ja(a(this).html()),-1==a.inArray("months",H)?ga(s,1,1,"years",a(this)):(d="months",S.settings.always_visible&&T.val(""),fa())}),a(J).bind("click",function(b){b.preventDefault(),ga(m,l,n,"days",a(".dp_current",h)),S.settings.always_visible&&S.show(),S.hide()}),a(k).bind("click",function(b){b.preventDefault(),T.val(""),S.settings.always_visible?(t=null,u=null,v=null,a("td.dp_selected",e).removeClass("dp_selected")):(t=null,u=null,v=null,r=null,s=null),S.hide(),S.settings.onClear&&"function"==typeof S.settings.onClear&&S.settings.onClear.call(T,T)}),S.settings.always_visible||(a(document).bind("mousedown.Zebra_DatePicker_"+N+", touchstart.Zebra_DatePicker_"+N,function(b){if(e.hasClass("dp_visible")){if(S.settings.show_icon&&a(b.target).get(0)===f.get(0))return!0;0===a(b.target).parents().filter(".Zebra_DatePicker").length&&S.hide()}}),a(document).bind("keyup.Zebra_DatePicker_"+N,function(a){e.hasClass("dp_visible")&&27==a.which&&S.hide()})),fa()};S.clear_date=function(){a(k).trigger("click")},S.destroy=function(){void 0!==S.icon&&S.icon.remove(),S.datepicker.remove(),S.settings.show_icon&&!S.settings.always_visible&&T.unwrap(),T.unbind("click.Zebra_DatePicker_"+N),T.unbind("blur.Zebra_DatePicker_"+N),a(document).unbind("keyup.Zebra_DatePicker_"+N),a(document).unbind("mousedown.Zebra_DatePicker_"+N),a(window).unbind("resize.Zebra_DatePicker_"+N),a(window).unbind("orientationchange.Zebra_DatePicker_"+N),T.removeData("Zebra_DatePicker"),T.attr("readonly",R.readonly?!0:!1),T.attr("style",R.style?R.style:"")},S.hide=function(){S.settings.always_visible||(ba("hide"),e.removeClass("dp_visible").addClass("dp_hidden"),S.settings.onClose&&"function"==typeof S.settings.onClose&&S.settings.onClose.call(T,T))},S.set_date=function(a){var b;(b=V(a))&&!ca(b.getFullYear(),b.getMonth(),b.getDate())&&(T.val(a),ka(b))},S.show=function(){d=S.settings.view;var b=V(T.val()||(S.settings.start_date?S.settings.start_date:""));if(b?(u=b.getMonth(),r=b.getMonth(),v=b.getFullYear(),s=b.getFullYear(),t=b.getDate(),ca(v,u,t)&&(S.settings.strict&&T.val(""),r=o,s=p)):(r=o,s=p),fa(),S.settings.always_visible)e.removeClass("dp_hidden").addClass("dp_visible");else{if(S.settings.container.is("body")){var c=e.outerWidth(),g=e.outerHeight(),h=(void 0!==f?f.offset().left+f.outerWidth(!0):T.offset().left+T.outerWidth(!0))+S.settings.offset[0],i=(void 0!==f?f.offset().top:T.offset().top)-g+S.settings.offset[1],j=a(window).width(),k=a(window).height(),l=a(window).scrollTop(),m=a(window).scrollLeft();"below"==S.settings.default_position&&(i=(void 0!==f?f.offset().top:T.offset().top)+S.settings.offset[1]),h+c>m+j&&(h=m+j-c),m>h&&(h=m),i+g>l+k&&(i=l+k-g),l>i&&(i=l),e.css({left:h,top:i})}else e.css({left:0,top:0});e.removeClass("dp_hidden").addClass("dp_visible"),ba()}S.settings.onOpen&&"function"==typeof S.settings.onOpen&&S.settings.onOpen.call(T,T)},S.update=function(b){S.original_direction&&(S.original_direction=S.direction),S.settings=a.extend(S.settings,b),U(!0)};var V=function(b){if(b+="",""!==a.trim(b)){for(var c=X(S.settings.format),d=["d","D","j","l","N","S","w","F","m","M","n","Y","y"],e=[],f=[],g=null,h=null,i=0;i<d.length;i++)(g=c.indexOf(d[i]))>-1&&e.push({character:d[i],position:g});if(e.sort(function(a,b){return a.position-b.position}),a.each(e,function(a,b){switch(b.character){case"d":f.push("0[1-9]|[12][0-9]|3[01]");break;case"D":f.push("[a-z]{3}");break;case"j":f.push("[1-9]|[12][0-9]|3[01]");break;case"l":f.push("[a-z]+");break;case"N":f.push("[1-7]");break;case"S":f.push("st|nd|rd|th");break;case"w":f.push("[0-6]");break;case"F":f.push("[a-z]+");break;case"m":f.push("0[1-9]|1[012]+");break;case"M":f.push("[a-z]{3}");break;case"n":f.push("[1-9]|1[012]");break;case"Y":f.push("[0-9]{4}");break;case"y":f.push("[0-9]{2}")}}),f.length&&(e.reverse(),a.each(e,function(a,b){c=c.replace(b.character,"("+f[f.length-a-1]+")")}),f=new RegExp("^"+c+"$","ig"),h=f.exec(b))){var j,k=new Date,l=1,m=k.getMonth()+1,n=k.getFullYear(),o=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],p=["January","February","March","April","May","June","July","August","September","October","November","December"],q=!0;if(e.reverse(),a.each(e,function(b,c){if(!q)return!0;switch(c.character){case"m":case"n":m=ja(h[b+1]);break;case"d":case"j":l=ja(h[b+1]);break;case"D":case"l":case"F":case"M":j="D"==c.character||"l"==c.character?S.settings.days:S.settings.months,q=!1,a.each(j,function(a,d){if(q)return!0;if(h[b+1].toLowerCase()==d.substring(0,"D"==c.character||"M"==c.character?3:d.length).toLowerCase()){switch(c.character){case"D":h[b+1]=o[a].substring(0,3);break;case"l":h[b+1]=o[a];break;case"F":h[b+1]=p[a],m=a+1;break;case"M":h[b+1]=p[a].substring(0,3),m=a+1}q=!0}});break;case"Y":n=ja(h[b+1]);break;case"y":n="19"+ja(h[b+1])}}),q){var r=new Date(n,(m||1)-1,l||1);if(r.getFullYear()==n&&r.getDate()==(l||1)&&r.getMonth()==(m||1)-1)return r}}return!1}},W=function(a){"firefox"==ma.name?a.css("MozUserSelect","none"):"explorer"==ma.name?a.bind("selectstart",function(){return!1}):a.mousedown(function(){return!1})},X=function(a){return a.replace(/([-.,*+?^${}()|[\]\/\\])/g,"\\$1")},Y=function(b){for(var c="",d=b.getDate(),e=b.getDay(),f=S.settings.days[e],g=b.getMonth()+1,h=S.settings.months[g-1],i=b.getFullYear()+"",j=0;j<S.settings.format.length;j++){var k=S.settings.format.charAt(j);switch(k){case"y":i=i.substr(2);case"Y":c+=i;break;case"m":g=ia(g,2);case"n":c+=g;break;case"M":h=a.isArray(S.settings.months_abbr)&&void 0!==S.settings.months_abbr[g-1]?S.settings.months_abbr[g-1]:S.settings.months[g-1].substr(0,3);case"F":c+=h;break;case"d":d=ia(d,2);case"j":c+=d;break;case"D":f=a.isArray(S.settings.days_abbr)&&void 0!==S.settings.days_abbr[e]?S.settings.days_abbr[e]:S.settings.days[e].substr(0,3);case"l":c+=f;break;case"N":e++;case"w":c+=e;break;case"S":c+=d%10==1&&"11"!=d?"st":d%10==2&&"12"!=d?"nd":d%10==3&&"13"!=d?"rd":"th";break;default:c+=k}}return c},Z=function(){var b=new Date(s,r+1,0).getDate(),c=new Date(s,r,1).getDay(),d=new Date(s,r,0).getDate(),e=c-S.settings.first_day_of_week;e=0>e?7+e:e,ea(S.settings.header_captions.days);var f="<tr>";S.settings.show_week_number&&(f+="<th>"+S.settings.show_week_number+"</th>");for(var g=0;7>g;g++)f+="<th>"+(a.isArray(S.settings.days_abbr)&&void 0!==S.settings.days_abbr[(S.settings.first_day_of_week+g)%7]?S.settings.days_abbr[(S.settings.first_day_of_week+g)%7]:S.settings.days[(S.settings.first_day_of_week+g)%7].substr(0,2))+"</th>";for(f+="</tr><tr>",g=0;42>g;g++){g>0&&g%7===0&&(f+="</tr><tr>"),g%7===0&&S.settings.show_week_number&&(f+='<td class="dp_week_number">'+la(new Date(s,r,g-e+1))+"</td>");var i=g-e+1;if(S.settings.select_other_months&&(e>g||i>b)){var j=new Date(s,r,i),k=j.getFullYear(),o=j.getMonth(),p=j.getDate();j=k+ia(o+1,2)+ia(p,2)}if(e>g)f+='<td class="'+(S.settings.select_other_months&&!ca(k,o,p)?"dp_not_in_month_selectable date_"+j:"dp_not_in_month")+'">'+(S.settings.select_other_months||S.settings.show_other_months?ia(d-e+g+1,S.settings.zero_pad?2:0):" ")+"</td>";else if(i>b)f+='<td class="'+(S.settings.select_other_months&&!ca(k,o,p)?"dp_not_in_month_selectable date_"+j:"dp_not_in_month")+'">'+(S.settings.select_other_months||S.settings.show_other_months?ia(i-b,S.settings.zero_pad?2:0):" ")+"</td>";else{var q=(S.settings.first_day_of_week+g)%7,w="",x=aa(s,r,i);ca(s,r,i)?(a.inArray(q,S.settings.weekend_days)>-1?w="dp_weekend_disabled":w+=" dp_disabled",r==l&&s==m&&n==i&&(w+=" dp_disabled_current"),""!=x&&(w+=" "+x+"_disabled")):(a.inArray(q,S.settings.weekend_days)>-1&&(w="dp_weekend"),r==u&&s==v&&t==i&&(w+=" dp_selected"),r==l&&s==m&&n==i&&(w+=" dp_current"),""!=x&&(w+=" "+x)),f+="<td"+(""!==w?' class="'+a.trim(w)+'"':"")+">"+((S.settings.zero_pad?ia(i,2):i)||" ")+"</td>"}}f+="</tr>",h.html(a(f)),S.settings.always_visible&&(E=a("td:not(.dp_disabled, .dp_weekend_disabled, .dp_not_in_month, .dp_week_number)",h)),h.show()},$=function(){ea(S.settings.header_captions.months);for(var b="<tr>",c=0;12>c;c++){c>0&&c%3===0&&(b+="</tr><tr>");var d="dp_month_"+c;ca(s,c)?d+=" dp_disabled":u!==!1&&u==c&&s==v?d+=" dp_selected":l==c&&m==s&&(d+=" dp_current"),b+='<td class="'+a.trim(d)+'">'+(a.isArray(S.settings.months_abbr)&&void 0!==S.settings.months_abbr[c]?S.settings.months_abbr[c]:S.settings.months[c].substr(0,3))+"</td>"}b+="</tr>",i.html(a(b)),S.settings.always_visible&&(F=a("td:not(.dp_disabled)",i)),i.show()},_=function(){ea(S.settings.header_captions.years);for(var b="<tr>",c=0;12>c;c++){c>0&&c%3===0&&(b+="</tr><tr>");var d="";ca(s-7+c)?d+=" dp_disabled":v&&v==s-7+c?d+=" dp_selected":m==s-7+c&&(d+=" dp_current"),b+="<td"+(""!==a.trim(d)?' class="'+a.trim(d)+'"':"")+">"+(s-7+c)+"</td>"}b+="</tr>",j.html(a(b)),S.settings.always_visible&&(G=a("td:not(.dp_disabled)",j)),j.show()},aa=function(b,c,d){var e,f,g;"undefined"!=typeof c&&(c+=1);for(f in P)if(e=P[f],g=!1,a.isArray(O[e])&&a.each(O[e],function(){if(!g){var f=this;if((a.inArray(b,f[2])>-1||a.inArray("*",f[2])>-1)&&("undefined"!=typeof c&&a.inArray(c,f[1])>-1||a.inArray("*",f[1])>-1)&&("undefined"!=typeof d&&a.inArray(d,f[0])>-1||a.inArray("*",f[0])>-1)){if("*"==f[3])return g=e;var h=new Date(b,c-1,d).getDay();if(a.inArray(h,f[3])>-1)return g=e}}}),g)return g;return g||""},ba=function(b){if("explorer"==ma.name&&6==ma.version){if(!y){var c=ja(e.css("zIndex"))-1;y=a("<iframe>",{src:'javascript:document.write("")',scrolling:"no",frameborder:0,css:{zIndex:c,position:"absolute",top:-1e3,left:-1e3,width:e.outerWidth(),height:e.outerHeight(),filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=0)",display:"none"}}),a("body").append(y)}switch(b){case"hide":y.hide();break;default:var d=e.offset();y.css({top:d.top,left:d.left,display:"block"})}}},ca=function(b,c,d){if(!(void 0!==b&&!isNaN(b)||void 0!==c&&!isNaN(c)||void 0!==d&&!isNaN(d)))return!1;if(1e3>b)return!0;if(a.isArray(S.settings.direction)||0!==ja(S.settings.direction)){var e=ja(ha(b,"undefined"!=typeof c?ia(c,2):"","undefined"!=typeof d?ia(d,2):"")),f=(e+"").length;if(8==f&&("undefined"!=typeof z&&e<ja(ha(p,ia(o,2),ia(q,2)))||"undefined"!=typeof A&&e>ja(ha(C,ia(D,2),ia(B,2)))))return!0;if(6==f&&("undefined"!=typeof z&&e<ja(ha(p,ia(o,2)))||"undefined"!=typeof A&&e>ja(ha(C,ia(D,2)))))return!0;if(4==f&&("undefined"!=typeof z&&p>e||"undefined"!=typeof A&&e>C))return!0}"undefined"!=typeof c&&(c+=1);var g=!1,h=!1;return a.isArray(x)&&x.length&&a.each(x,function(){if(!g){var e=this;if((a.inArray(b,e[2])>-1||a.inArray("*",e[2])>-1)&&("undefined"!=typeof c&&a.inArray(c,e[1])>-1||a.inArray("*",e[1])>-1)&&("undefined"!=typeof d&&a.inArray(d,e[0])>-1||a.inArray("*",e[0])>-1)){if("*"==e[3])return g=!0;var f=new Date(b,c-1,d).getDay();if(a.inArray(f,e[3])>-1)return g=!0}}}),w&&a.each(w,function(){if(!h){var e=this;if((a.inArray(b,e[2])>-1||a.inArray("*",e[2])>-1)&&(h=!0,"undefined"!=typeof c))if(h=!0,a.inArray(c,e[1])>-1||a.inArray("*",e[1])>-1){if("undefined"!=typeof d)if(h=!0,a.inArray(d,e[0])>-1||a.inArray("*",e[0])>-1){if("*"==e[3])return h=!0;var f=new Date(b,c-1,d).getDay();if(a.inArray(f,e[3])>-1)return h=!0;h=!1}else h=!1}else h=!1}}),w&&h?!1:x&&g?!0:!1},da=function(a){return(a+"").match(/^\-?[0-9]+$/)?!0:!1},ea=function(b){!isNaN(parseFloat(r))&&isFinite(r)&&(b=b.replace(/\bm\b|\bn\b|\bF\b|\bM\b/,function(b){switch(b){case"m":return ia(r+1,2);case"n":return r+1;case"F":return S.settings.months[r];case"M":return a.isArray(S.settings.months_abbr)&&void 0!==S.settings.months_abbr[r]?S.settings.months_abbr[r]:S.settings.months[r].substr(0,3);default:return b}})),!isNaN(parseFloat(s))&&isFinite(s)&&(b=b.replace(/\bY\b/,s).replace(/\by\b/,(s+"").substr(2)).replace(/\bY1\b/i,s-7).replace(/\bY2\b/i,s+4)),a(".dp_caption",g).html(b)},fa=function(){if(""===h.text()||"days"==d){if(""===h.text()){S.settings.always_visible||e.css("left",-1e3),e.css("visibility","visible"),Z();var b=h.outerWidth(),c=h.outerHeight();i.css({width:b,height:c}),j.css({width:b,height:c}),g.css("width",b),K.css("width",b),e.css("visibility","").addClass("dp_hidden")}else Z();i.hide(),j.hide()}else"months"==d?($(),h.hide(),j.hide()):"years"==d&&(_(),h.hide(),i.hide());if(S.settings.onChange&&"function"==typeof S.settings.onChange&&void 0!==d){var f="days"==d?h.find("td:not(.dp_disabled, .dp_weekend_disabled, .dp_not_in_month)"):"months"==d?i.find("td:not(.dp_disabled, .dp_weekend_disabled, .dp_not_in_month)"):j.find("td:not(.dp_disabled, .dp_weekend_disabled, .dp_not_in_month)");f.each(function(){var b;"days"==d?a(this).hasClass("dp_not_in_month_selectable")?(b=a(this).attr("class").match(/date\_([0-9]{4})(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])/),a(this).data("date",b[1]+"-"+b[2]+"-"+b[3])):a(this).data("date",s+"-"+ia(r+1,2)+"-"+ia(ja(a(this).text()),2)):"months"==d?(b=a(this).attr("class").match(/dp\_month\_([0-9]+)/),a(this).data("date",s+"-"+ia(ja(b[1])+1,2))):a(this).data("date",ja(a(this).text()))}),S.settings.onChange.call(T,d,f,T)}K.show(),S.settings.show_clear_date===!0||0===S.settings.show_clear_date&&""!==T.val()||S.settings.always_visible&&S.settings.show_clear_date!==!1?(k.show(),L?(J.css("width","50%"),k.css("width","50%")):(J.hide(),k.css("width","100%"))):(k.hide(),L?J.show().css("width","100%"):K.hide())},ga=function(a,b,c,d,e){var f=new Date(a,b,c,12,0,0),g="days"==d?E:"months"==d?F:G,h=Y(f);T.val(h),S.settings.always_visible&&(u=f.getMonth(),r=f.getMonth(),v=f.getFullYear(),s=f.getFullYear(),t=f.getDate(),g.removeClass("dp_selected"),e.addClass("dp_selected"),"days"==d&&e.hasClass("dp_not_in_month_selectable")&&S.show()),S.hide(),ka(f),S.settings.onSelect&&"function"==typeof S.settings.onSelect&&S.settings.onSelect.call(T,h,a+"-"+ia(b+1,2)+"-"+ia(c,2),f,T,la(f)),T.focus()},ha=function(){for(var a="",b=0;b<arguments.length;b++)a+=arguments[b]+"";return a},ia=function(a,b){for(a+="";a.length<b;)a="0"+a;return a},ja=function(a){return parseInt(a,10)},ka=function(b){S.settings.pair&&a.each(S.settings.pair,function(){var c=a(this);if(c.data&&c.data("Zebra_DatePicker")){var d=c.data("Zebra_DatePicker");d.update({reference_date:b,direction:0===d.settings.direction?1:d.settings.direction}),d.settings.always_visible&&d.show()}else c.data("zdp_reference_date",b)})},la=function(a){var b,c,d,e,f,g,h,i,j,k=a.getFullYear(),l=a.getMonth()+1,m=a.getDate();return 3>l?(b=k-1,c=(b/4|0)-(b/100|0)+(b/400|0),d=((b-1)/4|0)-((b-1)/100|0)+((b-1)/400|0),e=c-d,f=0,g=m-1+31*(l-1)):(b=k,c=(b/4|0)-(b/100|0)+(b/400|0),d=((b-1)/4|0)-((b-1)/100|0)+((b-1)/400|0),e=c-d,f=e+1,g=m+((153*(l-3)+2)/5|0)+58+e),h=(b+c)%7,m=(g+h-f)%7,i=g+3-m,j=0>i?53-((h-e)/5|0):i>364+e?1:(i/7|0)+1},ma={init:function(){this.name=this.searchString(this.dataBrowser)||"",this.version=this.searchVersion(navigator.userAgent)||this.searchVersion(navigator.appVersion)||""},searchString:function(a){for(var b=0;b<a.length;b++){var c=a[b].string,d=a[b].prop;if(this.versionSearchString=a[b].versionSearch||a[b].identity,c){if(-1!=c.indexOf(a[b].subString))return a[b].identity}else if(d)return a[b].identity}},searchVersion:function(a){var b=a.indexOf(this.versionSearchString);if(-1!=b)return parseFloat(a.substring(b+this.versionSearchString.length+1))},dataBrowser:[{string:navigator.userAgent,subString:"Firefox",identity:"firefox"},{string:navigator.userAgent,subString:"MSIE",identity:"explorer",versionSearch:"MSIE"}]};ma.init(),U()},a.fn.Zebra_DatePicker=function(b){return this.each(function(){void 0!==a(this).data("Zebra_DatePicker")&&a(this).data("Zebra_DatePicker").destroy();var c=new a.Zebra_DatePicker(this,b);a(this).data("Zebra_DatePicker",c)})}});
|
1
|
+
/**
|
2
|
+
* Zebra_DatePicker
|
3
|
+
*
|
4
|
+
* Zebra_DatePicker is a small, compact and highly configurable date picker plugin for jQuery
|
5
|
+
*
|
6
|
+
* Read more {@link https://github.com/stefangabos/Zebra_Datepicker/ here}
|
7
|
+
*
|
8
|
+
* @author Stefan Gabos <contact@stefangabos.ro>
|
9
|
+
* @version 1.9.7 (last revision: December 03, 2017)
|
10
|
+
* @copyright (c) 2011 - 2017 Stefan Gabos
|
11
|
+
* @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU LESSER GENERAL PUBLIC LICENSE
|
12
|
+
* @package Zebra_DatePicker
|
13
|
+
*/
|
14
|
+
(function(factory) {
|
15
|
+
|
16
|
+
'use strict';
|
17
|
+
|
18
|
+
// AMD
|
19
|
+
if (typeof define === 'function' && define.amd) define(['jquery'], factory);
|
20
|
+
|
21
|
+
// CommonJS
|
22
|
+
else if (typeof exports === 'object') factory(require('jquery'));
|
23
|
+
|
24
|
+
// browser globals
|
25
|
+
else factory(jQuery);
|
26
|
+
|
27
|
+
}(function($) {
|
28
|
+
|
29
|
+
'use strict';
|
30
|
+
|
31
|
+
$.Zebra_DatePicker = function(element, options) {
|
32
|
+
|
33
|
+
var defaults = {
|
34
|
+
|
35
|
+
// setting this property to a jQuery element, will result in the date picker being always visible, the indicated
|
36
|
+
// element being the date picker's container;
|
37
|
+
//
|
38
|
+
// setting this to boolean TRUE will keep will result in the date picker not closing when selecting a
|
39
|
+
// date but only when the user clicks outside the date picker.
|
40
|
+
//
|
41
|
+
// note that when a date format is used that also involves time, this property will be automatically
|
42
|
+
// set to TRUE!
|
43
|
+
//
|
44
|
+
// default is FALSE
|
45
|
+
always_visible: false,
|
46
|
+
|
47
|
+
// by default, the date picker is injected into the <body>; use this property to tell the library to inject
|
48
|
+
// the date picker into a custom element - useful when you want the date picker to open at a specific position
|
49
|
+
//
|
50
|
+
// must be a jQuery element
|
51
|
+
//
|
52
|
+
// default is $('body')
|
53
|
+
container: $('body'),
|
54
|
+
|
55
|
+
// dates that should have custom classes applied to them
|
56
|
+
// an object in the form of
|
57
|
+
// {
|
58
|
+
// 'myclass1': [dates_to_apply_the_custom_class_to],
|
59
|
+
// 'myclass2': [dates_to_apply_the_custom_class_to]
|
60
|
+
// }
|
61
|
+
// where "dates_to_apply_the_custom_class_to" is an array of dates in the same format as required for
|
62
|
+
// "disabled_dates" property.
|
63
|
+
//
|
64
|
+
// custom classes will be applied *only* in the day picker view and not on month/year views!
|
65
|
+
// also note that the class name will have the "_disabled" suffix added if the day the class is applied to
|
66
|
+
// is disabled
|
67
|
+
//
|
68
|
+
// in order for the styles in your custom classes to be applied, make sure you are using the following syntax:
|
69
|
+
//
|
70
|
+
// .Zebra_DatePicker .dp_daypicker td.myclass1 { .. }
|
71
|
+
// .Zebra_DatePicker .dp_daypicker td.myclass1_disabled { .. }
|
72
|
+
//
|
73
|
+
// default is FALSE, no custom classes
|
74
|
+
custom_classes: false,
|
75
|
+
|
76
|
+
// days of the week; Sunday to Saturday
|
77
|
+
days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
78
|
+
|
79
|
+
// by default, the abbreviated name of a day consists of the first 2 letters from the day's full name;
|
80
|
+
// while this is common for most languages, there are also exceptions for languages like Thai, Loa, Myanmar,
|
81
|
+
// etc. where this is not correct; for these cases, specify an array with the abbreviations to be used for
|
82
|
+
// the 7 days of the week; leave it FALSE to use the first 2 letters of a day's name as the abbreviation.
|
83
|
+
//
|
84
|
+
// default is FALSE
|
85
|
+
days_abbr: false,
|
86
|
+
|
87
|
+
// the position of the date picker relative to the element it is attached to. note that, regardless of this
|
88
|
+
// setting, the date picker's position will be automatically adjusted to fit in the viewport, if needed.
|
89
|
+
//
|
90
|
+
// possible values are "above" and "below"
|
91
|
+
//
|
92
|
+
// default is "above"
|
93
|
+
default_position: 'above',
|
94
|
+
|
95
|
+
// direction of the calendar
|
96
|
+
//
|
97
|
+
// a positive or negative integer: n (a positive integer) creates a future-only calendar beginning at n days
|
98
|
+
// after today; -n (a negative integer); if n is 0, the calendar has no restrictions. use boolean true for
|
99
|
+
// a future-only calendar starting with today and use boolean false for a past-only calendar ending today.
|
100
|
+
//
|
101
|
+
// you may also set this property to an array with two elements in the following combinations:
|
102
|
+
//
|
103
|
+
// - first item is boolean TRUE (calendar starts today), an integer > 0 (calendar starts n days after
|
104
|
+
// today), or a valid date given in the format defined by the "format" attribute, using English for
|
105
|
+
// month names (calendar starts at the specified date), and the second item is boolean FALSE (the calendar
|
106
|
+
// has no ending date), an integer > 0 (calendar ends n days after the starting date), or a valid date
|
107
|
+
// given in the format defined by the "format" attribute, using English for month names, and which occurs
|
108
|
+
// after the starting date (calendar ends at the specified date)
|
109
|
+
//
|
110
|
+
// - first item is boolean FALSE (calendar ends today), an integer < 0 (calendar ends n days before today),
|
111
|
+
// or a valid date given in the format defined by the "format" attribute, using English for month names
|
112
|
+
// (calendar ends at the specified date), and the second item is an integer > 0 (calendar ends n days
|
113
|
+
// before the ending date), or a valid date given in the format defined by the "format" attribute, using
|
114
|
+
// English for month names and which occurs before the starting date (calendar starts at the specified
|
115
|
+
// date)
|
116
|
+
//
|
117
|
+
// [1, 7] - calendar starts tomorrow and ends seven days after that
|
118
|
+
// [true, 7] - calendar starts today and ends seven days after that
|
119
|
+
// ['2013-01-01', false] - calendar starts on January 1st 2013 and has no ending date ("format" is YYYY-MM-DD)
|
120
|
+
// [false, '2012-01-01'] - calendar ends today and starts on January 1st 2012 ("format" is YYYY-MM-DD)
|
121
|
+
//
|
122
|
+
// note that "disabled_dates" property will still apply!
|
123
|
+
//
|
124
|
+
// default is 0 (no restrictions)
|
125
|
+
direction: 0,
|
126
|
+
|
127
|
+
// an array of disabled dates in the following format: 'day month year weekday' where "weekday" is optional
|
128
|
+
// and can be 0-6 (Saturday to Sunday); the syntax is similar to cron's syntax: the values are separated by
|
129
|
+
// spaces and may contain * (asterisk) - (dash) and , (comma) delimiters:
|
130
|
+
//
|
131
|
+
// ['1 1 2012'] would disable January 1, 2012;
|
132
|
+
// ['* 1 2012'] would disable all days in January 2012;
|
133
|
+
// ['1-10 1 2012'] would disable January 1 through 10 in 2012;
|
134
|
+
// ['1,10 1 2012'] would disable January 1 and 10 in 2012;
|
135
|
+
// ['1-10,20,22,24 1-3 *'] would disable 1 through 10, plus the 22nd and 24th of January through March for every year;
|
136
|
+
// ['* * * 0,6'] would disable all Saturdays and Sundays;
|
137
|
+
// ['01 07 2012', '02 07 2012', '* 08 2012'] would disable 1st and 2nd of July 2012, and all of August of 2012
|
138
|
+
//
|
139
|
+
// default is FALSE, no disabled dates
|
140
|
+
//
|
141
|
+
// DISABLING ALL DATES AND NOT SPECIFYING AT LEAST ONE ENABLED DATE WILL SEND THE SCRIPT INTO AN INFINITE
|
142
|
+
// LOOP SEARCHING FOR AN ENABLED DATE TO DISPLAY!
|
143
|
+
disabled_dates: false,
|
144
|
+
|
145
|
+
// an array of enabled dates in the same format as required for "disabled_dates" property.
|
146
|
+
// to be used together with the "disabled_dates" property by first setting the "disabled_dates" property to
|
147
|
+
// something like "[* * * *]" (which will disable everything) and the setting the "enabled_dates" property to,
|
148
|
+
// say, "[* * * 0,6]" to enable just weekends.
|
149
|
+
enabled_dates: false,
|
150
|
+
|
151
|
+
// an array of selectable hours.
|
152
|
+
// default is FALSE, all hours are selectable.
|
153
|
+
enabled_hours: false,
|
154
|
+
|
155
|
+
// an array of selectable minutes.
|
156
|
+
// default is FALSE, all minutes are selectable.
|
157
|
+
enabled_minutes: false,
|
158
|
+
|
159
|
+
// an array of selectable seconds.
|
160
|
+
// default is FALSE, all seconds are selectable.
|
161
|
+
enabled_seconds: false,
|
162
|
+
|
163
|
+
// week's starting day
|
164
|
+
//
|
165
|
+
// valid values are 0 to 6, Sunday to Saturday
|
166
|
+
//
|
167
|
+
// default is 1, Monday
|
168
|
+
first_day_of_week: 1,
|
169
|
+
|
170
|
+
// format of the returned date
|
171
|
+
//
|
172
|
+
// accepts the following characters for date formatting: d, D, j, l, N, w, S, F, m, M, n, Y, y, h, H,
|
173
|
+
// g, G, i, s, a, A borrowing the syntax from PHP's "date" function.
|
174
|
+
//
|
175
|
+
// note that when setting a date format without days ('d', 'j'), the users will be able to select only years
|
176
|
+
// and months, and when setting a format without months and days ('F', 'm', 'M', 'n', 'd', 'j'), the
|
177
|
+
// users will be able to select only years; likewise, when setting a date format with just months ('F', 'm',
|
178
|
+
// 'M', 'n') or just years ('Y', 'y'), users will be able to select only months and years, respectively.
|
179
|
+
//
|
180
|
+
// setting a format that also involves time (h, H, g, G, i, s, a, A) will automatically enable the time
|
181
|
+
// picker.
|
182
|
+
//
|
183
|
+
// also note that the value of the "view" property (see below) may be overridden if it is the case: a value of
|
184
|
+
// "days" for the "view" property makes no sense if the date format doesn't allow the selection of days.
|
185
|
+
//
|
186
|
+
// default is Y-m-d
|
187
|
+
format: 'Y-m-d',
|
188
|
+
|
189
|
+
// captions in the datepicker's header, for the 3 possible views: days, months, years
|
190
|
+
//
|
191
|
+
// for each of the 3 views the following special characters may be used borrowing from PHP's "date" function's
|
192
|
+
// syntax: m, n, F, M, y and Y; any of these will be replaced at runtime with the appropriate date fragment,
|
193
|
+
// depending on the currently viewed date. two more special characters are also available Y1 and Y2 (upper
|
194
|
+
// case representing years with 4 digits, lowercase representing years with 2 digits) which represent
|
195
|
+
// "currently selected year - 7" and "currently selected year + 4" and which only make sense used in the
|
196
|
+
// "years" view.
|
197
|
+
//
|
198
|
+
// even though any of these special characters may be used in any of the 3 views, you should use m, n, F, M
|
199
|
+
// for the "days" view and y, Y, Y1, Y2, y1, y2 for the "months" and "years" view or you may get unexpected
|
200
|
+
// results!
|
201
|
+
//
|
202
|
+
// Text and HTML can also be used, and will be rendered as it is, as in the example below (the library is
|
203
|
+
// smart enough to not replace special characters when used in words or HTML tags):
|
204
|
+
//
|
205
|
+
// header_captions: {
|
206
|
+
// 'days': 'Departure:<br>F, Y',
|
207
|
+
// 'months': 'Departure:<br>Y',
|
208
|
+
// 'years': 'Departure:<br>Y1 - Y2'
|
209
|
+
// }
|
210
|
+
//
|
211
|
+
// Default is
|
212
|
+
//
|
213
|
+
// header_captions: {
|
214
|
+
// 'days': 'F, Y',
|
215
|
+
// 'months': 'Y',
|
216
|
+
// 'years': 'Y1 - Y2'
|
217
|
+
// }
|
218
|
+
header_captions: {
|
219
|
+
days: 'F, Y',
|
220
|
+
months: 'Y',
|
221
|
+
years: 'Y1 - Y2'
|
222
|
+
},
|
223
|
+
|
224
|
+
// icon's position
|
225
|
+
// accepted values are "left" and "right"
|
226
|
+
//
|
227
|
+
// default is "right"
|
228
|
+
icon_position: 'right',
|
229
|
+
|
230
|
+
// should the icon for opening the datepicker be inside the element?
|
231
|
+
// if set to FALSE, the icon will be placed to the right of the parent element, while if set to TRUE it will
|
232
|
+
// be placed to the right of the parent element, but *inside* the element itself
|
233
|
+
//
|
234
|
+
// default is TRUE
|
235
|
+
inside: true,
|
236
|
+
|
237
|
+
// the caption for the "Clear" button
|
238
|
+
lang_clear_date: 'Clear date',
|
239
|
+
|
240
|
+
// months names
|
241
|
+
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
242
|
+
|
243
|
+
// by default, the abbreviated name of a month consists of the first 3 letters from the month's full name;
|
244
|
+
// while this is common for most languages, there are also exceptions for languages like Thai, Loa, Myanmar,
|
245
|
+
// etc. where this is not correct; for these cases, specify an array with the abbreviations to be used for
|
246
|
+
// the months of the year; leave it FALSE to use the first 3 letters of a month's name as the abbreviation.
|
247
|
+
//
|
248
|
+
// default is FALSE
|
249
|
+
months_abbr: false,
|
250
|
+
|
251
|
+
// HTML to be used for previous/next and up/down buttons, in that order
|
252
|
+
//
|
253
|
+
// default is ['◀', '▶', '▲', '▼']
|
254
|
+
navigation: ['◀', '▶', '▲', '▼'],
|
255
|
+
|
256
|
+
// the offset, in pixels (x, y), to shift the date picker's position relative to the top-right of the icon
|
257
|
+
// that toggles the date picker or, if the icon is disabled, relative to the top-right corner of the element
|
258
|
+
// the plugin is attached to.
|
259
|
+
//
|
260
|
+
// note that this only applies if the position of element relative to the browser's viewport doesn't require
|
261
|
+
// the date picker to be placed automatically so that it is visible!
|
262
|
+
//
|
263
|
+
// default is [5, -5]
|
264
|
+
offset: [5, -5],
|
265
|
+
|
266
|
+
// set whether the date picker should be shown *only* when interacting with the icon
|
267
|
+
// note that if you also set the "show_icon" property to FALSE, you will not be able to show the date picker anymore!
|
268
|
+
//
|
269
|
+
// default is FALSE
|
270
|
+
open_icon_only: false,
|
271
|
+
|
272
|
+
// set this property to TRUE if you want the date picker to be shown when the parent element (if
|
273
|
+
// "open_icon_only" is not set to FALSE) or the associated calendar icon (if "show_icon" is set to TRUE)
|
274
|
+
// receive focus.
|
275
|
+
//
|
276
|
+
// default is FALSE
|
277
|
+
open_on_focus: false,
|
278
|
+
|
279
|
+
// if set as a jQuery element with a Zebra_DatePicker attached, that particular date picker will use the
|
280
|
+
// current date picker's value as starting date
|
281
|
+
// note that the rules set in the "direction" property will still apply, only that the reference date will
|
282
|
+
// not be the current system date but the value selected in the current date picker
|
283
|
+
// default is FALSE (not paired with another date picker)
|
284
|
+
pair: false,
|
285
|
+
|
286
|
+
// should the element the calendar is attached to, be read-only?
|
287
|
+
// if set to TRUE, a date can be set only through the date picker and cannot be entered manually
|
288
|
+
//
|
289
|
+
// default is TRUE
|
290
|
+
readonly_element: true,
|
291
|
+
|
292
|
+
// should days from previous and/or next month be selectable when visible?
|
293
|
+
// note that if the value of this property is set to TRUE, the value of "show_other_months" will be considered
|
294
|
+
// TRUE regardless of the actual value!
|
295
|
+
//
|
296
|
+
// default is FALSE
|
297
|
+
select_other_months: false,
|
298
|
+
|
299
|
+
// should the "Clear date" button be visible?
|
300
|
+
//
|
301
|
+
// accepted values are:
|
302
|
+
//
|
303
|
+
// - 0 (zero) - the button for clearing a previously selected date is shown only if a previously selected date
|
304
|
+
// already exists; this means that if the input the date picker is attached to is empty, and the user selects
|
305
|
+
// a date for the first time, this button will not be visible; once the user picked a date and opens the date
|
306
|
+
// picker again, this time the button will be visible.
|
307
|
+
//
|
308
|
+
// - TRUE will make the button visible all the time
|
309
|
+
//
|
310
|
+
// - FALSE will disable the button
|
311
|
+
//
|
312
|
+
// default is "0" (without quotes)
|
313
|
+
show_clear_date: 0,
|
314
|
+
|
315
|
+
// should a calendar icon be added to the elements the plugin is attached to?
|
316
|
+
//
|
317
|
+
// default is TRUE
|
318
|
+
show_icon: true,
|
319
|
+
|
320
|
+
// should days from previous and/or next month be visible?
|
321
|
+
//
|
322
|
+
// default is TRUE
|
323
|
+
show_other_months: true,
|
324
|
+
|
325
|
+
// should the "Today" button be visible?
|
326
|
+
// setting it to anything but boolean FALSE will enable the button and will use the property's value as
|
327
|
+
// caption for the button; setting it to FALSE will disable the button
|
328
|
+
//
|
329
|
+
// default is "Today"
|
330
|
+
show_select_today: 'Today',
|
331
|
+
|
332
|
+
// should an extra column be shown, showing the number of each week?
|
333
|
+
// anything other than FALSE will enable this feature, and use the given value as column title
|
334
|
+
// i.e. show_week_number: 'Wk' would enable this feature and have "Wk" as the column's title
|
335
|
+
//
|
336
|
+
// default is FALSE
|
337
|
+
show_week_number: false,
|
338
|
+
|
339
|
+
// a default date to start the date picker with
|
340
|
+
// must be specified in the format defined by the "format" property, or it will be ignored!
|
341
|
+
// note that this value is used only if there is no value in the field the date picker is attached to!
|
342
|
+
//
|
343
|
+
// default is FALSE
|
344
|
+
start_date: false,
|
345
|
+
|
346
|
+
// should default values, in the input field the date picker is attached to, be deleted if they are not valid
|
347
|
+
// according to "direction" and/or "disabled_dates"?
|
348
|
+
//
|
349
|
+
// default is FALSE
|
350
|
+
strict: false,
|
351
|
+
|
352
|
+
// how should the date picker start; valid values are "days", "months" and "years"
|
353
|
+
// note that the date picker is always cycling days-months-years when clicking in the date picker's header,
|
354
|
+
// and years-months-days when selecting dates (unless one or more of the views are missing due to the date's
|
355
|
+
// format)
|
356
|
+
//
|
357
|
+
// also note that the value of the "view" property may be overridden if the date's format requires so! (i.e.
|
358
|
+
// "days" for the "view" property makes no sense if the date format doesn't allow the selection of days)
|
359
|
+
//
|
360
|
+
// default is "days"
|
361
|
+
view: 'days',
|
362
|
+
|
363
|
+
// days of the week that are considered "weekend days"
|
364
|
+
// valid values are 0 to 6, Sunday to Saturday
|
365
|
+
//
|
366
|
+
// default values are 0 and 6 (Saturday and Sunday)
|
367
|
+
weekend_days: [0, 6],
|
368
|
+
|
369
|
+
// when set to TRUE, day numbers < 10 will be prefixed with 0; set to FALSE if you don't want that
|
370
|
+
//
|
371
|
+
// default is TRUE
|
372
|
+
zero_pad: false,
|
373
|
+
|
374
|
+
// callback function to be executed whenever the user changes the view (days/months/years), as well as when
|
375
|
+
// the user navigates by clicking on the "next"/"previous" icons in any of the views;
|
376
|
+
//
|
377
|
+
// the callback function called by this event takes 3 arguments - the first argument represents the current
|
378
|
+
// view (can be "days", "months" or "years"), the second argument represents an array containing the "active"
|
379
|
+
// elements (not disabled) from the view, as jQuery elements, allowing for easy customization and interaction
|
380
|
+
// with particular cells in the date picker's view, while the third argument is a reference to the element
|
381
|
+
// the date picker is attached to, as a jQuery object (deprecated - use the "this" keyword inside the callback
|
382
|
+
// function to refer to the element the date picker is attached to)
|
383
|
+
//
|
384
|
+
// for simplifying searching for particular dates, each element in the second argument will also have a
|
385
|
+
// "date" data attribute whose format depends on the value of the "view" argument:
|
386
|
+
// - YYYY-MM-DD for elements in the "days" view
|
387
|
+
// - YYYY-MM for elements in the "months" view
|
388
|
+
// - YYYY for elements in the "years" view
|
389
|
+
//
|
390
|
+
// the "this" keyword inside the callback function refers to the element the date picker is attached to!
|
391
|
+
onChange: null,
|
392
|
+
|
393
|
+
// callback function to be executed when the user clicks the "Clear" button
|
394
|
+
// the callback function takes a single argument:
|
395
|
+
// - a reference to the element the date picker is attached to, as a jQuery object (deprecated - use the
|
396
|
+
// "this" keyword inside the callback function to refer to the element the date picker is attached to)
|
397
|
+
//
|
398
|
+
// the "this" keyword inside the callback function refers to the element the date picker is attached to!
|
399
|
+
onClear: null,
|
400
|
+
|
401
|
+
// callback function to be executed when the date picker is shown
|
402
|
+
// the callback function takes a single argument:
|
403
|
+
// - a reference to the element the date picker is attached to, as a jQuery object (deprecated - use the
|
404
|
+
// "this" keyword inside the callback function to refer to the element the date picker is attached to)
|
405
|
+
//
|
406
|
+
// the "this" keyword inside the callback function refers to the element the date picker is attached to!
|
407
|
+
onOpen: null,
|
408
|
+
|
409
|
+
// callback function to be executed when the date picker is closed, but only when the "always_visible"
|
410
|
+
// property is set to FALSE
|
411
|
+
// the callback function takes a single argument:
|
412
|
+
// - a reference to the element the date picker is attached to, as a jQuery object (deprecated - use the
|
413
|
+
// "this" keyword inside the callback function to refer to the element the date picker is attached to)
|
414
|
+
//
|
415
|
+
// the "this" keyword inside the callback function refers to the element the date picker is attached to!
|
416
|
+
onClose: null,
|
417
|
+
|
418
|
+
// callback function to be executed when a date is selected
|
419
|
+
// the callback function takes 5 arguments:
|
420
|
+
// - the date in the format specified by the "format" attribute;
|
421
|
+
// - the date in YYYY-MM-DD format
|
422
|
+
// - the date as a JavaScript Date object
|
423
|
+
// - a reference to the element the date picker is attached to, as a jQuery object (deprecated - use the
|
424
|
+
// "this" keyword inside the callback function to refer to the element the date picker is attached to)
|
425
|
+
// - the ISO 8601 week number of the selected date
|
426
|
+
//
|
427
|
+
// the "this" keyword inside the callback function refers to the element the date picker is attached to!
|
428
|
+
onSelect: null
|
429
|
+
|
430
|
+
},
|
431
|
+
|
432
|
+
// private properties
|
433
|
+
cleardate, clickables, confirm_selection, current_system_day, current_system_month, current_system_year,
|
434
|
+
custom_class_names = [], custom_classes = {}, datepicker, daypicker, daypicker_cells, default_day,
|
435
|
+
default_month, default_year, disabled_dates = [], enabled_dates = [], end_date, first_selectable_day,
|
436
|
+
first_selectable_month, first_selectable_year, footer, header, icon, last_selectable_day, last_selectable_month,
|
437
|
+
last_selectable_year, monthpicker, monthpicker_cells, original_attributes = {}, selected_hour, selected_minute,
|
438
|
+
selected_second, selected_ampm, view_toggler, selected_month, selected_year, selecttoday, shim,
|
439
|
+
show_select_today, start_date, timeout, timepicker, timepicker_config, uniqueid = '', yearpicker, yearpicker_cells,
|
440
|
+
view, views;
|
441
|
+
|
442
|
+
var plugin = this;
|
443
|
+
|
444
|
+
plugin.settings = {};
|
445
|
+
|
446
|
+
// the jQuery version of the element
|
447
|
+
// "element" (without the $) will point to the DOM element
|
448
|
+
var $element = $(element);
|
449
|
+
|
450
|
+
/**
|
451
|
+
* Constructor method. Initializes the date picker.
|
452
|
+
*
|
453
|
+
* @return void
|
454
|
+
*/
|
455
|
+
var init = function(update) {
|
456
|
+
|
457
|
+
var
|
458
|
+
|
459
|
+
// the characters that may be present in the date format and that represent days, months, years, hours,
|
460
|
+
// minutes and seconds
|
461
|
+
date_chars = {
|
462
|
+
days: ['d', 'j', 'D'],
|
463
|
+
months: ['F', 'm', 'M', 'n', 't'],
|
464
|
+
years: ['o', 'Y', 'y'],
|
465
|
+
hours: ['G', 'g', 'H', 'h'],
|
466
|
+
minutes: ['i'],
|
467
|
+
seconds: ['s'],
|
468
|
+
ampm: ['A', 'a']
|
469
|
+
},
|
470
|
+
|
471
|
+
// some defaults
|
472
|
+
type = null, data, dates, k, l;
|
473
|
+
|
474
|
+
// generate a random ID for each date picker (we'll use this if later a certain date picker is destroyed to
|
475
|
+
// remove related events)
|
476
|
+
// the code is taken from http://stackoverflow.com/a/105074
|
477
|
+
for (k = 0; k < 3; k++) uniqueid += Math.floor((1 + Math.random()) * 0x10000).toString(16);
|
478
|
+
|
479
|
+
// unless we're not just updating settings
|
480
|
+
if (!update) {
|
481
|
+
|
482
|
+
// merge default settings with user-settings (
|
483
|
+
plugin.settings = $.extend({}, defaults, options);
|
484
|
+
|
485
|
+
// preserve some of element's original attributes
|
486
|
+
original_attributes['readonly'] = $element.attr('readonly');
|
487
|
+
original_attributes['style'] = $element.attr('style');
|
488
|
+
|
489
|
+
// iterate through the element's data attributes (if any)
|
490
|
+
for (data in $element.data())
|
491
|
+
|
492
|
+
// if data attribute's name starts with "zdp_"
|
493
|
+
if (data.indexOf('zdp_') === 0) {
|
494
|
+
|
495
|
+
// remove the "zdp_" prefix
|
496
|
+
data = data.replace(/^zdp\_/, '');
|
497
|
+
|
498
|
+
// if such a property exists
|
499
|
+
if (undefined !== defaults[data])
|
500
|
+
|
501
|
+
// update the property's value
|
502
|
+
// (note that for the "pair" property we need to convert the property to an element)
|
503
|
+
plugin.settings[data] = (data === 'pair' ? $($element.data('zdp_' + data)) : $element.data('zdp_' + data));
|
504
|
+
|
505
|
+
}
|
506
|
+
|
507
|
+
}
|
508
|
+
|
509
|
+
// if the element should be read-only, set the "readonly" attribute
|
510
|
+
if (plugin.settings.readonly_element) $element.attr('readonly', 'readonly');
|
511
|
+
|
512
|
+
// assume there's no timepicker
|
513
|
+
timepicker_config = false;
|
514
|
+
|
515
|
+
// the views the user can cycle through
|
516
|
+
views = [];
|
517
|
+
|
518
|
+
// determine the views the user can cycle through, depending on the format
|
519
|
+
// that is, if the format doesn't contain the day, the user will be able to cycle only through years and months,
|
520
|
+
// whereas if the format doesn't contain months nor days, the user will only be able to select years
|
521
|
+
|
522
|
+
// iterate through all the character blocks
|
523
|
+
for (type in date_chars)
|
524
|
+
|
525
|
+
// iterate through the characters of each block
|
526
|
+
$.each(date_chars[type], function(index, character) {
|
527
|
+
|
528
|
+
var i, max;
|
529
|
+
|
530
|
+
// if current character exists in the "format" property
|
531
|
+
if (plugin.settings.format.indexOf(character) > -1)
|
532
|
+
|
533
|
+
// if user can cycle through the "days" view
|
534
|
+
if (type === 'days') views.push('days');
|
535
|
+
|
536
|
+
// if user can cycle through the "months" view
|
537
|
+
else if (type === 'months') views.push('months');
|
538
|
+
|
539
|
+
// if user can cycle through the "years" view
|
540
|
+
else if (type === 'years') views.push('years');
|
541
|
+
|
542
|
+
// if time is available in the date's format
|
543
|
+
else if (type === 'hours' || type === 'minutes' || type === 'seconds' || type === 'ampm') {
|
544
|
+
|
545
|
+
// if variable is not yet initialized
|
546
|
+
if (!timepicker_config) {
|
547
|
+
|
548
|
+
// initialize the variable now
|
549
|
+
timepicker_config = {is12hour: false};
|
550
|
+
|
551
|
+
// users may access the "time" view
|
552
|
+
views.push('time');
|
553
|
+
|
554
|
+
}
|
555
|
+
|
556
|
+
// if hours are available in the date's format
|
557
|
+
if (type === 'hours') {
|
558
|
+
|
559
|
+
// selectable hours (12 or 24) depending on the format
|
560
|
+
if (character === 'g' || character == 'h') {
|
561
|
+
|
562
|
+
max = 12;
|
563
|
+
|
564
|
+
// set a flag telling that the hour is 12 hour format
|
565
|
+
timepicker_config.is12hour = true;
|
566
|
+
|
567
|
+
} else max = 24;
|
568
|
+
|
569
|
+
timepicker_config.hours = [];
|
570
|
+
|
571
|
+
// iterate through valid hours
|
572
|
+
for (i = (max === 12 ? 1 : 0); i < (max === 12 ? 13 : max); i++)
|
573
|
+
|
574
|
+
// and add them to the lookup array if a user-defined list of values doesn't exist, or if the value is in that list
|
575
|
+
if (!$.isArray(plugin.settings.enabled_hours) || $.inArray(i, plugin.settings.enabled_hours) > -1) timepicker_config.hours.push(i);
|
576
|
+
|
577
|
+
// if minutes are available in the date's format
|
578
|
+
} else if (type === 'minutes') {
|
579
|
+
|
580
|
+
timepicker_config.minutes = [];
|
581
|
+
|
582
|
+
// iterate through valid minutes
|
583
|
+
for (i = 0; i < 60; i++)
|
584
|
+
|
585
|
+
// and add them to the lookup array if a user-defined list of values doesn't exist, or if the value is in that list
|
586
|
+
if (!$.isArray(plugin.settings.enabled_minutes) || $.inArray(i, plugin.settings.enabled_minutes) > -1) timepicker_config.minutes.push(i);
|
587
|
+
|
588
|
+
// if seconds are available in the date's format
|
589
|
+
} else if (type === 'seconds') {
|
590
|
+
|
591
|
+
timepicker_config.seconds = [];
|
592
|
+
|
593
|
+
// iterate through valid minutes
|
594
|
+
for (i = 0; i < 60; i++)
|
595
|
+
|
596
|
+
// and add them to the lookup array if a user-defined list of values doesn't exist, or if the value is in that list
|
597
|
+
if (!$.isArray(plugin.settings.enabled_seconds) || $.inArray(i, plugin.settings.enabled_seconds) > -1) timepicker_config.seconds.push(i);
|
598
|
+
|
599
|
+
// if am/pm is available in the date's format
|
600
|
+
} else
|
601
|
+
|
602
|
+
// pre-fill the array of selectable seconds
|
603
|
+
timepicker_config.ampm = ['am', 'pm'];
|
604
|
+
|
605
|
+
}
|
606
|
+
|
607
|
+
});
|
608
|
+
|
609
|
+
// if invalid format (no days, no months, no years) use the default where the user is able to cycle through
|
610
|
+
// all the views, except time
|
611
|
+
if (views.length === 0) views = ['years', 'months', 'days'];
|
612
|
+
|
613
|
+
// if the starting view is not amongst the views the user can cycle through, set the correct starting view
|
614
|
+
if ($.inArray(plugin.settings.view, views) === -1) plugin.settings.view = views[views.length - 1];
|
615
|
+
|
616
|
+
// parse the rules for disabling dates and turn them into arrays of arrays
|
617
|
+
|
618
|
+
for (k in plugin.settings.custom_classes) if (plugin.settings.custom_classes.hasOwnProperty(k)) custom_class_names.push(k);
|
619
|
+
|
620
|
+
// it's the same logic for preparing the enabled/disable dates, as well as dates that have custom classes
|
621
|
+
for (l = 0; l < 2 + custom_class_names.length; l++) {
|
622
|
+
|
623
|
+
// first time we're doing disabled dates,
|
624
|
+
if (l === 0) dates = plugin.settings.disabled_dates;
|
625
|
+
|
626
|
+
// second time we're doing enabled_dates
|
627
|
+
else if (l === 1) dates = plugin.settings.enabled_dates;
|
628
|
+
|
629
|
+
// otherwise, we're doing dates that will have custom classes
|
630
|
+
else dates = plugin.settings.custom_classes[custom_class_names[l - 2]];
|
631
|
+
|
632
|
+
// if we have a non-empty array
|
633
|
+
if ($.isArray(dates) && dates.length > 0)
|
634
|
+
|
635
|
+
// iterate through the rules
|
636
|
+
$.each(dates, function() {
|
637
|
+
|
638
|
+
// split the values in rule by white space
|
639
|
+
var rules = this.split(' '), i, j, k, limits;
|
640
|
+
|
641
|
+
// there can be a maximum of 4 rules (days, months, years and, optionally, day of the week)
|
642
|
+
for (i = 0; i < 4; i++) {
|
643
|
+
|
644
|
+
// if one of the values is not available
|
645
|
+
// replace it with a * (wildcard)
|
646
|
+
if (!rules[i]) rules[i] = '*';
|
647
|
+
|
648
|
+
// if rule contains a comma, create a new array by splitting the rule by commas
|
649
|
+
// if there are no commas create an array containing the rule's string
|
650
|
+
rules[i] = (rules[i].indexOf(',') > -1 ? rules[i].split(',') : new Array(rules[i]));
|
651
|
+
|
652
|
+
// iterate through the items in the rule
|
653
|
+
for (j = 0; j < rules[i].length; j++)
|
654
|
+
|
655
|
+
// if item contains a dash (defining a range)
|
656
|
+
if (rules[i][j].indexOf('-') > -1) {
|
657
|
+
|
658
|
+
// get the lower and upper limits of the range
|
659
|
+
limits = rules[i][j].match(/^([0-9]+)\-([0-9]+)/);
|
660
|
+
|
661
|
+
// if range is valid
|
662
|
+
if (null !== limits) {
|
663
|
+
|
664
|
+
// iterate through the range
|
665
|
+
for (k = to_int(limits[1]); k <= to_int(limits[2]); k++)
|
666
|
+
|
667
|
+
// if value is not already among the values of the rule
|
668
|
+
// add it to the rule
|
669
|
+
if ($.inArray(k, rules[i]) === -1) rules[i].push(k + '');
|
670
|
+
|
671
|
+
// remove the range indicator
|
672
|
+
rules[i].splice(j, 1);
|
673
|
+
|
674
|
+
}
|
675
|
+
|
676
|
+
}
|
677
|
+
|
678
|
+
// iterate through the items in the rule
|
679
|
+
// and make sure that numbers are numbers
|
680
|
+
for (j = 0; j < rules[i].length; j++) rules[i][j] = (isNaN(to_int(rules[i][j])) ? rules[i][j] : to_int(rules[i][j]));
|
681
|
+
|
682
|
+
}
|
683
|
+
|
684
|
+
// add to the correct list of processed rules
|
685
|
+
// first time we're doing disabled dates,
|
686
|
+
if (l === 0) disabled_dates.push(rules);
|
687
|
+
|
688
|
+
// second time we're doing enabled_dates
|
689
|
+
else if (l === 1) enabled_dates.push(rules);
|
690
|
+
|
691
|
+
// otherwise, we're doing the dates to which custom classes need to be applied
|
692
|
+
else {
|
693
|
+
|
694
|
+
if (undefined === custom_classes[custom_class_names[l - 2]]) custom_classes[custom_class_names[l - 2]] = [];
|
695
|
+
custom_classes[custom_class_names[l - 2]].push(rules);
|
696
|
+
|
697
|
+
}
|
698
|
+
|
699
|
+
});
|
700
|
+
|
701
|
+
}
|
702
|
+
|
703
|
+
var
|
704
|
+
|
705
|
+
// cache the current system date
|
706
|
+
date = new Date(),
|
707
|
+
|
708
|
+
// when the date picker's starting date depends on the value of another date picker, this value will be
|
709
|
+
// set by the other date picker
|
710
|
+
// this value will be used as base for all calculations (if not set, will be the same as the current
|
711
|
+
// system date)
|
712
|
+
reference_date = (!plugin.settings.reference_date ? ($element.data('zdp_reference_date') && undefined !== $element.data('zdp_reference_date') ? $element.data('zdp_reference_date') : date) : plugin.settings.reference_date),
|
713
|
+
|
714
|
+
tmp_start_date, tmp_end_date;
|
715
|
+
|
716
|
+
// reset these values here as this method might be called more than once during a date picker's lifetime
|
717
|
+
// (when the selectable dates depend on the values from another date picker)
|
718
|
+
start_date = undefined; end_date = undefined;
|
719
|
+
|
720
|
+
// extract the date parts
|
721
|
+
// also, save the current system month/day/year - we'll use them to highlight the current system date
|
722
|
+
first_selectable_month = reference_date.getMonth();
|
723
|
+
current_system_month = date.getMonth();
|
724
|
+
first_selectable_year = reference_date.getFullYear();
|
725
|
+
current_system_year = date.getFullYear();
|
726
|
+
first_selectable_day = reference_date.getDate();
|
727
|
+
current_system_day = date.getDate();
|
728
|
+
|
729
|
+
// check if the calendar has any restrictions
|
730
|
+
|
731
|
+
// calendar is future-only, starting today
|
732
|
+
// it means we have a starting date (the current system date), but no ending date
|
733
|
+
if (plugin.settings.direction === true) start_date = reference_date;
|
734
|
+
|
735
|
+
// calendar is past only, ending today
|
736
|
+
else if (plugin.settings.direction === false) {
|
737
|
+
|
738
|
+
// it means we have an ending date (the reference date), but no starting date
|
739
|
+
end_date = reference_date;
|
740
|
+
|
741
|
+
// extract the date parts
|
742
|
+
last_selectable_month = end_date.getMonth();
|
743
|
+
last_selectable_year = end_date.getFullYear();
|
744
|
+
last_selectable_day = end_date.getDate();
|
745
|
+
|
746
|
+
} else if (
|
747
|
+
|
748
|
+
// if direction is not given as an array and the value is an integer > 0
|
749
|
+
(!$.isArray(plugin.settings.direction) && is_integer(plugin.settings.direction) && to_int(plugin.settings.direction) > 0) ||
|
750
|
+
|
751
|
+
// or direction is given as an array
|
752
|
+
($.isArray(plugin.settings.direction) && (
|
753
|
+
|
754
|
+
// and first entry is a valid date
|
755
|
+
(tmp_start_date = check_date(plugin.settings.direction[0])) ||
|
756
|
+
// or a boolean TRUE
|
757
|
+
plugin.settings.direction[0] === true ||
|
758
|
+
// or an integer > 0
|
759
|
+
(is_integer(plugin.settings.direction[0]) && plugin.settings.direction[0] > 0)
|
760
|
+
|
761
|
+
) && (
|
762
|
+
|
763
|
+
// and second entry is a valid date
|
764
|
+
(tmp_end_date = check_date(plugin.settings.direction[1])) ||
|
765
|
+
// or a boolean FALSE
|
766
|
+
plugin.settings.direction[1] === false ||
|
767
|
+
// or integer >= 0
|
768
|
+
(is_integer(plugin.settings.direction[1]) && plugin.settings.direction[1] >= 0)
|
769
|
+
|
770
|
+
))
|
771
|
+
|
772
|
+
) {
|
773
|
+
|
774
|
+
// if an exact starting date was given, use that as a starting date
|
775
|
+
if (tmp_start_date) start_date = tmp_start_date;
|
776
|
+
|
777
|
+
// otherwise
|
778
|
+
else
|
779
|
+
|
780
|
+
// figure out the starting date
|
781
|
+
// use the Date object to normalize the date
|
782
|
+
// for example, 2011 05 33 will be transformed to 2011 06 02
|
783
|
+
start_date = new Date(
|
784
|
+
first_selectable_year,
|
785
|
+
first_selectable_month,
|
786
|
+
first_selectable_day + (!$.isArray(plugin.settings.direction) ? to_int(plugin.settings.direction) : to_int(plugin.settings.direction[0] === true ? 0 : plugin.settings.direction[0]))
|
787
|
+
);
|
788
|
+
|
789
|
+
// re-extract the date parts
|
790
|
+
first_selectable_month = start_date.getMonth();
|
791
|
+
first_selectable_year = start_date.getFullYear();
|
792
|
+
first_selectable_day = start_date.getDate();
|
793
|
+
|
794
|
+
// if an exact ending date was given and the date is after the starting date, use that as a ending date
|
795
|
+
if (tmp_end_date && +tmp_end_date >= +start_date) end_date = tmp_end_date;
|
796
|
+
|
797
|
+
// if have information about the ending date
|
798
|
+
else if (!tmp_end_date && plugin.settings.direction[1] !== false && $.isArray(plugin.settings.direction))
|
799
|
+
|
800
|
+
// figure out the ending date
|
801
|
+
// use the Date object to normalize the date
|
802
|
+
// for example, 2011 05 33 will be transformed to 2011 06 02
|
803
|
+
end_date = new Date(
|
804
|
+
first_selectable_year,
|
805
|
+
first_selectable_month,
|
806
|
+
first_selectable_day + to_int(plugin.settings.direction[1])
|
807
|
+
);
|
808
|
+
|
809
|
+
// if a valid ending date exists
|
810
|
+
if (end_date) {
|
811
|
+
|
812
|
+
// extract the date parts
|
813
|
+
last_selectable_month = end_date.getMonth();
|
814
|
+
last_selectable_year = end_date.getFullYear();
|
815
|
+
last_selectable_day = end_date.getDate();
|
816
|
+
|
817
|
+
}
|
818
|
+
|
819
|
+
} else if (
|
820
|
+
|
821
|
+
// if direction is not given as an array and the value is an integer < 0
|
822
|
+
(!$.isArray(plugin.settings.direction) && is_integer(plugin.settings.direction) && to_int(plugin.settings.direction) < 0) ||
|
823
|
+
|
824
|
+
// or direction is given as an array
|
825
|
+
($.isArray(plugin.settings.direction) && (
|
826
|
+
|
827
|
+
// and first entry is boolean FALSE
|
828
|
+
plugin.settings.direction[0] === false ||
|
829
|
+
// or an integer < 0
|
830
|
+
(is_integer(plugin.settings.direction[0]) && plugin.settings.direction[0] < 0)
|
831
|
+
|
832
|
+
) && (
|
833
|
+
|
834
|
+
// and second entry is a valid date
|
835
|
+
(tmp_start_date = check_date(plugin.settings.direction[1])) ||
|
836
|
+
// or an integer >= 0
|
837
|
+
(is_integer(plugin.settings.direction[1]) && plugin.settings.direction[1] >= 0)
|
838
|
+
|
839
|
+
))
|
840
|
+
|
841
|
+
) {
|
842
|
+
|
843
|
+
// figure out the ending date
|
844
|
+
// use the Date object to normalize the date
|
845
|
+
// for example, 2011 05 33 will be transformed to 2011 06 02
|
846
|
+
end_date = new Date(
|
847
|
+
first_selectable_year,
|
848
|
+
first_selectable_month,
|
849
|
+
first_selectable_day + (!$.isArray(plugin.settings.direction) ? to_int(plugin.settings.direction) : to_int(plugin.settings.direction[0] === false ? 0 : plugin.settings.direction[0]))
|
850
|
+
);
|
851
|
+
|
852
|
+
// re-extract the date parts
|
853
|
+
last_selectable_month = end_date.getMonth();
|
854
|
+
last_selectable_year = end_date.getFullYear();
|
855
|
+
last_selectable_day = end_date.getDate();
|
856
|
+
|
857
|
+
// if an exact starting date was given, and the date is before the ending date, use that as a starting date
|
858
|
+
if (tmp_start_date && +tmp_start_date < +end_date) start_date = tmp_start_date;
|
859
|
+
|
860
|
+
// if have information about the starting date
|
861
|
+
else if (!tmp_start_date && $.isArray(plugin.settings.direction))
|
862
|
+
|
863
|
+
// figure out the staring date
|
864
|
+
// use the Date object to normalize the date
|
865
|
+
// for example, 2011 05 33 will be transformed to 2011 06 02
|
866
|
+
start_date = new Date(
|
867
|
+
last_selectable_year,
|
868
|
+
last_selectable_month,
|
869
|
+
last_selectable_day - to_int(plugin.settings.direction[1])
|
870
|
+
);
|
871
|
+
|
872
|
+
// if a valid starting date exists
|
873
|
+
if (start_date) {
|
874
|
+
|
875
|
+
// extract the date parts
|
876
|
+
first_selectable_month = start_date.getMonth();
|
877
|
+
first_selectable_year = start_date.getFullYear();
|
878
|
+
first_selectable_day = start_date.getDate();
|
879
|
+
|
880
|
+
}
|
881
|
+
|
882
|
+
// if there are disabled dates
|
883
|
+
} else if ($.isArray(plugin.settings.disabled_dates) && plugin.settings.disabled_dates.length > 0)
|
884
|
+
|
885
|
+
// iterate through the rules for disabling dates
|
886
|
+
for (var interval in disabled_dates)
|
887
|
+
|
888
|
+
// only if there is a rule that disables *everything*
|
889
|
+
if (disabled_dates[interval][0] === '*' && disabled_dates[interval][1] === '*' && disabled_dates[interval][2] === '*' && disabled_dates[interval][3] === '*') {
|
890
|
+
|
891
|
+
var tmpDates = [];
|
892
|
+
|
893
|
+
// iterate through the rules for enabling dates
|
894
|
+
// looking for the minimum/maximum selectable date (if it's the case)
|
895
|
+
$.each(enabled_dates, function() {
|
896
|
+
|
897
|
+
var rule = this;
|
898
|
+
|
899
|
+
// if the rule doesn't apply to all years
|
900
|
+
if (rule[2][0] !== '*')
|
901
|
+
|
902
|
+
// format date and store it in our stack
|
903
|
+
tmpDates.push(parseInt(
|
904
|
+
rule[2][0] +
|
905
|
+
(rule[1][0] === '*' ? '12' : str_pad(rule[1][0], 2)) +
|
906
|
+
(rule[0][0] === '*' ? (rule[1][0] === '*' ? '31' : new Date(rule[2][0], rule[1][0], 0).getDate()) : str_pad(rule[0][0], 2)), 10));
|
907
|
+
|
908
|
+
});
|
909
|
+
|
910
|
+
// sort dates ascending
|
911
|
+
tmpDates.sort();
|
912
|
+
|
913
|
+
// if we have any rules
|
914
|
+
if (tmpDates.length > 0) {
|
915
|
+
|
916
|
+
// get date parts
|
917
|
+
var matches = (tmpDates[0] + '').match(/([0-9]{4})([0-9]{2})([0-9]{2})/);
|
918
|
+
|
919
|
+
// assign the date parts to the appropriate variables
|
920
|
+
first_selectable_year = parseInt(matches[1], 10);
|
921
|
+
first_selectable_month = parseInt(matches[2], 10) - 1;
|
922
|
+
first_selectable_day = parseInt(matches[3], 10);
|
923
|
+
|
924
|
+
}
|
925
|
+
|
926
|
+
// don't look further
|
927
|
+
break;
|
928
|
+
|
929
|
+
}
|
930
|
+
|
931
|
+
// if first selectable date exists but is disabled, find the actual first selectable date
|
932
|
+
if (is_disabled(first_selectable_year, first_selectable_month, first_selectable_day)) {
|
933
|
+
|
934
|
+
// loop until we find the first selectable year
|
935
|
+
while (is_disabled(first_selectable_year))
|
936
|
+
|
937
|
+
// if calendar is past-only,
|
938
|
+
if (!start_date) {
|
939
|
+
|
940
|
+
// decrement the year
|
941
|
+
first_selectable_year--;
|
942
|
+
|
943
|
+
// because we've changed years, reset the month to December
|
944
|
+
first_selectable_month = 11;
|
945
|
+
|
946
|
+
// otherwise
|
947
|
+
} else {
|
948
|
+
|
949
|
+
// increment the year
|
950
|
+
first_selectable_year++;
|
951
|
+
|
952
|
+
// because we've changed years, reset the month to January
|
953
|
+
first_selectable_month = 0;
|
954
|
+
|
955
|
+
}
|
956
|
+
|
957
|
+
// loop until we find the first selectable month
|
958
|
+
while (is_disabled(first_selectable_year, first_selectable_month)) {
|
959
|
+
|
960
|
+
// if calendar is past-only
|
961
|
+
if (!start_date) {
|
962
|
+
|
963
|
+
// decrement the month
|
964
|
+
first_selectable_month--;
|
965
|
+
|
966
|
+
// because we've changed months, reset the day to the last day of the month
|
967
|
+
first_selectable_day = new Date(first_selectable_year, first_selectable_month + 1, 0).getDate();
|
968
|
+
|
969
|
+
// otherwise
|
970
|
+
} else {
|
971
|
+
|
972
|
+
// increment the month
|
973
|
+
first_selectable_month++;
|
974
|
+
|
975
|
+
// because we've changed months, reset the day to the first day of the month
|
976
|
+
first_selectable_day = 1;
|
977
|
+
|
978
|
+
}
|
979
|
+
|
980
|
+
// if we moved to a following year
|
981
|
+
if (first_selectable_month > 11) {
|
982
|
+
|
983
|
+
// increment the year
|
984
|
+
first_selectable_year++;
|
985
|
+
|
986
|
+
// reset the month to January
|
987
|
+
first_selectable_month = 0;
|
988
|
+
|
989
|
+
// because we've changed months, reset the day to the first day of the month
|
990
|
+
first_selectable_day = 1;
|
991
|
+
|
992
|
+
// if we moved to a previous year
|
993
|
+
} else if (first_selectable_month < 0) {
|
994
|
+
|
995
|
+
// decrement the year
|
996
|
+
first_selectable_year--;
|
997
|
+
|
998
|
+
// reset the month to December
|
999
|
+
first_selectable_month = 11;
|
1000
|
+
|
1001
|
+
// because we've changed months, reset the day to the last day of the month
|
1002
|
+
first_selectable_day = new Date(first_selectable_year, first_selectable_month + 1, 0).getDate();
|
1003
|
+
|
1004
|
+
}
|
1005
|
+
|
1006
|
+
}
|
1007
|
+
|
1008
|
+
// loop until we find the first selectable day
|
1009
|
+
while (is_disabled(first_selectable_year, first_selectable_month, first_selectable_day)) {
|
1010
|
+
|
1011
|
+
// if calendar is past-only, decrement the day
|
1012
|
+
if (!start_date) first_selectable_day--;
|
1013
|
+
|
1014
|
+
// otherwise, increment the day
|
1015
|
+
else first_selectable_day++;
|
1016
|
+
|
1017
|
+
// use the Date object to normalize the date
|
1018
|
+
// for example, 2011 05 33 will be transformed to 2011 06 02
|
1019
|
+
date = new Date(first_selectable_year, first_selectable_month, first_selectable_day);
|
1020
|
+
|
1021
|
+
// re-extract date parts from the normalized date
|
1022
|
+
// as we use them in the current loop
|
1023
|
+
first_selectable_year = date.getFullYear();
|
1024
|
+
first_selectable_month = date.getMonth();
|
1025
|
+
first_selectable_day = date.getDate();
|
1026
|
+
|
1027
|
+
}
|
1028
|
+
|
1029
|
+
// use the Date object to normalize the date
|
1030
|
+
// for example, 2011 05 33 will be transformed to 2011 06 02
|
1031
|
+
date = new Date(first_selectable_year, first_selectable_month, first_selectable_day);
|
1032
|
+
|
1033
|
+
// re-extract date parts from the normalized date
|
1034
|
+
// as we use them in the current loop
|
1035
|
+
first_selectable_year = date.getFullYear();
|
1036
|
+
first_selectable_month = date.getMonth();
|
1037
|
+
first_selectable_day = date.getDate();
|
1038
|
+
|
1039
|
+
}
|
1040
|
+
|
1041
|
+
// get the default date, from the element, and check if it represents a valid date, according to the required format
|
1042
|
+
var default_date = check_date($element.val() || (plugin.settings.start_date ? plugin.settings.start_date : ''));
|
1043
|
+
|
1044
|
+
// if there is a default date, date picker is in "strict" mode, and the default date is disabled
|
1045
|
+
if (default_date && plugin.settings.strict && is_disabled(default_date.getFullYear(), default_date.getMonth(), default_date.getDate()))
|
1046
|
+
|
1047
|
+
// clear the value of the parent element
|
1048
|
+
$element.val('');
|
1049
|
+
|
1050
|
+
// updates value for the date picker whose starting date depends on the selected date (if any)
|
1051
|
+
if (!update && (undefined !== start_date || undefined !== default_date))
|
1052
|
+
update_dependent(undefined !== default_date ? default_date : start_date);
|
1053
|
+
|
1054
|
+
// if date picker is not always visible in a container
|
1055
|
+
if (!(plugin.settings.always_visible instanceof jQuery)) {
|
1056
|
+
|
1057
|
+
// if we're just creating the date picker
|
1058
|
+
if (!update) {
|
1059
|
+
|
1060
|
+
// if a calendar icon should be added to the element the plugin is attached to, create the icon now
|
1061
|
+
if (plugin.settings.show_icon) {
|
1062
|
+
|
1063
|
+
// strangely, in Firefox 21+ (or maybe even earlier) input elements have their "display" property
|
1064
|
+
// set to "inline" instead of "inline-block" as do all the other browsers.
|
1065
|
+
// because this behavior brakes the positioning of the icon, we'll set the "display" property to
|
1066
|
+
// "inline-block" before anything else;
|
1067
|
+
if (browser.name === 'firefox' && $element.is('input[type="text"]') && $element.css('display') === 'inline') $element.css('display', 'inline-block');
|
1068
|
+
|
1069
|
+
// we create a wrapper for the parent element so that we can later position the icon
|
1070
|
+
// also, make sure the wrapper inherits some important css properties of the parent element
|
1071
|
+
var icon_wrapper = $('<span class="Zebra_DatePicker_Icon_Wrapper"></span>').css({
|
1072
|
+
display: $element.css('display'),
|
1073
|
+
position: $element.css('position') === 'static' ? 'relative' : $element.css('position'),
|
1074
|
+
float: $element.css('float'),
|
1075
|
+
top: $element.css('top'),
|
1076
|
+
right: $element.css('right'),
|
1077
|
+
bottom: $element.css('bottom'),
|
1078
|
+
left: $element.css('left')
|
1079
|
+
});
|
1080
|
+
|
1081
|
+
// if parent element has its "display" property set to "block"
|
1082
|
+
// the wrapper has to have its "width" set
|
1083
|
+
if ($element.css('display') === 'block') icon_wrapper.css('width', $element.outerWidth(true));
|
1084
|
+
|
1085
|
+
// put wrapper around the element
|
1086
|
+
// also, make sure we set some important css properties for it
|
1087
|
+
$element.wrap(icon_wrapper).css({
|
1088
|
+
position: 'relative',
|
1089
|
+
top: 'auto',
|
1090
|
+
right: 'auto',
|
1091
|
+
bottom: 'auto',
|
1092
|
+
left: 'auto'
|
1093
|
+
});
|
1094
|
+
|
1095
|
+
// create the actual calendar icon (show a disabled icon if the element is disabled)
|
1096
|
+
icon = $('<button type="button" class="Zebra_DatePicker_Icon' + ($element.attr('disabled') === 'disabled' ? ' Zebra_DatePicker_Icon_Disabled' : '') + '">Pick a date</button>');
|
1097
|
+
|
1098
|
+
// a reference to the icon, as a global property
|
1099
|
+
plugin.icon = icon;
|
1100
|
+
|
1101
|
+
// the date picker will open when clicking both the icon and the element the plugin is attached to
|
1102
|
+
// (or the icon only, if set so)
|
1103
|
+
clickables = plugin.settings.open_icon_only ? icon : icon.add($element);
|
1104
|
+
|
1105
|
+
// if calendar icon is not visible, the date picker will open when clicking the element
|
1106
|
+
} else clickables = $element;
|
1107
|
+
|
1108
|
+
// attach the "click" and, if required, the "focus" event to the clickable elements (icon and/or element)
|
1109
|
+
clickables.on('click.Zebra_DatePicker_' + uniqueid + (plugin.settings.open_on_focus ? ' focus.Zebra_DatePicker_' + uniqueid : ''), function() {
|
1110
|
+
|
1111
|
+
// if date picker is not visible and element is not disabled
|
1112
|
+
if (datepicker.hasClass('dp_hidden') && !$element.attr('disabled'))
|
1113
|
+
|
1114
|
+
// show the date picker
|
1115
|
+
plugin.show();
|
1116
|
+
|
1117
|
+
});
|
1118
|
+
|
1119
|
+
// attach a keydown event to the clickable elements (icon and/or element)
|
1120
|
+
clickables.on('keydown.Zebra_DatePicker_' + uniqueid, function(e) {
|
1121
|
+
|
1122
|
+
// if "Tab" key was pressed and the date picker is visible
|
1123
|
+
if (e.keyCode === 9 && !datepicker.hasClass('dp_hidden'))
|
1124
|
+
|
1125
|
+
// hide the date picker
|
1126
|
+
plugin.hide();
|
1127
|
+
|
1128
|
+
});
|
1129
|
+
|
1130
|
+
// if users can manually enter dates and a pair date element exists
|
1131
|
+
if (!plugin.settings.readonly_element && plugin.settings.pair)
|
1132
|
+
|
1133
|
+
// whenever the element looses focus
|
1134
|
+
$element.on('blur.Zebra_DatePicker_' + uniqueid, function() {
|
1135
|
+
|
1136
|
+
var date;
|
1137
|
+
|
1138
|
+
// if a valid date was entered, update the paired date picker
|
1139
|
+
if ((date = check_date($(this).val())) && !is_disabled(date.getFullYear(), date.getMonth(), date.getDate())) update_dependent(date);
|
1140
|
+
|
1141
|
+
});
|
1142
|
+
|
1143
|
+
// if icon exists, inject it into the DOM, right after the parent element (and inside the wrapper)
|
1144
|
+
if (undefined !== icon) icon.insertAfter($element);
|
1145
|
+
|
1146
|
+
}
|
1147
|
+
|
1148
|
+
// if calendar icon exists
|
1149
|
+
if (undefined !== icon) {
|
1150
|
+
|
1151
|
+
// needed when updating: remove any inline style set previously by library,
|
1152
|
+
// so we get the right values below
|
1153
|
+
icon.attr('style', '');
|
1154
|
+
|
1155
|
+
// if calendar icon is to be placed *inside* the element
|
1156
|
+
// add an extra class to the icon
|
1157
|
+
if (plugin.settings.inside) icon.addClass('Zebra_DatePicker_Icon_Inside_' + (plugin.settings.icon_position === 'right' ? 'Right' : 'Left'));
|
1158
|
+
|
1159
|
+
var
|
1160
|
+
|
1161
|
+
// get element's width and height (including margins)
|
1162
|
+
element_width = $element.outerWidth(),
|
1163
|
+
element_height = $element.outerHeight(),
|
1164
|
+
element_margin_left = parseInt($element.css('marginLeft'), 10) || 0,
|
1165
|
+
element_margin_top = parseInt($element.css('marginTop'), 10) || 0,
|
1166
|
+
|
1167
|
+
// get icon's width, height and margins
|
1168
|
+
icon_width = icon.outerWidth(),
|
1169
|
+
icon_height = icon.outerHeight(),
|
1170
|
+
icon_margin_left = parseInt(icon.css('marginLeft'), 10) || 0,
|
1171
|
+
icon_margin_right = parseInt(icon.css('marginRight'), 10) || 0;
|
1172
|
+
|
1173
|
+
// if icon is to be placed *inside* the element
|
1174
|
+
// position the icon accordingly
|
1175
|
+
if (plugin.settings.inside) {
|
1176
|
+
|
1177
|
+
// set icon's top
|
1178
|
+
icon.css('top', element_margin_top + ((element_height - icon_height) / 2));
|
1179
|
+
|
1180
|
+
// place icon to the right or to the left, according to the settings
|
1181
|
+
if (plugin.settings.icon_position === 'right') icon.css('right', 0);
|
1182
|
+
else icon.css('left', 0);
|
1183
|
+
|
1184
|
+
// if icon is to be placed to the right of the element
|
1185
|
+
// position the icon accordingly
|
1186
|
+
} else
|
1187
|
+
|
1188
|
+
icon.css({
|
1189
|
+
top: element_margin_top + ((element_height - icon_height) / 2),
|
1190
|
+
left: element_margin_left + element_width + icon_margin_left
|
1191
|
+
});
|
1192
|
+
|
1193
|
+
// assume the datepicker is not disabled
|
1194
|
+
icon.removeClass(' Zebra_DatePicker_Icon_Disabled');
|
1195
|
+
|
1196
|
+
// if element the datepicker is attached to became disabled, disable the calendar icon, too
|
1197
|
+
if ($element.attr('disabled') === 'disabled') icon.addClass('Zebra_DatePicker_Icon_Disabled');
|
1198
|
+
|
1199
|
+
}
|
1200
|
+
|
1201
|
+
}
|
1202
|
+
|
1203
|
+
// if the "Today" button is to be shown and it makes sense to be shown
|
1204
|
+
// (the "days" view is available and "today" is not a disabled date)
|
1205
|
+
show_select_today = (plugin.settings.show_select_today !== false && $.inArray('days', views) > -1 && !is_disabled(current_system_year, current_system_month, current_system_day) ? plugin.settings.show_select_today : false);
|
1206
|
+
|
1207
|
+
// if we just needed to recompute the things above
|
1208
|
+
if (update) {
|
1209
|
+
|
1210
|
+
// make sure we update these strings, in case they've changed
|
1211
|
+
$('.dp_previous', datepicker).html(plugin.settings.navigation[0]);
|
1212
|
+
$('.dp_next', datepicker).html(plugin.settings.navigation[1]);
|
1213
|
+
$('.dp_time_controls_increase .dp_time_control', datepicker).html(plugin.settings.navigation[2]);
|
1214
|
+
$('.dp_time_controls_decrease .dp_time_control', datepicker).html(plugin.settings.navigation[3]);
|
1215
|
+
$('.dp_clear', datepicker).html(plugin.settings.lang_clear_date);
|
1216
|
+
$('.dp_today', datepicker).html(plugin.settings.show_select_today);
|
1217
|
+
|
1218
|
+
// don't go further
|
1219
|
+
return;
|
1220
|
+
|
1221
|
+
}
|
1222
|
+
|
1223
|
+
// update icon/date picker position on resize and/or changing orientation
|
1224
|
+
$(window).on('resize.Zebra_DatePicker_' + uniqueid + ', orientationchange.Zebra_DatePicker_' + uniqueid, function() {
|
1225
|
+
|
1226
|
+
// hide the date picker
|
1227
|
+
plugin.hide();
|
1228
|
+
|
1229
|
+
// if the icon is visible, update its position as the parent element might have changed position
|
1230
|
+
if (icon !== undefined) {
|
1231
|
+
|
1232
|
+
// we use timeouts so that we do not call the "update" method on *every* step of the resize event
|
1233
|
+
|
1234
|
+
// clear a previously set timeout
|
1235
|
+
clearTimeout(timeout);
|
1236
|
+
|
1237
|
+
// set timeout again
|
1238
|
+
timeout = setTimeout(function() {
|
1239
|
+
|
1240
|
+
// update the date picker
|
1241
|
+
plugin.update();
|
1242
|
+
|
1243
|
+
}, 100);
|
1244
|
+
|
1245
|
+
}
|
1246
|
+
|
1247
|
+
});
|
1248
|
+
|
1249
|
+
// generate the container that will hold everything
|
1250
|
+
var html = '' +
|
1251
|
+
'<div class="Zebra_DatePicker">' +
|
1252
|
+
'<table class="dp_header dp_actions">' +
|
1253
|
+
'<tr>' +
|
1254
|
+
'<td class="dp_previous">' + plugin.settings.navigation[0] + '</td>' +
|
1255
|
+
'<td class="dp_caption"></td>' +
|
1256
|
+
'<td class="dp_next">' + plugin.settings.navigation[1] + '</td>' +
|
1257
|
+
'</tr>' +
|
1258
|
+
'</table>' +
|
1259
|
+
'<table class="dp_daypicker' + (plugin.settings.show_week_number ? ' dp_week_numbers' : '') + ' dp_body"></table>' +
|
1260
|
+
'<table class="dp_monthpicker dp_body"></table>' +
|
1261
|
+
'<table class="dp_yearpicker dp_body"></table>' +
|
1262
|
+
'<table class="dp_timepicker dp_body"></table>' +
|
1263
|
+
'<table class="dp_footer dp_actions"><tr>' +
|
1264
|
+
'<td class="dp_today">' + show_select_today + '</td>' +
|
1265
|
+
'<td class="dp_clear">' + plugin.settings.lang_clear_date + '</td>' +
|
1266
|
+
'<td class="dp_view_toggler dp_icon"></td>' +
|
1267
|
+
'<td class="dp_confirm dp_icon"></td>' +
|
1268
|
+
'</tr></table>' +
|
1269
|
+
'</div>';
|
1270
|
+
|
1271
|
+
// create a jQuery object out of the HTML above and create a reference to it
|
1272
|
+
datepicker = $(html);
|
1273
|
+
|
1274
|
+
// create references to the different parts of the date picker
|
1275
|
+
header = $('table.dp_header', datepicker);
|
1276
|
+
daypicker = $('table.dp_daypicker', datepicker);
|
1277
|
+
monthpicker = $('table.dp_monthpicker', datepicker);
|
1278
|
+
yearpicker = $('table.dp_yearpicker', datepicker);
|
1279
|
+
timepicker = $('table.dp_timepicker', datepicker);
|
1280
|
+
footer = $('table.dp_footer', datepicker);
|
1281
|
+
selecttoday = $('td.dp_today', footer);
|
1282
|
+
cleardate = $('td.dp_clear', footer);
|
1283
|
+
view_toggler = $('td.dp_view_toggler', footer);
|
1284
|
+
confirm_selection = $('td.dp_confirm', footer);
|
1285
|
+
|
1286
|
+
// if date picker is not always visible in a container
|
1287
|
+
if (!(plugin.settings.always_visible instanceof jQuery))
|
1288
|
+
|
1289
|
+
// inject the container into the DOM
|
1290
|
+
plugin.settings.container.append(datepicker);
|
1291
|
+
|
1292
|
+
// otherwise, if element is not disabled
|
1293
|
+
else if (!$element.attr('disabled')) {
|
1294
|
+
|
1295
|
+
// inject the date picker into the designated container element
|
1296
|
+
plugin.settings.always_visible.append(datepicker);
|
1297
|
+
|
1298
|
+
// and make it visible right away
|
1299
|
+
plugin.show();
|
1300
|
+
|
1301
|
+
}
|
1302
|
+
|
1303
|
+
// add the mouseover/mousevents to all to the date picker's cells
|
1304
|
+
// except those that are not selectable
|
1305
|
+
datepicker
|
1306
|
+
.on('mouseover', 'td:not(.dp_disabled)', function() {
|
1307
|
+
$(this).addClass('dp_hover');
|
1308
|
+
})
|
1309
|
+
.on('mouseout', 'td:not(.dp_disabled)', function() {
|
1310
|
+
$(this).removeClass('dp_hover');
|
1311
|
+
});
|
1312
|
+
|
1313
|
+
// prevent text selection (prevent accidental select when user clicks too fast)
|
1314
|
+
disable_text_select(datepicker);
|
1315
|
+
|
1316
|
+
// event for when clicking the "previous" button
|
1317
|
+
$('.dp_previous', header).on('click', function() {
|
1318
|
+
|
1319
|
+
// if view is "months"
|
1320
|
+
// decrement year by one
|
1321
|
+
if (view === 'months') selected_year--;
|
1322
|
+
|
1323
|
+
// if view is "years"
|
1324
|
+
// decrement years by 12
|
1325
|
+
else if (view === 'years') selected_year -= 12;
|
1326
|
+
|
1327
|
+
// if view is "days"
|
1328
|
+
// decrement the month and
|
1329
|
+
// if month is out of range
|
1330
|
+
else if (--selected_month < 0) {
|
1331
|
+
|
1332
|
+
// go to the last month of the previous year
|
1333
|
+
selected_month = 11;
|
1334
|
+
selected_year--;
|
1335
|
+
|
1336
|
+
}
|
1337
|
+
|
1338
|
+
// generate the appropriate view
|
1339
|
+
manage_views();
|
1340
|
+
|
1341
|
+
});
|
1342
|
+
|
1343
|
+
// attach a click event to the caption in header
|
1344
|
+
$('.dp_caption', header).on('click', function() {
|
1345
|
+
|
1346
|
+
// if current view is "days", take the user to the next view, depending on the format
|
1347
|
+
if (view === 'days') view = ($.inArray('months', views) > -1 ? 'months' : ($.inArray('years', views) > -1 ? 'years' : 'days'));
|
1348
|
+
|
1349
|
+
// if current view is "months", take the user to the next view, depending on the format
|
1350
|
+
else if (view === 'months') view = ($.inArray('years', views) > -1 ? 'years' : ($.inArray('days', views) > -1 ? 'days' : 'months'));
|
1351
|
+
|
1352
|
+
// if current view is "years", take the user to the next view, depending on the format
|
1353
|
+
else view = ($.inArray('days', views) > -1 ? 'days' : ($.inArray('months', views) > -1 ? 'months' : 'years'));
|
1354
|
+
|
1355
|
+
// generate the appropriate view
|
1356
|
+
manage_views();
|
1357
|
+
|
1358
|
+
});
|
1359
|
+
|
1360
|
+
// event for when clicking the "next" button
|
1361
|
+
$('.dp_next', header).on('click', function() {
|
1362
|
+
|
1363
|
+
// if view is "months"
|
1364
|
+
// increment year by 1
|
1365
|
+
if (view === 'months') selected_year++;
|
1366
|
+
|
1367
|
+
// if view is "years"
|
1368
|
+
// increment years by 12
|
1369
|
+
else if (view === 'years') selected_year += 12;
|
1370
|
+
|
1371
|
+
// if view is "days"
|
1372
|
+
// increment the month and
|
1373
|
+
// if month is out of range
|
1374
|
+
else if (++selected_month === 12) {
|
1375
|
+
|
1376
|
+
// go to the first month of the next year
|
1377
|
+
selected_month = 0;
|
1378
|
+
selected_year++;
|
1379
|
+
|
1380
|
+
}
|
1381
|
+
|
1382
|
+
// generate the appropriate view
|
1383
|
+
manage_views();
|
1384
|
+
|
1385
|
+
});
|
1386
|
+
|
1387
|
+
// attach a click event for the cells in the day picker
|
1388
|
+
daypicker.on('click', 'td:not(.dp_disabled)', function() {
|
1389
|
+
|
1390
|
+
var matches;
|
1391
|
+
|
1392
|
+
// if other months are selectable and currently clicked cell contains a class with the cell's date
|
1393
|
+
if (plugin.settings.select_other_months && $(this).attr('class') && null !== (matches = $(this).attr('class').match(/date\_([0-9]{4})(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])/)))
|
1394
|
+
|
1395
|
+
// use the stored date
|
1396
|
+
select_date(matches[1], matches[2] - 1, matches[3], 'days', $(this));
|
1397
|
+
|
1398
|
+
// put selected date in the element the plugin is attached to, and hide the date picker
|
1399
|
+
else select_date(selected_year, selected_month, to_int($(this).html()), 'days', $(this));
|
1400
|
+
|
1401
|
+
});
|
1402
|
+
|
1403
|
+
// attach a click event for the cells in the month picker
|
1404
|
+
monthpicker.on('click', 'td:not(.dp_disabled)', function() {
|
1405
|
+
|
1406
|
+
// get the month we've clicked on
|
1407
|
+
var matches = $(this).attr('class').match(/dp\_month\_([0-9]+)/);
|
1408
|
+
|
1409
|
+
// set the selected month
|
1410
|
+
selected_month = to_int(matches[1]);
|
1411
|
+
|
1412
|
+
// if user can select only years and months
|
1413
|
+
if ($.inArray('days', views) === -1)
|
1414
|
+
|
1415
|
+
// put selected date in the element the plugin is attached to, and hide the date picker
|
1416
|
+
select_date(selected_year, selected_month, 1, 'months', $(this));
|
1417
|
+
|
1418
|
+
else {
|
1419
|
+
|
1420
|
+
// direct the user to the "days" view
|
1421
|
+
view = 'days';
|
1422
|
+
|
1423
|
+
// if date picker is always visible
|
1424
|
+
// empty the value in the text box the date picker is attached to
|
1425
|
+
if (plugin.settings.always_visible) $element.val('');
|
1426
|
+
|
1427
|
+
// generate the appropriate view
|
1428
|
+
manage_views();
|
1429
|
+
|
1430
|
+
}
|
1431
|
+
|
1432
|
+
});
|
1433
|
+
|
1434
|
+
// attach a click event for the cells in the year picker
|
1435
|
+
yearpicker.on('click', 'td:not(.dp_disabled)', function() {
|
1436
|
+
|
1437
|
+
// set the selected year
|
1438
|
+
selected_year = to_int($(this).html());
|
1439
|
+
|
1440
|
+
// if user can select only years
|
1441
|
+
if ($.inArray('months', views) === -1)
|
1442
|
+
|
1443
|
+
// put selected date in the element the plugin is attached to, and hide the date picker
|
1444
|
+
select_date(selected_year, 1, 1, 'years', $(this));
|
1445
|
+
|
1446
|
+
else {
|
1447
|
+
|
1448
|
+
// direct the user to the "months" view
|
1449
|
+
view = 'months';
|
1450
|
+
|
1451
|
+
// if date picker is always visible
|
1452
|
+
// empty the value in the text box the date picker is attached to
|
1453
|
+
if (plugin.settings.always_visible) $element.val('');
|
1454
|
+
|
1455
|
+
// generate the appropriate view
|
1456
|
+
manage_views();
|
1457
|
+
|
1458
|
+
}
|
1459
|
+
|
1460
|
+
});
|
1461
|
+
|
1462
|
+
// function to execute when the "Today" button is clicked
|
1463
|
+
selecttoday.on('click', function(e) {
|
1464
|
+
|
1465
|
+
// date might have changed since we opened the date picker, so always use the current date
|
1466
|
+
var date = new Date;
|
1467
|
+
|
1468
|
+
e.preventDefault();
|
1469
|
+
|
1470
|
+
// select the current date
|
1471
|
+
select_date(date.getFullYear(), date.getMonth(), date.getDate(), 'days', $('.dp_current', daypicker));
|
1472
|
+
|
1473
|
+
});
|
1474
|
+
|
1475
|
+
// function to execute when the "Clear" button is clicked
|
1476
|
+
cleardate.on('click', function(e) {
|
1477
|
+
|
1478
|
+
e.preventDefault();
|
1479
|
+
|
1480
|
+
// clear the element's value
|
1481
|
+
$element.val('');
|
1482
|
+
|
1483
|
+
// reset these values
|
1484
|
+
default_day = null; default_month = null; default_year = null;
|
1485
|
+
|
1486
|
+
// if date picker is not always visible
|
1487
|
+
if (!plugin.settings.always_visible) {
|
1488
|
+
|
1489
|
+
// reset these values
|
1490
|
+
selected_month = null; selected_year = null;
|
1491
|
+
|
1492
|
+
// if date picker is always visible
|
1493
|
+
} else
|
1494
|
+
|
1495
|
+
// remove the "selected" class from all cells that have it
|
1496
|
+
$('td.dp_selected', datepicker).removeClass('dp_selected');
|
1497
|
+
|
1498
|
+
// give the focus back to the parent element
|
1499
|
+
$element.focus();
|
1500
|
+
|
1501
|
+
// hide the date picker
|
1502
|
+
plugin.hide();
|
1503
|
+
|
1504
|
+
// if a callback function exists for when clearing a date
|
1505
|
+
if (plugin.settings.onClear && typeof plugin.settings.onClear === 'function')
|
1506
|
+
|
1507
|
+
// execute the callback function and pass as argument the element the plugin is attached to
|
1508
|
+
plugin.settings.onClear.call($element, $element);
|
1509
|
+
|
1510
|
+
});
|
1511
|
+
|
1512
|
+
// function to execute when the clock/calendar button is clicked in the footer
|
1513
|
+
view_toggler.on('click', function() {
|
1514
|
+
|
1515
|
+
// if we're not in the time picker mode
|
1516
|
+
if (view !== 'time') {
|
1517
|
+
|
1518
|
+
// switch to time picker mode
|
1519
|
+
view = 'time';
|
1520
|
+
manage_views();
|
1521
|
+
|
1522
|
+
// if we are already in the time picker mode,
|
1523
|
+
// switch back to the standard view
|
1524
|
+
// (let the click on the header's caption handle things)
|
1525
|
+
} else $('.dp_caption', header).trigger('click');
|
1526
|
+
|
1527
|
+
});
|
1528
|
+
|
1529
|
+
// when the "confirm selection" button is clicked, hide the date picker
|
1530
|
+
// (visible only when in the "time" view)
|
1531
|
+
confirm_selection.on('click', function() {
|
1532
|
+
|
1533
|
+
// as users may click this before making any adjustments to time, simulate time adjustment so that
|
1534
|
+
// a value is selected
|
1535
|
+
$('.dp_time_controls_increase td').trigger('click');
|
1536
|
+
$('.dp_time_controls_decrease td').trigger('click');
|
1537
|
+
|
1538
|
+
plugin.hide();
|
1539
|
+
|
1540
|
+
});
|
1541
|
+
|
1542
|
+
// handle value increases on the time picker
|
1543
|
+
datepicker.on('click', '.dp_time_controls_increase td, .dp_time_controls_decrease td', function() {
|
1544
|
+
|
1545
|
+
var
|
1546
|
+
|
1547
|
+
// are we increasing or decreasing values?
|
1548
|
+
increase = $(this).parent('.dp_time_controls_increase').length > 0,
|
1549
|
+
|
1550
|
+
// figure out what we're increasing (hour, minutes, seconds, ampm)
|
1551
|
+
matches = $(this).attr('class').match(/dp\_time\_([^\s]+)/i),
|
1552
|
+
value_container = $('.dp_time_segments .dp_time_' + matches[1] + (matches[1] !== 'ampm' ? 's' : ''), timepicker),
|
1553
|
+
|
1554
|
+
// the current value (strip the zeros in front)
|
1555
|
+
value = value_container.text().toLowerCase(),
|
1556
|
+
|
1557
|
+
// the array with allowed values
|
1558
|
+
lookup = timepicker_config[matches[1] + (matches[1] !== 'ampm' ? 's' : '')],
|
1559
|
+
|
1560
|
+
// the current value's position in the array of allowed values
|
1561
|
+
current_value_position = lookup.indexOf(matches[1] !== 'ampm' ? parseInt(value, 10) : value),
|
1562
|
+
|
1563
|
+
// the next value's position in the lookup array
|
1564
|
+
next_value_position = current_value_position === -1 ? 0 : (increase ? (current_value_position + 1 >= lookup.length ? 0 : current_value_position + 1) : (current_value_position - 1 < 0 ? lookup.length - 1 : current_value_position - 1)),
|
1565
|
+
|
1566
|
+
default_date;
|
1567
|
+
|
1568
|
+
// increase/decrease the required value according to the values in the lookup array
|
1569
|
+
if (matches[1] === 'hour') selected_hour = lookup[next_value_position];
|
1570
|
+
else if (matches[1] === 'minute') selected_minute = lookup[next_value_position];
|
1571
|
+
else if (matches[1] === 'second') selected_second = lookup[next_value_position];
|
1572
|
+
else selected_ampm = lookup[next_value_position];
|
1573
|
+
|
1574
|
+
// if a default day is not available and the "start_date" property is set
|
1575
|
+
if (!default_day && plugin.settings.start_date) {
|
1576
|
+
|
1577
|
+
// check if "start_date" is valid according to the format
|
1578
|
+
default_date = check_date(plugin.settings.start_date);
|
1579
|
+
|
1580
|
+
// ...and if it is, extract the day from there
|
1581
|
+
if (default_date) default_day = default_date.getDate();
|
1582
|
+
|
1583
|
+
}
|
1584
|
+
|
1585
|
+
// if still no value, use the first selectable day
|
1586
|
+
if (!default_day) default_day = first_selectable_day;
|
1587
|
+
|
1588
|
+
// set the new value
|
1589
|
+
value_container.text(str_pad(lookup[next_value_position], 2).toUpperCase());
|
1590
|
+
|
1591
|
+
// update the value in the element
|
1592
|
+
select_date(selected_year, selected_month, default_day);
|
1593
|
+
|
1594
|
+
});
|
1595
|
+
|
1596
|
+
// if date picker is not always visible in a container
|
1597
|
+
if (!(plugin.settings.always_visible instanceof jQuery)) {
|
1598
|
+
|
1599
|
+
// whenever anything is clicked on the page
|
1600
|
+
$(document).on('mousedown.Zebra_DatePicker_' + uniqueid + ' touchstart.Zebra_DatePicker_' + uniqueid, function(e) {
|
1601
|
+
|
1602
|
+
// if
|
1603
|
+
if (
|
1604
|
+
|
1605
|
+
// date picker is visible
|
1606
|
+
!datepicker.hasClass('dp_hidden') &&
|
1607
|
+
(
|
1608
|
+
// date picker opens only on interacting with the icon, icon exists, but it is not the clicked element
|
1609
|
+
(plugin.settings.open_icon_only && plugin.icon && $(e.target).get(0) !== plugin.icon.get(0)) ||
|
1610
|
+
|
1611
|
+
// date picker doesn't open only on interacting with the icon but the clicked element it's not the icon nor the parent element
|
1612
|
+
(!plugin.settings.open_icon_only && $(e.target).get(0) !== $element.get(0) && (!plugin.icon || $(e.target).get(0) !== plugin.icon.get(0)))
|
1613
|
+
|
1614
|
+
) &&
|
1615
|
+
|
1616
|
+
// and the click is not inside the calendar
|
1617
|
+
$(e.target).parents().filter('.Zebra_DatePicker').length === 0
|
1618
|
+
|
1619
|
+
// hide the date picker
|
1620
|
+
) plugin.hide(true);
|
1621
|
+
|
1622
|
+
});
|
1623
|
+
|
1624
|
+
// whenever a key is pressed on the page
|
1625
|
+
$(document).on('keyup.Zebra_DatePicker_' + uniqueid, function(e) {
|
1626
|
+
|
1627
|
+
// if the date picker is visible
|
1628
|
+
// and the pressed key is ESC
|
1629
|
+
// hide the date picker
|
1630
|
+
if (!datepicker.hasClass('dp_hidden') && e.which === 27) plugin.hide();
|
1631
|
+
|
1632
|
+
});
|
1633
|
+
|
1634
|
+
}
|
1635
|
+
|
1636
|
+
// last thing is to pre-render some of the date picker right away
|
1637
|
+
manage_views();
|
1638
|
+
|
1639
|
+
};
|
1640
|
+
|
1641
|
+
/**
|
1642
|
+
* Clears the selected date.
|
1643
|
+
*
|
1644
|
+
* @return void
|
1645
|
+
*/
|
1646
|
+
plugin.clear_date = function() {
|
1647
|
+
|
1648
|
+
$(cleardate).trigger('click');
|
1649
|
+
|
1650
|
+
};
|
1651
|
+
|
1652
|
+
/**
|
1653
|
+
* Destroys the date picker.
|
1654
|
+
*
|
1655
|
+
* @return void
|
1656
|
+
*/
|
1657
|
+
plugin.destroy = function() {
|
1658
|
+
|
1659
|
+
// if the calendar icon exists
|
1660
|
+
if (undefined !== plugin.icon) {
|
1661
|
+
|
1662
|
+
// remove associated event handlers
|
1663
|
+
plugin.icon.off('click.Zebra_DatePicker_' + uniqueid);
|
1664
|
+
plugin.icon.off('focus.Zebra_DatePicker_' + uniqueid);
|
1665
|
+
plugin.icon.off('keydown.Zebra_DatePicker_' + uniqueid);
|
1666
|
+
|
1667
|
+
// remove the icon itself
|
1668
|
+
plugin.icon.remove();
|
1669
|
+
|
1670
|
+
}
|
1671
|
+
|
1672
|
+
// remove all events attached to the datepicker
|
1673
|
+
// (these are the ones for increasing/decreasing values in the time picker)
|
1674
|
+
datepicker.off();
|
1675
|
+
|
1676
|
+
// remove the calendar
|
1677
|
+
datepicker.remove();
|
1678
|
+
|
1679
|
+
// if calendar icon was shown and the date picker was not always visible in a container,
|
1680
|
+
// also remove the wrapper used for positioning it
|
1681
|
+
if (plugin.settings.show_icon && !(plugin.settings.always_visible instanceof jQuery)) $element.unwrap();
|
1682
|
+
|
1683
|
+
// remove associated event handlers from the element
|
1684
|
+
$element.off('blur.Zebra_DatePicker_' + uniqueid);
|
1685
|
+
$element.off('click.Zebra_DatePicker_' + uniqueid);
|
1686
|
+
$element.off('focus.Zebra_DatePicker_' + uniqueid);
|
1687
|
+
$element.off('keydown.Zebra_DatePicker_' + uniqueid);
|
1688
|
+
$element.off('mousedown.Zebra_DatePicker_' + uniqueid);
|
1689
|
+
|
1690
|
+
// remove associated event handlers from the document
|
1691
|
+
$(document).off('keyup.Zebra_DatePicker_' + uniqueid);
|
1692
|
+
$(document).off('mousedown.Zebra_DatePicker_' + uniqueid);
|
1693
|
+
$(document).off('touchstart.Zebra_DatePicker_' + uniqueid);
|
1694
|
+
$(window).off('resize.Zebra_DatePicker_' + uniqueid);
|
1695
|
+
$(window).off('orientationchange.Zebra_DatePicker_' + uniqueid);
|
1696
|
+
|
1697
|
+
// remove association with the element
|
1698
|
+
$element.removeData('Zebra_DatePicker');
|
1699
|
+
|
1700
|
+
// restore element's modified attributes
|
1701
|
+
$element.attr('readonly', original_attributes['readonly']);
|
1702
|
+
$element.attr('style', original_attributes['style'] ? original_attributes['style'] : '');
|
1703
|
+
|
1704
|
+
};
|
1705
|
+
|
1706
|
+
/**
|
1707
|
+
* Hides the date picker.
|
1708
|
+
*
|
1709
|
+
* @return void
|
1710
|
+
*/
|
1711
|
+
plugin.hide = function(outside) {
|
1712
|
+
|
1713
|
+
// if date picker is not always visible or we clicked outside the date picker
|
1714
|
+
// (the "outside" argument is TRUE when clicking outside the date picker and the "always_visible" is set to boolean TRUE)
|
1715
|
+
if (!plugin.settings.always_visible || outside) {
|
1716
|
+
|
1717
|
+
// hide the iFrameShim in Internet Explorer 6
|
1718
|
+
iframeShim('hide');
|
1719
|
+
|
1720
|
+
// hide the date picker
|
1721
|
+
datepicker.addClass('dp_hidden');
|
1722
|
+
|
1723
|
+
// if a callback function exists for when hiding the date picker
|
1724
|
+
if (plugin.settings.onClose && typeof plugin.settings.onClose === 'function')
|
1725
|
+
|
1726
|
+
// execute the callback function and pass as argument the element the plugin is attached to
|
1727
|
+
plugin.settings.onClose.call($element, $element);
|
1728
|
+
|
1729
|
+
}
|
1730
|
+
|
1731
|
+
};
|
1732
|
+
|
1733
|
+
/**
|
1734
|
+
* Set the date picker's value
|
1735
|
+
*
|
1736
|
+
* Must be in the format set by the "format" property!
|
1737
|
+
*
|
1738
|
+
* @return void
|
1739
|
+
*/
|
1740
|
+
plugin.set_date = function(date) {
|
1741
|
+
|
1742
|
+
var dateObj;
|
1743
|
+
|
1744
|
+
// if a valid date was entered, and date is not disabled
|
1745
|
+
if ((dateObj = check_date(date)) && !is_disabled(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate())) {
|
1746
|
+
|
1747
|
+
// set the element's value
|
1748
|
+
$element.val(date);
|
1749
|
+
|
1750
|
+
// update the paired date picker (if any)
|
1751
|
+
update_dependent(dateObj);
|
1752
|
+
|
1753
|
+
}
|
1754
|
+
|
1755
|
+
};
|
1756
|
+
|
1757
|
+
/**
|
1758
|
+
* Shows the date picker.
|
1759
|
+
*
|
1760
|
+
* @return void
|
1761
|
+
*/
|
1762
|
+
plugin.show = function() {
|
1763
|
+
|
1764
|
+
// always show the view defined in settings
|
1765
|
+
view = plugin.settings.view;
|
1766
|
+
|
1767
|
+
// get the default date, from the element, and check if it represents a valid date, according to the required format
|
1768
|
+
var default_date = check_date($element.val() || (plugin.settings.start_date ? plugin.settings.start_date : '')),
|
1769
|
+
current_date;
|
1770
|
+
|
1771
|
+
// if the value represents a valid date
|
1772
|
+
if (default_date) {
|
1773
|
+
|
1774
|
+
// extract the date parts
|
1775
|
+
// we'll use these to highlight the default date in the date picker and as starting point to
|
1776
|
+
// what year and month to start the date picker with
|
1777
|
+
// why separate values? because selected_* will change as user navigates within the date picker
|
1778
|
+
default_month = default_date.getMonth();
|
1779
|
+
selected_month = default_date.getMonth();
|
1780
|
+
default_year = default_date.getFullYear();
|
1781
|
+
selected_year = default_date.getFullYear();
|
1782
|
+
default_day = default_date.getDate();
|
1783
|
+
|
1784
|
+
// if the default date represents a disabled date
|
1785
|
+
if (is_disabled(default_year, default_month, default_day)) {
|
1786
|
+
|
1787
|
+
// if date picker is in "strict" mode, clear the value of the parent element
|
1788
|
+
if (plugin.settings.strict) $element.val('');
|
1789
|
+
|
1790
|
+
// the calendar will start with the first selectable year/month
|
1791
|
+
selected_month = first_selectable_month;
|
1792
|
+
selected_year = first_selectable_year;
|
1793
|
+
|
1794
|
+
}
|
1795
|
+
|
1796
|
+
// if a default value is not available, or value does not represent a valid date
|
1797
|
+
} else {
|
1798
|
+
|
1799
|
+
// the calendar will start with the first selectable year/month
|
1800
|
+
selected_month = first_selectable_month;
|
1801
|
+
selected_year = first_selectable_year;
|
1802
|
+
|
1803
|
+
}
|
1804
|
+
|
1805
|
+
// whatever the case, if time picker is enabled
|
1806
|
+
if (timepicker_config) {
|
1807
|
+
|
1808
|
+
// if a default date is available, use the time from there
|
1809
|
+
if (default_date) current_date = default_date;
|
1810
|
+
|
1811
|
+
// use current system time otherwise
|
1812
|
+
else current_date = new Date();
|
1813
|
+
|
1814
|
+
// extract time parts from it
|
1815
|
+
selected_hour = current_date.getHours();
|
1816
|
+
selected_minute = current_date.getMinutes();
|
1817
|
+
selected_second = current_date.getSeconds();
|
1818
|
+
selected_ampm = (selected_hour >= 12 ? 'pm' : 'am');
|
1819
|
+
|
1820
|
+
// if hour is in 12 hour format
|
1821
|
+
if (timepicker_config.is12hour)
|
1822
|
+
|
1823
|
+
// convert it to the correct value
|
1824
|
+
selected_hour = (selected_hour % 12 === 0 ? 12 : selected_hour % 12);
|
1825
|
+
|
1826
|
+
// make sure that the default values are withing the allowed range, if a range is defined
|
1827
|
+
if ($.isArray(plugin.settings.enabled_hours) && $.inArray(selected_hour, plugin.settings.enabled_hours) === -1) selected_hour = plugin.settings.enabled_hours[0];
|
1828
|
+
if ($.isArray(plugin.settings.enabled_minutes) && $.inArray(selected_minute, plugin.settings.enabled_minutes) === -1) selected_minute = plugin.settings.enabled_minutes[0];
|
1829
|
+
if ($.isArray(plugin.settings.enabled_seconds) && $.inArray(selected_second, plugin.settings.enabled_seconds) === -1) selected_second = plugin.settings.enabled_seconds[0];
|
1830
|
+
|
1831
|
+
}
|
1832
|
+
|
1833
|
+
// generate the appropriate view
|
1834
|
+
manage_views();
|
1835
|
+
|
1836
|
+
// if date picker is not always visible in a container, and the calendar icon is visible
|
1837
|
+
if (!(plugin.settings.always_visible instanceof jQuery)) {
|
1838
|
+
|
1839
|
+
// if date picker is to be injected into the <body>
|
1840
|
+
if (plugin.settings.container.is('body')) {
|
1841
|
+
|
1842
|
+
var
|
1843
|
+
|
1844
|
+
// get the date picker width and height
|
1845
|
+
datepicker_width = datepicker.outerWidth(),
|
1846
|
+
datepicker_height = datepicker.outerHeight(),
|
1847
|
+
|
1848
|
+
// compute the date picker's default left and top
|
1849
|
+
// this will be computed relative to the icon's top-right corner (if the calendar icon exists), or
|
1850
|
+
// relative to the element's top-right corner otherwise, to which the offsets given at initialization
|
1851
|
+
// are added/subtracted
|
1852
|
+
left = (undefined !== icon ? icon.offset().left + icon.outerWidth(true) : $element.offset().left + $element.outerWidth(true)) + plugin.settings.offset[0],
|
1853
|
+
top = (undefined !== icon ? icon.offset().top : $element.offset().top) - datepicker_height + plugin.settings.offset[1],
|
1854
|
+
|
1855
|
+
// get browser window's width and height
|
1856
|
+
window_width = $(window).width(),
|
1857
|
+
window_height = $(window).height(),
|
1858
|
+
|
1859
|
+
// get browser window's horizontal and vertical scroll offsets
|
1860
|
+
window_scroll_top = $(window).scrollTop(),
|
1861
|
+
window_scroll_left = $(window).scrollLeft();
|
1862
|
+
|
1863
|
+
if (plugin.settings.default_position === 'below')
|
1864
|
+
top = (undefined !== icon ? icon.offset().top : $element.offset().top) + plugin.settings.offset[1];
|
1865
|
+
|
1866
|
+
// if date picker is outside the viewport, adjust its position so that it is visible
|
1867
|
+
if (left + datepicker_width > window_scroll_left + window_width) left = window_scroll_left + window_width - datepicker_width;
|
1868
|
+
if (left < window_scroll_left) left = window_scroll_left;
|
1869
|
+
|
1870
|
+
if (top + datepicker_height > window_scroll_top + window_height) top = window_scroll_top + window_height - datepicker_height;
|
1871
|
+
if (top < window_scroll_top) top = window_scroll_top;
|
1872
|
+
|
1873
|
+
// make the date picker visible
|
1874
|
+
datepicker.css({
|
1875
|
+
left: left,
|
1876
|
+
top: top
|
1877
|
+
});
|
1878
|
+
|
1879
|
+
// if date picker is to be injected into a custom container element
|
1880
|
+
} else
|
1881
|
+
|
1882
|
+
datepicker.css({
|
1883
|
+
left: 0,
|
1884
|
+
top: 0
|
1885
|
+
});
|
1886
|
+
|
1887
|
+
// fade-in the date picker
|
1888
|
+
// for Internet Explorer < 9 show the date picker instantly or fading alters the font's weight
|
1889
|
+
datepicker.removeClass('dp_hidden');
|
1890
|
+
|
1891
|
+
// show the iFrameShim in Internet Explorer 6
|
1892
|
+
iframeShim();
|
1893
|
+
|
1894
|
+
// if date picker is always visible, show it
|
1895
|
+
} else datepicker.removeClass('dp_hidden');
|
1896
|
+
|
1897
|
+
// if a callback function exists for when showing the date picker
|
1898
|
+
if (plugin.settings.onOpen && typeof plugin.settings.onOpen === 'function')
|
1899
|
+
|
1900
|
+
// execute the callback function and pass as argument the element the plugin is attached to
|
1901
|
+
plugin.settings.onOpen.call($element, $element);
|
1902
|
+
|
1903
|
+
};
|
1904
|
+
|
1905
|
+
/**
|
1906
|
+
* Updates the configuration options given as argument
|
1907
|
+
*
|
1908
|
+
* @param object values An object containing any number of configuration options to be updated
|
1909
|
+
*
|
1910
|
+
* @return void
|
1911
|
+
*/
|
1912
|
+
plugin.update = function(values) {
|
1913
|
+
|
1914
|
+
// if original direction not saved, save it now
|
1915
|
+
if (plugin.original_direction) plugin.original_direction = plugin.direction;
|
1916
|
+
|
1917
|
+
// update configuration options
|
1918
|
+
plugin.settings = $.extend(plugin.settings, values);
|
1919
|
+
|
1920
|
+
// reinitialize the object with the new options
|
1921
|
+
init(true);
|
1922
|
+
|
1923
|
+
};
|
1924
|
+
|
1925
|
+
/**
|
1926
|
+
* Checks if a string represents a valid date according to the format defined by the "format" property.
|
1927
|
+
*
|
1928
|
+
* @param string str_date A string representing a date, formatted accordingly to the "format" property.
|
1929
|
+
* For example, if "format" is "Y-m-d" the string should look like "2011-06-01"
|
1930
|
+
*
|
1931
|
+
* @return mixed Returns a JavaScript Date object if string represents a valid date according
|
1932
|
+
* formatted according to the "format" property, or FALSE otherwise.
|
1933
|
+
*
|
1934
|
+
* @access private
|
1935
|
+
*/
|
1936
|
+
var check_date = function(str_date) {
|
1937
|
+
|
1938
|
+
// treat argument as a string
|
1939
|
+
str_date += '';
|
1940
|
+
|
1941
|
+
// if value is given
|
1942
|
+
if ($.trim(str_date) !== '') {
|
1943
|
+
|
1944
|
+
var
|
1945
|
+
|
1946
|
+
// prepare the format by removing white space from it
|
1947
|
+
// and also escape characters that could have special meaning in a regular expression
|
1948
|
+
format = escape_regexp(plugin.settings.format),
|
1949
|
+
|
1950
|
+
// allowed characters in date's format
|
1951
|
+
format_chars = ['d', 'D', 'j', 'l', 'N', 'S', 'w', 'F', 'm', 'M', 'n', 'Y', 'y', 'G', 'g', 'H', 'h', 'i', 's', 'a', 'A'],
|
1952
|
+
|
1953
|
+
// "matches" will contain the characters defining the date's format
|
1954
|
+
matches = [],
|
1955
|
+
|
1956
|
+
// "regexp" will contain the regular expression built for each of the characters used in the date's format
|
1957
|
+
regexp = [],
|
1958
|
+
|
1959
|
+
// "position" will contain the position of the character found in the date's format
|
1960
|
+
position = null,
|
1961
|
+
|
1962
|
+
// "segments" will contain the matches of the regular expression
|
1963
|
+
segments = null;
|
1964
|
+
|
1965
|
+
// iterate through the allowed characters in date's format
|
1966
|
+
for (var i = 0; i < format_chars.length; i++)
|
1967
|
+
|
1968
|
+
// if character is found in the date's format
|
1969
|
+
if ((position = format.indexOf(format_chars[i])) > -1)
|
1970
|
+
|
1971
|
+
// save it, alongside the character's position
|
1972
|
+
matches.push({
|
1973
|
+
character: format_chars[i],
|
1974
|
+
position: position
|
1975
|
+
});
|
1976
|
+
|
1977
|
+
// sort characters defining the date's format based on their position, ascending
|
1978
|
+
matches.sort(function(a, b) { return a.position - b.position; });
|
1979
|
+
|
1980
|
+
// iterate through the characters defining the date's format
|
1981
|
+
$.each(matches, function(index, match) {
|
1982
|
+
|
1983
|
+
// add to the array of regular expressions, based on the character
|
1984
|
+
switch (match.character) {
|
1985
|
+
|
1986
|
+
case 'd': regexp.push('0[1-9]|[12][0-9]|3[01]'); break;
|
1987
|
+
case 'D': regexp.push('[a-z]{3}'); break;
|
1988
|
+
case 'j': regexp.push('[1-9]|[12][0-9]|3[01]'); break;
|
1989
|
+
case 'l': regexp.push('[a-z]+'); break;
|
1990
|
+
case 'N': regexp.push('[1-7]'); break;
|
1991
|
+
case 'S': regexp.push('st|nd|rd|th'); break;
|
1992
|
+
case 'w': regexp.push('[0-6]'); break;
|
1993
|
+
case 'F': regexp.push('[a-z]+'); break;
|
1994
|
+
case 'm': regexp.push('0[1-9]|1[012]'); break;
|
1995
|
+
case 'M': regexp.push('[a-z]{3}'); break;
|
1996
|
+
case 'n': regexp.push('[1-9]|1[012]'); break;
|
1997
|
+
case 'Y': regexp.push('[0-9]{4}'); break;
|
1998
|
+
case 'y': regexp.push('[0-9]{2}'); break;
|
1999
|
+
case 'G': regexp.push('[1-9]|1[0-9]|2[0123]'); break;
|
2000
|
+
case 'g': regexp.push('[0-9]|1[012]'); break;
|
2001
|
+
case 'H': regexp.push('0[0-9]|1[0-9]|2[0123]'); break;
|
2002
|
+
case 'h': regexp.push('0[0-9]|1[012]'); break;
|
2003
|
+
case 'i': regexp.push('0[0-9]|[12345][0-9]'); break;
|
2004
|
+
case 's': regexp.push('0[0-9]|[12345][0-9]'); break;
|
2005
|
+
case 'a': regexp.push('am|pm'); break;
|
2006
|
+
case 'A': regexp.push('AM|PM'); break;
|
2007
|
+
|
2008
|
+
}
|
2009
|
+
|
2010
|
+
});
|
2011
|
+
|
2012
|
+
// if we have an array of regular expressions
|
2013
|
+
if (regexp.length) {
|
2014
|
+
|
2015
|
+
// we will replace characters in the date's format in reversed order
|
2016
|
+
matches.reverse();
|
2017
|
+
|
2018
|
+
// iterate through the characters in date's format
|
2019
|
+
$.each(matches, function(index, match) {
|
2020
|
+
|
2021
|
+
// replace each character with the appropriate regular expression
|
2022
|
+
format = format.replace(match.character, '(' + regexp[regexp.length - index - 1] + ')');
|
2023
|
+
|
2024
|
+
});
|
2025
|
+
|
2026
|
+
// the final regular expression
|
2027
|
+
regexp = new RegExp('^' + format + '$', 'ig');
|
2028
|
+
|
2029
|
+
// if regular expression was matched
|
2030
|
+
if ((segments = regexp.exec(str_date))) {
|
2031
|
+
|
2032
|
+
// check if date is a valid date (i.e. there's no February 31)
|
2033
|
+
|
2034
|
+
var tmpdate = new Date(),
|
2035
|
+
original_day = 1,
|
2036
|
+
original_month = tmpdate.getMonth() + 1,
|
2037
|
+
original_year = tmpdate.getFullYear(),
|
2038
|
+
original_hours = tmpdate.getHours(),
|
2039
|
+
original_minutes = tmpdate.getMinutes(),
|
2040
|
+
original_seconds = tmpdate.getSeconds(),
|
2041
|
+
original_ampm,
|
2042
|
+
english_days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
2043
|
+
english_months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
2044
|
+
iterable,
|
2045
|
+
|
2046
|
+
// by default, we assume the date is valid
|
2047
|
+
valid = true;
|
2048
|
+
|
2049
|
+
// reverse back the characters in the date's format
|
2050
|
+
matches.reverse();
|
2051
|
+
|
2052
|
+
// iterate through the characters in the date's format
|
2053
|
+
$.each(matches, function(index, match) {
|
2054
|
+
|
2055
|
+
// if the date is not valid, don't look further
|
2056
|
+
if (!valid) return true;
|
2057
|
+
|
2058
|
+
// based on the character
|
2059
|
+
switch (match.character) {
|
2060
|
+
|
2061
|
+
case 'm':
|
2062
|
+
case 'n':
|
2063
|
+
|
2064
|
+
// extract the month from the value entered by the user
|
2065
|
+
original_month = to_int(segments[index + 1]);
|
2066
|
+
|
2067
|
+
break;
|
2068
|
+
|
2069
|
+
case 'd':
|
2070
|
+
case 'j':
|
2071
|
+
|
2072
|
+
// extract the day from the value entered by the user
|
2073
|
+
original_day = to_int(segments[index + 1]);
|
2074
|
+
|
2075
|
+
break;
|
2076
|
+
|
2077
|
+
case 'D':
|
2078
|
+
case 'l':
|
2079
|
+
case 'F':
|
2080
|
+
case 'M':
|
2081
|
+
|
2082
|
+
// if day is given as day name, we'll check against the names in the used language
|
2083
|
+
if (match.character === 'D' || match.character === 'l') iterable = plugin.settings.days;
|
2084
|
+
|
2085
|
+
// if month is given as month name, we'll check against the names in the used language
|
2086
|
+
else iterable = plugin.settings.months;
|
2087
|
+
|
2088
|
+
// by default, we assume the day or month was not entered correctly
|
2089
|
+
valid = false;
|
2090
|
+
|
2091
|
+
// iterate through the month/days in the used language
|
2092
|
+
$.each(iterable, function(key, value) {
|
2093
|
+
|
2094
|
+
// if month/day was entered correctly, don't look further
|
2095
|
+
if (valid) return true;
|
2096
|
+
|
2097
|
+
// if month/day was entered correctly
|
2098
|
+
if (segments[index + 1].toLowerCase() === value.substring(0, (match.character === 'D' || match.character === 'M' ? 3 : value.length)).toLowerCase()) {
|
2099
|
+
|
2100
|
+
// extract the day/month from the value entered by the user
|
2101
|
+
switch (match.character) {
|
2102
|
+
|
2103
|
+
case 'D': segments[index + 1] = english_days[key].substring(0, 3); break;
|
2104
|
+
case 'l': segments[index + 1] = english_days[key]; break;
|
2105
|
+
case 'F': segments[index + 1] = english_months[key]; original_month = key + 1; break;
|
2106
|
+
case 'M': segments[index + 1] = english_months[key].substring(0, 3); original_month = key + 1; break;
|
2107
|
+
|
2108
|
+
}
|
2109
|
+
|
2110
|
+
// day/month value is valid
|
2111
|
+
valid = true;
|
2112
|
+
|
2113
|
+
}
|
2114
|
+
|
2115
|
+
});
|
2116
|
+
|
2117
|
+
break;
|
2118
|
+
|
2119
|
+
case 'Y':
|
2120
|
+
|
2121
|
+
// extract the year from the value entered by the user
|
2122
|
+
original_year = to_int(segments[index + 1]);
|
2123
|
+
|
2124
|
+
break;
|
2125
|
+
|
2126
|
+
case 'y':
|
2127
|
+
|
2128
|
+
// extract the year from the value entered by the user
|
2129
|
+
original_year = '19' + to_int(segments[index + 1]);
|
2130
|
+
|
2131
|
+
break;
|
2132
|
+
|
2133
|
+
case 'G':
|
2134
|
+
case 'H':
|
2135
|
+
case 'g':
|
2136
|
+
case 'h':
|
2137
|
+
|
2138
|
+
// extract the hours from the value entered by the user
|
2139
|
+
original_hours = to_int(segments[index + 1]);
|
2140
|
+
break;
|
2141
|
+
|
2142
|
+
case 'i':
|
2143
|
+
|
2144
|
+
// extract the minutes from the value entered by the user
|
2145
|
+
original_minutes = to_int(segments[index + 1]);
|
2146
|
+
break;
|
2147
|
+
|
2148
|
+
case 's':
|
2149
|
+
|
2150
|
+
// extract the seconds from the value entered by the user
|
2151
|
+
original_seconds = to_int(segments[index + 1]);
|
2152
|
+
break;
|
2153
|
+
|
2154
|
+
case 'a':
|
2155
|
+
case 'A':
|
2156
|
+
|
2157
|
+
// extract the seconds from the value entered by the user
|
2158
|
+
original_ampm = segments[index + 1].toLowerCase();
|
2159
|
+
break;
|
2160
|
+
|
2161
|
+
}
|
2162
|
+
|
2163
|
+
});
|
2164
|
+
|
2165
|
+
// if everything is ok so far
|
2166
|
+
if (valid) {
|
2167
|
+
|
2168
|
+
// generate a Date object using the values entered by the user
|
2169
|
+
// (handle also the case when original_month and/or original_day are undefined - i.e date format is "Y-m" or "Y")
|
2170
|
+
var date = new Date(original_year, (original_month || 1) - 1, original_day || 1, original_hours + (original_ampm === 'pm' ? 12 : 0), original_minutes, original_seconds);
|
2171
|
+
|
2172
|
+
// if, after that, the date is the same as the date entered by the user
|
2173
|
+
if (date.getFullYear() === original_year && date.getDate() === (original_day || 1) && date.getMonth() === ((original_month || 1) - 1))
|
2174
|
+
|
2175
|
+
// return the date as JavaScript date object
|
2176
|
+
return date;
|
2177
|
+
|
2178
|
+
}
|
2179
|
+
|
2180
|
+
}
|
2181
|
+
|
2182
|
+
}
|
2183
|
+
|
2184
|
+
// if script gets this far, return false as something must've went wrong
|
2185
|
+
return false;
|
2186
|
+
|
2187
|
+
}
|
2188
|
+
|
2189
|
+
};
|
2190
|
+
|
2191
|
+
/**
|
2192
|
+
* Prevents the possibility of selecting text on a given element. Used on the "previous" and "next" buttons
|
2193
|
+
* where text might get accidentally selected when user quickly clicks on the buttons.
|
2194
|
+
*
|
2195
|
+
* Code by http://chris-barr.com/index.php/entry/disable_text_selection_with_jquery/
|
2196
|
+
*
|
2197
|
+
* @param jQuery Element el A jQuery element on which to prevents text selection.
|
2198
|
+
*
|
2199
|
+
* @return void
|
2200
|
+
*
|
2201
|
+
* @access private
|
2202
|
+
*/
|
2203
|
+
var disable_text_select = function(el) {
|
2204
|
+
|
2205
|
+
// if browser is Firefox
|
2206
|
+
if (browser.name === 'firefox') el.css('MozUserSelect', 'none');
|
2207
|
+
|
2208
|
+
// if browser is Internet Explorer
|
2209
|
+
else if (browser.name === 'explorer') $(document).on('selectstart', el, function() { return false; });
|
2210
|
+
|
2211
|
+
// for the other browsers
|
2212
|
+
else el.mousedown(function() { return false; });
|
2213
|
+
|
2214
|
+
};
|
2215
|
+
|
2216
|
+
/**
|
2217
|
+
* Escapes special characters in a string, preparing it for use in a regular expression.
|
2218
|
+
*
|
2219
|
+
* @param string str The string in which special characters should be escaped.
|
2220
|
+
*
|
2221
|
+
* @return string Returns the string with escaped special characters.
|
2222
|
+
*
|
2223
|
+
* @access private
|
2224
|
+
*/
|
2225
|
+
var escape_regexp = function(str) {
|
2226
|
+
|
2227
|
+
// return string with special characters escaped
|
2228
|
+
return str.replace(/([-.,*+?^${}()|[\]\/\\])/g, '\\$1');
|
2229
|
+
|
2230
|
+
};
|
2231
|
+
|
2232
|
+
/**
|
2233
|
+
* Formats a JavaScript date object to the format specified by the "format" property.
|
2234
|
+
* Code taken from http://electricprism.com/aeron/calendar/
|
2235
|
+
*
|
2236
|
+
* @param date date A valid JavaScript date object
|
2237
|
+
*
|
2238
|
+
* @return string Returns a string containing the formatted date
|
2239
|
+
*
|
2240
|
+
* @access private
|
2241
|
+
*/
|
2242
|
+
var format = function(date) {
|
2243
|
+
|
2244
|
+
var result = '',
|
2245
|
+
|
2246
|
+
// extract parts of the date:
|
2247
|
+
// day number, 1 - 31
|
2248
|
+
j = date.getDate(),
|
2249
|
+
|
2250
|
+
// day of the week, 0 - 6, Sunday - Saturday
|
2251
|
+
w = date.getDay(),
|
2252
|
+
|
2253
|
+
// the name of the day of the week Sunday - Saturday
|
2254
|
+
l = plugin.settings.days[w],
|
2255
|
+
|
2256
|
+
// the month number, 1 - 12
|
2257
|
+
n = date.getMonth() + 1,
|
2258
|
+
|
2259
|
+
// the month name, January - December
|
2260
|
+
f = plugin.settings.months[n - 1],
|
2261
|
+
|
2262
|
+
// the year (as a string)
|
2263
|
+
y = date.getFullYear() + '',
|
2264
|
+
|
2265
|
+
// the hour, 0-23
|
2266
|
+
h = date.getHours(),
|
2267
|
+
|
2268
|
+
// the hour in 12 hours format
|
2269
|
+
h12 = h % 12 === 0 ? 12 : h % 12,
|
2270
|
+
|
2271
|
+
// the minute, 0-59
|
2272
|
+
m = date.getMinutes(),
|
2273
|
+
|
2274
|
+
// the second, 0-59
|
2275
|
+
s = date.getSeconds(),
|
2276
|
+
|
2277
|
+
// am/pm
|
2278
|
+
a = (h >= 12 ? 'pm' : 'am'),
|
2279
|
+
|
2280
|
+
i, chr;
|
2281
|
+
|
2282
|
+
// iterate through the characters in the format
|
2283
|
+
for (i = 0; i < plugin.settings.format.length; i++) {
|
2284
|
+
|
2285
|
+
// extract the current character
|
2286
|
+
chr = plugin.settings.format.charAt(i);
|
2287
|
+
|
2288
|
+
// see what character it is
|
2289
|
+
switch (chr) {
|
2290
|
+
|
2291
|
+
// year as two digits
|
2292
|
+
case 'y': y = y.substr(2);
|
2293
|
+
|
2294
|
+
// year as four digits
|
2295
|
+
// falls through
|
2296
|
+
case 'Y': result += y; break;
|
2297
|
+
|
2298
|
+
// month number, prefixed with 0
|
2299
|
+
case 'm': n = str_pad(n, 2);
|
2300
|
+
|
2301
|
+
// month number, not prefixed with 0
|
2302
|
+
// falls through
|
2303
|
+
case 'n': result += n; break;
|
2304
|
+
|
2305
|
+
// month name, three letters
|
2306
|
+
case 'M': f = ($.isArray(plugin.settings.months_abbr) && undefined !== plugin.settings.months_abbr[n - 1] ? plugin.settings.months_abbr[n - 1] : plugin.settings.months[n - 1].substr(0, 3));
|
2307
|
+
|
2308
|
+
// full month name
|
2309
|
+
// falls through
|
2310
|
+
case 'F': result += f; break;
|
2311
|
+
|
2312
|
+
// day number, prefixed with 0
|
2313
|
+
case 'd': j = str_pad(j, 2);
|
2314
|
+
|
2315
|
+
// day number not prefixed with 0
|
2316
|
+
// falls through
|
2317
|
+
case 'j': result += j; break;
|
2318
|
+
|
2319
|
+
// day name, three letters
|
2320
|
+
case 'D': l = ($.isArray(plugin.settings.days_abbr) && undefined !== plugin.settings.days_abbr[w] ? plugin.settings.days_abbr[w] : plugin.settings.days[w].substr(0, 3));
|
2321
|
+
|
2322
|
+
// full day name
|
2323
|
+
// falls through
|
2324
|
+
case 'l': result += l; break;
|
2325
|
+
|
2326
|
+
// ISO-8601 numeric representation of the day of the week, 1 - 7
|
2327
|
+
case 'N': w++;
|
2328
|
+
|
2329
|
+
// day of the week, 0 - 6
|
2330
|
+
// falls through
|
2331
|
+
case 'w': result += w; break;
|
2332
|
+
|
2333
|
+
// English ordinal suffix for the day of the month, 2 characters
|
2334
|
+
// (st, nd, rd or th (works well with j))
|
2335
|
+
case 'S':
|
2336
|
+
|
2337
|
+
if (j % 10 === 1 && j !== '11') result += 'st';
|
2338
|
+
|
2339
|
+
else if (j % 10 === 2 && j !== '12') result += 'nd';
|
2340
|
+
|
2341
|
+
else if (j % 10 === 3 && j !== '13') result += 'rd';
|
2342
|
+
|
2343
|
+
else result += 'th';
|
2344
|
+
|
2345
|
+
break;
|
2346
|
+
|
2347
|
+
// hour in 12 hours format, without leading zeros
|
2348
|
+
case 'g': result += h12; break;
|
2349
|
+
|
2350
|
+
// hour in 12 hours format, with leading zeros
|
2351
|
+
case 'h': result += str_pad(h12, 2); break;
|
2352
|
+
|
2353
|
+
// hour in 24 hours format, without leading zeros
|
2354
|
+
case 'G': result += h; break;
|
2355
|
+
|
2356
|
+
// hour in 24 hours format, with leading zeros
|
2357
|
+
case 'H': result += str_pad(h, 2); break;
|
2358
|
+
|
2359
|
+
// minutes, with leading zeros
|
2360
|
+
case 'i': result += str_pad(m, 2); break;
|
2361
|
+
|
2362
|
+
// seconds, with leading zeros
|
2363
|
+
case 's': result += str_pad(s, 2); break;
|
2364
|
+
|
2365
|
+
// am/pm, lowercase
|
2366
|
+
case 'a': result += a; break;
|
2367
|
+
|
2368
|
+
// am/pm, uppercase
|
2369
|
+
case 'A': result += a.toUpperCase(); break;
|
2370
|
+
|
2371
|
+
// this is probably the separator
|
2372
|
+
default: result += chr;
|
2373
|
+
|
2374
|
+
}
|
2375
|
+
|
2376
|
+
}
|
2377
|
+
|
2378
|
+
// return formated date
|
2379
|
+
return result;
|
2380
|
+
|
2381
|
+
};
|
2382
|
+
|
2383
|
+
/**
|
2384
|
+
* Generates the day picker view, and displays it
|
2385
|
+
*
|
2386
|
+
* @return void
|
2387
|
+
*
|
2388
|
+
* @access private
|
2389
|
+
*/
|
2390
|
+
var generate_daypicker = function() {
|
2391
|
+
|
2392
|
+
var
|
2393
|
+
|
2394
|
+
// get the number of days in the selected month
|
2395
|
+
days_in_month = new Date(selected_year, selected_month + 1, 0).getDate(),
|
2396
|
+
|
2397
|
+
// get the selected month's starting day (from 0 to 6)
|
2398
|
+
first_day = new Date(selected_year, selected_month, 1).getDay(),
|
2399
|
+
|
2400
|
+
// how many days are there in the previous month
|
2401
|
+
days_in_previous_month = new Date(selected_year, selected_month, 0).getDate(),
|
2402
|
+
|
2403
|
+
// how many days are there to be shown from the previous month
|
2404
|
+
days_from_previous_month = first_day - plugin.settings.first_day_of_week,
|
2405
|
+
|
2406
|
+
i, html, day, real_date, real_year, real_month, real_day, weekday, class_name, custom_class_name, is_weekend;
|
2407
|
+
|
2408
|
+
// the final value of how many days are there to be shown from the previous month
|
2409
|
+
days_from_previous_month = days_from_previous_month < 0 ? 7 + days_from_previous_month : days_from_previous_month;
|
2410
|
+
|
2411
|
+
// manage header caption and enable/disable navigation buttons if necessary
|
2412
|
+
manage_header(plugin.settings.header_captions['days']);
|
2413
|
+
|
2414
|
+
// start generating the HTML
|
2415
|
+
html = '<tr>';
|
2416
|
+
|
2417
|
+
// if a column featuring the number of the week is to be shown
|
2418
|
+
if (plugin.settings.show_week_number)
|
2419
|
+
|
2420
|
+
// column title
|
2421
|
+
html += '<th>' + plugin.settings.show_week_number + '</th>';
|
2422
|
+
|
2423
|
+
// name of week days
|
2424
|
+
// show the abbreviated day names (or only the first two letters of the full name if no abbreviations are specified)
|
2425
|
+
// and also, take in account the value of the "first_day_of_week" property
|
2426
|
+
for (i = 0; i < 7; i++)
|
2427
|
+
|
2428
|
+
html += '<th>' + ($.isArray(plugin.settings.days_abbr) && undefined !== plugin.settings.days_abbr[(plugin.settings.first_day_of_week + i) % 7] ? plugin.settings.days_abbr[(plugin.settings.first_day_of_week + i) % 7] : plugin.settings.days[(plugin.settings.first_day_of_week + i) % 7].substr(0, 2)) + '</th>';
|
2429
|
+
|
2430
|
+
html += '</tr><tr>';
|
2431
|
+
|
2432
|
+
// the calendar shows a total of 42 days
|
2433
|
+
for (i = 0; i < 42; i++) {
|
2434
|
+
|
2435
|
+
// seven days per row
|
2436
|
+
if (i > 0 && i % 7 === 0) html += '</tr><tr>';
|
2437
|
+
|
2438
|
+
// if week number is to be shown
|
2439
|
+
if (i % 7 === 0 && plugin.settings.show_week_number)
|
2440
|
+
|
2441
|
+
// show ISO 8601 week number
|
2442
|
+
html += '<th>' + getWeekNumber(new Date(selected_year, selected_month, (i - days_from_previous_month + 1))) + '</th>';
|
2443
|
+
|
2444
|
+
// the number of the day in month
|
2445
|
+
day = (i - days_from_previous_month + 1);
|
2446
|
+
|
2447
|
+
// if dates in previous/next month can be selected, and this is one of those days
|
2448
|
+
if (plugin.settings.select_other_months && (i < days_from_previous_month || day > days_in_month)) {
|
2449
|
+
|
2450
|
+
// use the Date object to normalize the date
|
2451
|
+
// for example, 2011 05 33 will be transformed to 2011 06 02
|
2452
|
+
real_date = new Date(selected_year, selected_month, day);
|
2453
|
+
real_year = real_date.getFullYear();
|
2454
|
+
real_month = real_date.getMonth();
|
2455
|
+
real_day = real_date.getDate();
|
2456
|
+
|
2457
|
+
// extract normalized date parts and merge them
|
2458
|
+
real_date = real_year + str_pad(real_month + 1, 2) + str_pad(real_day, 2);
|
2459
|
+
|
2460
|
+
}
|
2461
|
+
|
2462
|
+
// get the week day (0 to 6, Sunday to Saturday)
|
2463
|
+
weekday = (plugin.settings.first_day_of_week + i) % 7;
|
2464
|
+
|
2465
|
+
// is day on a weekend?
|
2466
|
+
is_weekend = ($.inArray(weekday, plugin.settings.weekend_days) > -1);
|
2467
|
+
|
2468
|
+
// if this is a day from the previous month
|
2469
|
+
if (i < days_from_previous_month)
|
2470
|
+
|
2471
|
+
html += '<td class="dp_not_in_month ' + (is_weekend ? 'dp_weekend ' : '') + (plugin.settings.select_other_months && !is_disabled(real_year, real_month, real_day) ? 'date_' + real_date : 'dp_disabled') + '">' + (plugin.settings.select_other_months || plugin.settings.show_other_months ? str_pad(days_in_previous_month - days_from_previous_month + i + 1, plugin.settings.zero_pad ? 2 : 0) : ' ') + '</td>';
|
2472
|
+
|
2473
|
+
// if this is a day from the next month
|
2474
|
+
else if (day > days_in_month)
|
2475
|
+
|
2476
|
+
html += '<td class="dp_not_in_month ' + (is_weekend ? 'dp_weekend ' : '') + (plugin.settings.select_other_months && !is_disabled(real_year, real_month, real_day) ? 'date_' + real_date : 'dp_disabled') + '">' + (plugin.settings.select_other_months || plugin.settings.show_other_months ? str_pad(day - days_in_month, plugin.settings.zero_pad ? 2 : 0) : ' ') + '</td>';
|
2477
|
+
|
2478
|
+
// if this is a day from the current month
|
2479
|
+
else {
|
2480
|
+
|
2481
|
+
class_name = '';
|
2482
|
+
|
2483
|
+
// custom class, if any
|
2484
|
+
custom_class_name = get_custom_class(selected_year, selected_month, day);
|
2485
|
+
|
2486
|
+
// if day is in weekend
|
2487
|
+
if (is_weekend) class_name = ' dp_weekend';
|
2488
|
+
|
2489
|
+
// highlight the current system date
|
2490
|
+
if (selected_month === current_system_month && selected_year === current_system_year && current_system_day === day) class_name += ' dp_current';
|
2491
|
+
|
2492
|
+
// apply custom class, if a custom class exists
|
2493
|
+
if (custom_class_name !== '') class_name += ' ' + custom_class_name;
|
2494
|
+
|
2495
|
+
// highlight the currently selected date
|
2496
|
+
if (selected_month === default_month && selected_year === default_year && default_day === day) class_name += ' dp_selected';
|
2497
|
+
|
2498
|
+
// if date needs to be disabled
|
2499
|
+
if (is_disabled(selected_year, selected_month, day)) class_name += ' dp_disabled';
|
2500
|
+
|
2501
|
+
// print the day of the month (if "day" is NaN, use an empty string instead)
|
2502
|
+
html += '<td' + (class_name !== '' ? ' class="' + class_name.trim() + '"' : '') + '>' + ((plugin.settings.zero_pad ? str_pad(day, 2) : day) || ' ') + '</td>';
|
2503
|
+
|
2504
|
+
}
|
2505
|
+
|
2506
|
+
}
|
2507
|
+
|
2508
|
+
// wrap up generating the day picker
|
2509
|
+
html += '</tr>';
|
2510
|
+
|
2511
|
+
// inject the day picker into the DOM
|
2512
|
+
daypicker.html($(html));
|
2513
|
+
|
2514
|
+
// if date picker is always visible
|
2515
|
+
if (plugin.settings.always_visible)
|
2516
|
+
|
2517
|
+
// cache all the cells
|
2518
|
+
// (we need them so that we can easily remove the "dp_selected" class from all of them when user selects a date)
|
2519
|
+
daypicker_cells = $('td:not(.dp_disabled)', daypicker);
|
2520
|
+
|
2521
|
+
// make the day picker visible
|
2522
|
+
daypicker.show();
|
2523
|
+
|
2524
|
+
};
|
2525
|
+
|
2526
|
+
/**
|
2527
|
+
* Generates the month picker view, and displays it
|
2528
|
+
*
|
2529
|
+
* @return void
|
2530
|
+
*
|
2531
|
+
* @access private
|
2532
|
+
*/
|
2533
|
+
var generate_monthpicker = function() {
|
2534
|
+
|
2535
|
+
// manage header caption and enable/disable navigation buttons if necessary
|
2536
|
+
manage_header(plugin.settings.header_captions['months']);
|
2537
|
+
|
2538
|
+
// start generating the HTML
|
2539
|
+
var html = '<tr>', i, class_name;
|
2540
|
+
|
2541
|
+
// iterate through all the months
|
2542
|
+
for (i = 0; i < 12; i++) {
|
2543
|
+
|
2544
|
+
// three month per row
|
2545
|
+
if (i > 0 && i % 3 === 0) html += '</tr><tr>';
|
2546
|
+
|
2547
|
+
class_name = 'dp_month_' + i;
|
2548
|
+
|
2549
|
+
// if month needs to be disabled
|
2550
|
+
if (is_disabled(selected_year, i)) class_name += ' dp_disabled';
|
2551
|
+
|
2552
|
+
// else, if a date is already selected and this is that particular month, highlight it
|
2553
|
+
else if (default_month !== false && default_month === i && selected_year === default_year) class_name += ' dp_selected';
|
2554
|
+
|
2555
|
+
// else, if this the current system month, highlight it
|
2556
|
+
else if (current_system_month === i && current_system_year === selected_year) class_name += ' dp_current';
|
2557
|
+
|
2558
|
+
// first three letters of the month's name
|
2559
|
+
html += '<td class="' + $.trim(class_name) + '">' + ($.isArray(plugin.settings.months_abbr) && undefined !== plugin.settings.months_abbr[i] ? plugin.settings.months_abbr[i] : plugin.settings.months[i].substr(0, 3)) + '</td>';
|
2560
|
+
|
2561
|
+
}
|
2562
|
+
|
2563
|
+
// wrap up
|
2564
|
+
html += '</tr>';
|
2565
|
+
|
2566
|
+
// inject into the DOM
|
2567
|
+
monthpicker.html($(html));
|
2568
|
+
|
2569
|
+
// if date picker is always visible
|
2570
|
+
if (plugin.settings.always_visible)
|
2571
|
+
|
2572
|
+
// cache all the cells
|
2573
|
+
// (we need them so that we can easily remove the "dp_selected" class from all of them when user selects a month)
|
2574
|
+
monthpicker_cells = $('td:not(.dp_disabled)', monthpicker);
|
2575
|
+
|
2576
|
+
// make the month picker visible
|
2577
|
+
monthpicker.show();
|
2578
|
+
|
2579
|
+
};
|
2580
|
+
|
2581
|
+
/**
|
2582
|
+
* Generates the time picker view, and displays it
|
2583
|
+
*
|
2584
|
+
* @return void
|
2585
|
+
*
|
2586
|
+
* @access private
|
2587
|
+
*/
|
2588
|
+
var generate_timepicker = function() {
|
2589
|
+
|
2590
|
+
var html;
|
2591
|
+
|
2592
|
+
// the HTML
|
2593
|
+
html = '<tr class="dp_time_controls_increase">' +
|
2594
|
+
(timepicker_config.hours ? '<td class="dp_time_hour dp_time_control">' + plugin.settings.navigation[2] + '</td>' : '') +
|
2595
|
+
(timepicker_config.minutes ? '<td class="dp_time_minute dp_time_control">' + plugin.settings.navigation[2] + '</td>' : '') +
|
2596
|
+
(timepicker_config.seconds ? '<td class="dp_time_second dp_time_control">' + plugin.settings.navigation[2] + '</td>' : '') +
|
2597
|
+
(timepicker_config.ampm ? '<td class="dp_time_ampm dp_time_control">' + plugin.settings.navigation[2] + '</td>' : '') +
|
2598
|
+
'</tr>';
|
2599
|
+
|
2600
|
+
html += '<tr class="dp_time_segments">';
|
2601
|
+
|
2602
|
+
if (timepicker_config.hours) html += '<td class="dp_time_hours dp_disabled' + (timepicker_config.minutes || timepicker_config.seconds || timepicker_config.ampm ? ' dp_time_separator' : '') + '"><div>' + str_pad(selected_hour, 2) + '</div></td>';
|
2603
|
+
if (timepicker_config.minutes) html += '<td class="dp_time_minutes dp_disabled' + (timepicker_config.seconds || timepicker_config.ampm ? ' dp_time_separator' : '') + '"><div>' + str_pad(selected_minute, 2) + '</div></td>';
|
2604
|
+
if (timepicker_config.seconds) html += '<td class="dp_time_seconds dp_disabled' + (timepicker_config.ampm ? ' dp_time_separator' : '') + '"><div>' + str_pad(selected_second, 2) + '</div></td>';
|
2605
|
+
if (timepicker_config.ampm) html += '<td class="dp_time_ampm dp_disabled">' + selected_ampm.toUpperCase() + '</td>';
|
2606
|
+
|
2607
|
+
html += '</tr>';
|
2608
|
+
|
2609
|
+
html += '<tr class="dp_time_controls_decrease">' +
|
2610
|
+
(timepicker_config.hours ? '<td class="dp_time_hour dp_time_control">' + plugin.settings.navigation[3] + '</td>' : '') +
|
2611
|
+
(timepicker_config.minutes ? '<td class="dp_time_minute dp_time_control">' + plugin.settings.navigation[3] + '</td>' : '') +
|
2612
|
+
(timepicker_config.seconds ? '<td class="dp_time_second dp_time_control">' + plugin.settings.navigation[3] + '</td>' : '') +
|
2613
|
+
(timepicker_config.ampm ? '<td class="dp_time_ampm dp_time_control">' + plugin.settings.navigation[3] + '</td>' : '') +
|
2614
|
+
'</tr>';
|
2615
|
+
|
2616
|
+
// inject into the DOM
|
2617
|
+
timepicker.html($(html));
|
2618
|
+
|
2619
|
+
// make the time picker visible
|
2620
|
+
timepicker.show();
|
2621
|
+
|
2622
|
+
}
|
2623
|
+
|
2624
|
+
/**
|
2625
|
+
* Generates the year picker view, and displays it
|
2626
|
+
*
|
2627
|
+
* @return void
|
2628
|
+
*
|
2629
|
+
* @access private
|
2630
|
+
*/
|
2631
|
+
var generate_yearpicker = function() {
|
2632
|
+
|
2633
|
+
// manage header caption and enable/disable navigation buttons if necessary
|
2634
|
+
manage_header(plugin.settings.header_captions['years']);
|
2635
|
+
|
2636
|
+
// start generating the HTML
|
2637
|
+
var html = '<tr>', i, class_name;
|
2638
|
+
|
2639
|
+
// we're showing 9 years at a time, current year in the middle
|
2640
|
+
for (i = 0; i < 12; i++) {
|
2641
|
+
|
2642
|
+
// three years per row
|
2643
|
+
if (i > 0 && i % 3 === 0) html += '</tr><tr>';
|
2644
|
+
|
2645
|
+
class_name = '';
|
2646
|
+
|
2647
|
+
// if year needs to be disabled
|
2648
|
+
if (is_disabled(selected_year - 7 + i)) class_name += ' dp_disabled';
|
2649
|
+
|
2650
|
+
// else, if a date is already selected and this is that particular year, highlight it
|
2651
|
+
else if (default_year && default_year === selected_year - 7 + i) class_name += ' dp_selected';
|
2652
|
+
|
2653
|
+
// else, if this is the current system year, highlight it
|
2654
|
+
else if (current_system_year === (selected_year - 7 + i)) class_name += ' dp_current';
|
2655
|
+
|
2656
|
+
// first three letters of the month's name
|
2657
|
+
html += '<td' + ($.trim(class_name) !== '' ? ' class="' + $.trim(class_name) + '"' : '') + '>' + (selected_year - 7 + i) + '</td>';
|
2658
|
+
|
2659
|
+
}
|
2660
|
+
|
2661
|
+
// wrap up
|
2662
|
+
html += '</tr>';
|
2663
|
+
|
2664
|
+
// inject into the DOM
|
2665
|
+
yearpicker.html($(html));
|
2666
|
+
|
2667
|
+
// if date picker is always visible
|
2668
|
+
if (plugin.settings.always_visible)
|
2669
|
+
|
2670
|
+
// cache all the cells
|
2671
|
+
// (we need them so that we can easily remove the "dp_selected" class from all of them when user selects a year)
|
2672
|
+
yearpicker_cells = $('td:not(.dp_disabled)', yearpicker);
|
2673
|
+
|
2674
|
+
// make the year picker visible
|
2675
|
+
yearpicker.show();
|
2676
|
+
|
2677
|
+
};
|
2678
|
+
|
2679
|
+
/**
|
2680
|
+
* Return the name of a custom class to be applied to the given date.
|
2681
|
+
*
|
2682
|
+
* @return string The name of a custom class to be applied to the given date, or an empty string if no custom
|
2683
|
+
* class needs to be applied.
|
2684
|
+
*
|
2685
|
+
* @param integer year The year to check
|
2686
|
+
* @param integer month The month to check
|
2687
|
+
* @param integer day The day to check
|
2688
|
+
*
|
2689
|
+
* @access private
|
2690
|
+
*/
|
2691
|
+
var get_custom_class = function(year, month, day) {
|
2692
|
+
|
2693
|
+
var class_name, i, found;
|
2694
|
+
|
2695
|
+
// if month is given as argument, increment it (as JavaScript uses 0 for January, 1 for February...)
|
2696
|
+
if (typeof month !== 'undefined') month = month + 1;
|
2697
|
+
|
2698
|
+
// iterate through the custom classes
|
2699
|
+
for (i in custom_class_names) {
|
2700
|
+
|
2701
|
+
// the class name we're currently checking
|
2702
|
+
class_name = custom_class_names[i]; found = false;
|
2703
|
+
|
2704
|
+
// if there are any custom classes defined
|
2705
|
+
if ($.isArray(custom_classes[class_name]))
|
2706
|
+
|
2707
|
+
// iterate through the rules for which the custom class to be applied
|
2708
|
+
$.each(custom_classes[class_name], function() {
|
2709
|
+
|
2710
|
+
// if a custom class needs to be applied to the date we're checking, don't look further
|
2711
|
+
if (found) return;
|
2712
|
+
|
2713
|
+
var rule = this, weekday;
|
2714
|
+
|
2715
|
+
// if the rules apply for the current year
|
2716
|
+
if ($.inArray(year, rule[2]) > -1 || $.inArray('*', rule[2]) > -1)
|
2717
|
+
|
2718
|
+
// if the rules apply for the current month
|
2719
|
+
if ((typeof month !== 'undefined' && $.inArray(month, rule[1]) > -1) || $.inArray('*', rule[1]) > -1)
|
2720
|
+
|
2721
|
+
// if the rules apply for the current day
|
2722
|
+
if ((typeof day !== 'undefined' && $.inArray(day, rule[0]) > -1) || $.inArray('*', rule[0]) > -1) {
|
2723
|
+
|
2724
|
+
// if custom class is to be applied whatever the day
|
2725
|
+
// don't look any further
|
2726
|
+
if (rule[3].indexOf('*') > -1) return (found = class_name);
|
2727
|
+
|
2728
|
+
// get the weekday
|
2729
|
+
weekday = new Date(year, month - 1, day).getDay();
|
2730
|
+
|
2731
|
+
// if custom class is to be applied to weekday
|
2732
|
+
// don't look any further
|
2733
|
+
if ($.inArray(weekday, rule[3]) > -1) return (found = class_name);
|
2734
|
+
|
2735
|
+
}
|
2736
|
+
|
2737
|
+
});
|
2738
|
+
|
2739
|
+
// if a custom class needs to be applied to the date we're checking, don't look further
|
2740
|
+
if (found) return found;
|
2741
|
+
|
2742
|
+
}
|
2743
|
+
|
2744
|
+
// return what we've found
|
2745
|
+
return found || '';
|
2746
|
+
|
2747
|
+
};
|
2748
|
+
|
2749
|
+
/**
|
2750
|
+
* Generates an iFrame shim in Internet Explorer 6 so that the date picker appears above select boxes.
|
2751
|
+
*
|
2752
|
+
* @return void
|
2753
|
+
*
|
2754
|
+
* @access private
|
2755
|
+
*/
|
2756
|
+
var iframeShim = function(action) {
|
2757
|
+
|
2758
|
+
var zIndex, offset;
|
2759
|
+
|
2760
|
+
// this is necessary only if browser is Internet Explorer 6
|
2761
|
+
if (browser.name === 'explorer' && browser.version === 6) {
|
2762
|
+
|
2763
|
+
// if the iFrame was not yet created
|
2764
|
+
// "undefined" evaluates as FALSE
|
2765
|
+
if (!shim) {
|
2766
|
+
|
2767
|
+
// the iFrame has to have the element's zIndex minus 1
|
2768
|
+
zIndex = to_int(datepicker.css('zIndex')) - 1;
|
2769
|
+
|
2770
|
+
// create the iFrame
|
2771
|
+
shim = $('<iframe>', {
|
2772
|
+
src: 'javascript:document.write("")',
|
2773
|
+
scrolling: 'no',
|
2774
|
+
frameborder: 0,
|
2775
|
+
css: {
|
2776
|
+
zIndex: zIndex,
|
2777
|
+
position: 'absolute',
|
2778
|
+
top: -1000,
|
2779
|
+
left: -1000,
|
2780
|
+
width: datepicker.outerWidth(),
|
2781
|
+
height: datepicker.outerHeight(),
|
2782
|
+
filter: 'progid:DXImageTransform.Microsoft.Alpha(opacity=0)',
|
2783
|
+
display: 'none'
|
2784
|
+
}
|
2785
|
+
});
|
2786
|
+
|
2787
|
+
// inject iFrame into DOM
|
2788
|
+
$('body').append(shim);
|
2789
|
+
|
2790
|
+
}
|
2791
|
+
|
2792
|
+
// what do we need to do
|
2793
|
+
switch (action) {
|
2794
|
+
|
2795
|
+
// hide the iFrame?
|
2796
|
+
case 'hide':
|
2797
|
+
|
2798
|
+
// set the iFrame's display property to "none"
|
2799
|
+
shim.hide();
|
2800
|
+
|
2801
|
+
break;
|
2802
|
+
|
2803
|
+
// show the iFrame?
|
2804
|
+
default:
|
2805
|
+
|
2806
|
+
// get date picker top and left position
|
2807
|
+
offset = datepicker.offset();
|
2808
|
+
|
2809
|
+
// position the iFrame shim right underneath the date picker
|
2810
|
+
// and set its display to "block"
|
2811
|
+
shim.css({
|
2812
|
+
top: offset.top,
|
2813
|
+
left: offset.left,
|
2814
|
+
display: 'block'
|
2815
|
+
});
|
2816
|
+
|
2817
|
+
}
|
2818
|
+
|
2819
|
+
}
|
2820
|
+
|
2821
|
+
};
|
2822
|
+
|
2823
|
+
/**
|
2824
|
+
* Checks if, according to the restrictions of the calendar and/or the values defined by the "disabled_dates"
|
2825
|
+
* property, a day, a month or a year needs to be disabled.
|
2826
|
+
*
|
2827
|
+
* @param integer year The year to check
|
2828
|
+
* @param integer month The month to check
|
2829
|
+
* @param integer day The day to check
|
2830
|
+
*
|
2831
|
+
* @return boolean Returns TRUE if the given value is not disabled or FALSE otherwise
|
2832
|
+
*
|
2833
|
+
* @access private
|
2834
|
+
*/
|
2835
|
+
var is_disabled = function(year, month, day) {
|
2836
|
+
|
2837
|
+
var now, len, disabled, enabled;
|
2838
|
+
|
2839
|
+
// don't check bogus values
|
2840
|
+
if ((undefined === year || isNaN(year)) && (undefined === month || isNaN(month)) && (undefined === day || isNaN(day))) return false;
|
2841
|
+
|
2842
|
+
// this date picker cannot handle years before 1000, so we return false in this case
|
2843
|
+
else if (year < 1000) return true;
|
2844
|
+
|
2845
|
+
// if calendar has direction restrictions
|
2846
|
+
if (!(!$.isArray(plugin.settings.direction) && to_int(plugin.settings.direction) === 0)) {
|
2847
|
+
|
2848
|
+
// normalize and merge arguments then transform the result to an integer
|
2849
|
+
now = to_int(str_concat(year, (typeof month !== 'undefined' ? str_pad(month, 2) : ''), (typeof day !== 'undefined' ? str_pad(day, 2) : '')));
|
2850
|
+
|
2851
|
+
// get the length of the argument
|
2852
|
+
len = (now + '').length;
|
2853
|
+
|
2854
|
+
// if we're checking days
|
2855
|
+
if (len === 8 && (
|
2856
|
+
|
2857
|
+
// day is before the first selectable date
|
2858
|
+
(typeof start_date !== 'undefined' && now < to_int(str_concat(first_selectable_year, str_pad(first_selectable_month, 2), str_pad(first_selectable_day, 2)))) ||
|
2859
|
+
|
2860
|
+
// or day is after the last selectable date
|
2861
|
+
(typeof end_date !== 'undefined' && now > to_int(str_concat(last_selectable_year, str_pad(last_selectable_month, 2), str_pad(last_selectable_day, 2))))
|
2862
|
+
|
2863
|
+
// day needs to be disabled
|
2864
|
+
)) return true;
|
2865
|
+
|
2866
|
+
// if we're checking months
|
2867
|
+
else if (len === 6 && (
|
2868
|
+
|
2869
|
+
// month is before the first selectable month
|
2870
|
+
(typeof start_date !== 'undefined' && now < to_int(str_concat(first_selectable_year, str_pad(first_selectable_month, 2)))) ||
|
2871
|
+
|
2872
|
+
// or day is after the last selectable date
|
2873
|
+
(typeof end_date !== 'undefined' && now > to_int(str_concat(last_selectable_year, str_pad(last_selectable_month, 2))))
|
2874
|
+
|
2875
|
+
// month needs to be disabled
|
2876
|
+
)) return true;
|
2877
|
+
|
2878
|
+
// if we're checking years
|
2879
|
+
else if (len === 4 && (
|
2880
|
+
|
2881
|
+
// year is before the first selectable year
|
2882
|
+
(typeof start_date !== 'undefined' && now < first_selectable_year) ||
|
2883
|
+
|
2884
|
+
// or day is after the last selectable date
|
2885
|
+
(typeof end_date !== 'undefined' && now > last_selectable_year)
|
2886
|
+
|
2887
|
+
// year needs to be disabled
|
2888
|
+
)) return true;
|
2889
|
+
|
2890
|
+
}
|
2891
|
+
|
2892
|
+
// if month is given as argument, increment it (as JavaScript uses 0 for January, 1 for February...)
|
2893
|
+
if (typeof month !== 'undefined') month = month + 1;
|
2894
|
+
|
2895
|
+
// by default, we assume the day/month/year is not enabled nor disabled
|
2896
|
+
disabled = false, enabled = false;
|
2897
|
+
|
2898
|
+
// if there are rules for disabling dates
|
2899
|
+
if ($.isArray(disabled_dates) && disabled_dates.length)
|
2900
|
+
|
2901
|
+
// iterate through the rules for disabling dates
|
2902
|
+
$.each(disabled_dates, function() {
|
2903
|
+
|
2904
|
+
// if the date is to be disabled, don't look any further
|
2905
|
+
if (disabled) return;
|
2906
|
+
|
2907
|
+
var rule = this, weekday;
|
2908
|
+
|
2909
|
+
// if the rules apply for the current year
|
2910
|
+
if ($.inArray(year, rule[2]) > -1 || $.inArray('*', rule[2]) > -1)
|
2911
|
+
|
2912
|
+
// if the rules apply for the current month
|
2913
|
+
if ((typeof month !== 'undefined' && $.inArray(month, rule[1]) > -1) || $.inArray('*', rule[1]) > -1)
|
2914
|
+
|
2915
|
+
// if the rules apply for the current day
|
2916
|
+
if ((typeof day !== 'undefined' && $.inArray(day, rule[0]) > -1) || $.inArray('*', rule[0]) > -1) {
|
2917
|
+
|
2918
|
+
// if day is to be disabled whatever the day
|
2919
|
+
// don't look any further
|
2920
|
+
if (rule[3].indexOf('*') > -1) return (disabled = true);
|
2921
|
+
|
2922
|
+
// get the weekday
|
2923
|
+
weekday = new Date(year, month - 1, day).getDay();
|
2924
|
+
|
2925
|
+
// if weekday is to be disabled
|
2926
|
+
// don't look any further
|
2927
|
+
if ($.inArray(weekday, rule[3]) > -1) return (disabled = true);
|
2928
|
+
|
2929
|
+
}
|
2930
|
+
|
2931
|
+
});
|
2932
|
+
|
2933
|
+
// if there are rules that explicitly enable dates
|
2934
|
+
if (enabled_dates)
|
2935
|
+
|
2936
|
+
// iterate through the rules for enabling dates
|
2937
|
+
$.each(enabled_dates, function() {
|
2938
|
+
|
2939
|
+
// if the date is to be enabled, don't look any further
|
2940
|
+
if (enabled) return;
|
2941
|
+
|
2942
|
+
var rule = this, weekday;
|
2943
|
+
|
2944
|
+
// if the rules apply for the current year
|
2945
|
+
if ($.inArray(year, rule[2]) > -1 || $.inArray('*', rule[2]) > -1) {
|
2946
|
+
|
2947
|
+
// the year is enabled
|
2948
|
+
enabled = true;
|
2949
|
+
|
2950
|
+
// if we're also checking months
|
2951
|
+
if (typeof month !== 'undefined') {
|
2952
|
+
|
2953
|
+
// we assume the month is enabled
|
2954
|
+
enabled = true;
|
2955
|
+
|
2956
|
+
// if the rules apply for the current month
|
2957
|
+
if ($.inArray(month, rule[1]) > -1 || $.inArray('*', rule[1]) > -1) {
|
2958
|
+
|
2959
|
+
// if we're also checking days
|
2960
|
+
if (typeof day !== 'undefined') {
|
2961
|
+
|
2962
|
+
// we assume the day is enabled
|
2963
|
+
enabled = true;
|
2964
|
+
|
2965
|
+
// if the rules apply for the current day
|
2966
|
+
if ($.inArray(day, rule[0]) > -1 || $.inArray('*', rule[0]) > -1) {
|
2967
|
+
|
2968
|
+
// if day is to be enabled whatever the day
|
2969
|
+
// don't look any further
|
2970
|
+
if (rule[3].indexOf('*') > -1) return (enabled = true);
|
2971
|
+
|
2972
|
+
// get the weekday
|
2973
|
+
weekday = new Date(year, month - 1, day).getDay();
|
2974
|
+
|
2975
|
+
// if weekday is to be enabled
|
2976
|
+
// don't look any further
|
2977
|
+
if ($.inArray(weekday, rule[3]) > -1) return (enabled = true);
|
2978
|
+
|
2979
|
+
// if we get this far, it means the day is not enabled
|
2980
|
+
enabled = false;
|
2981
|
+
|
2982
|
+
// if day is not enabled
|
2983
|
+
} else enabled = false;
|
2984
|
+
|
2985
|
+
}
|
2986
|
+
|
2987
|
+
// if month is not enabled
|
2988
|
+
} else enabled = false;
|
2989
|
+
|
2990
|
+
}
|
2991
|
+
|
2992
|
+
}
|
2993
|
+
|
2994
|
+
});
|
2995
|
+
|
2996
|
+
// if checked date is enabled, return false
|
2997
|
+
if (enabled_dates && enabled) return false;
|
2998
|
+
|
2999
|
+
// if checked date is disabled return false
|
3000
|
+
else if (disabled_dates && disabled) return true;
|
3001
|
+
|
3002
|
+
// if script gets this far it means that the day/month/year doesn't need to be disabled
|
3003
|
+
return false;
|
3004
|
+
|
3005
|
+
};
|
3006
|
+
|
3007
|
+
/**
|
3008
|
+
* Checks whether a value is an integer number.
|
3009
|
+
*
|
3010
|
+
* @param mixed value Value to check
|
3011
|
+
*
|
3012
|
+
* @return Returns TRUE if the value represents an integer number, or FALSE otherwise
|
3013
|
+
*
|
3014
|
+
* @access private
|
3015
|
+
*/
|
3016
|
+
var is_integer = function(value) {
|
3017
|
+
|
3018
|
+
// return TRUE if value represents an integer number, or FALSE otherwise
|
3019
|
+
return (value + '').match(/^\-?[0-9]+$/);
|
3020
|
+
|
3021
|
+
};
|
3022
|
+
|
3023
|
+
/**
|
3024
|
+
* Sets the caption in the header of the date picker and enables or disables navigation buttons when necessary.
|
3025
|
+
*
|
3026
|
+
* @param string caption String that needs to be displayed in the header
|
3027
|
+
*
|
3028
|
+
* @return void
|
3029
|
+
*
|
3030
|
+
* @access private
|
3031
|
+
*/
|
3032
|
+
var manage_header = function(caption) {
|
3033
|
+
|
3034
|
+
// if "selected_month" has a value
|
3035
|
+
// $.isNumeric is available only from jQuery 1.7 - thanks to birla for the fix!
|
3036
|
+
if (!isNaN(parseFloat(selected_month)) && isFinite(selected_month))
|
3037
|
+
|
3038
|
+
caption = caption.replace(/\bm\b|\bn\b|\bF\b|\bM\b/, function(match) {
|
3039
|
+
|
3040
|
+
switch (match) {
|
3041
|
+
|
3042
|
+
// month number, prefixed with 0
|
3043
|
+
case 'm':
|
3044
|
+
return str_pad(selected_month + 1, 2);
|
3045
|
+
|
3046
|
+
// month number, not prefixed with 0
|
3047
|
+
case 'n':
|
3048
|
+
return selected_month + 1;
|
3049
|
+
|
3050
|
+
// full month name
|
3051
|
+
case 'F':
|
3052
|
+
return plugin.settings.months[selected_month];
|
3053
|
+
|
3054
|
+
// month name, three letters
|
3055
|
+
case 'M':
|
3056
|
+
return ($.isArray(plugin.settings.months_abbr) && undefined !== plugin.settings.months_abbr[selected_month] ? plugin.settings.months_abbr[selected_month] : plugin.settings.months[selected_month].substr(0, 3));
|
3057
|
+
|
3058
|
+
// unknown replace
|
3059
|
+
default:
|
3060
|
+
return match;
|
3061
|
+
|
3062
|
+
}
|
3063
|
+
|
3064
|
+
});
|
3065
|
+
|
3066
|
+
// if "selected_year" has a value
|
3067
|
+
// $.isNumeric is available only from jQuery 1.7 - thanks to birla for the fix!
|
3068
|
+
if (!isNaN(parseFloat(selected_year)) && isFinite(selected_year))
|
3069
|
+
|
3070
|
+
// replace year-related patterns
|
3071
|
+
caption =
|
3072
|
+
|
3073
|
+
caption
|
3074
|
+
|
3075
|
+
// year as four digits
|
3076
|
+
.replace(/\bY\b/, selected_year)
|
3077
|
+
|
3078
|
+
// year as two digits
|
3079
|
+
.replace(/\by\b/, (selected_year + '').substr(2))
|
3080
|
+
|
3081
|
+
// lower limit of year as two or four digits
|
3082
|
+
.replace(/\bY1\b/i, selected_year - 7)
|
3083
|
+
|
3084
|
+
// upper limit of year as two or four digits
|
3085
|
+
.replace(/\bY2\b/i, selected_year + 4);
|
3086
|
+
|
3087
|
+
// update the caption in the header
|
3088
|
+
$('.dp_caption', header).html(caption);
|
3089
|
+
|
3090
|
+
};
|
3091
|
+
|
3092
|
+
/**
|
3093
|
+
* Shows the appropriate view (days, months or years) according to the current value of the "view" property.
|
3094
|
+
*
|
3095
|
+
* @return void
|
3096
|
+
*
|
3097
|
+
* @access private
|
3098
|
+
*/
|
3099
|
+
var manage_views = function() {
|
3100
|
+
|
3101
|
+
var height, elements;
|
3102
|
+
|
3103
|
+
// if the day picker was not yet generated
|
3104
|
+
if (daypicker.text() === '' || view === 'days') {
|
3105
|
+
|
3106
|
+
// if the day picker was not yet generated
|
3107
|
+
if (daypicker.text() === '') {
|
3108
|
+
|
3109
|
+
// if date picker is not always visible in a container
|
3110
|
+
if (!(plugin.settings.always_visible instanceof jQuery))
|
3111
|
+
|
3112
|
+
// temporarily set the date picker's left outside of view
|
3113
|
+
// so that we can later grab its width and height
|
3114
|
+
datepicker.css('left', -1000);
|
3115
|
+
|
3116
|
+
// temporarily make the date picker visible
|
3117
|
+
// so that we can later grab its width and height
|
3118
|
+
datepicker.removeClass('hidden');
|
3119
|
+
|
3120
|
+
// generate the day picker
|
3121
|
+
generate_daypicker();
|
3122
|
+
|
3123
|
+
// jQuery rounds values returned by outerWidth and outerHeight
|
3124
|
+
// therefore, if we can get the un-rounded values, get those
|
3125
|
+
// get the day picker's width and height
|
3126
|
+
if (typeof daypicker[0].getBoundingClientRect !== 'undefined') height = daypicker[0].getBoundingClientRect().height;
|
3127
|
+
|
3128
|
+
// if "getBoundingClientRect" is not available
|
3129
|
+
// get the day picker's height
|
3130
|
+
else height = daypicker.outerHeight(true);
|
3131
|
+
|
3132
|
+
// make the month picker have the same size as the day picker
|
3133
|
+
monthpicker.css('height', height);
|
3134
|
+
|
3135
|
+
// make the year picker have the same size as the day picker
|
3136
|
+
yearpicker.css('height', height);
|
3137
|
+
|
3138
|
+
// make the time picker have the same size as the day picker
|
3139
|
+
timepicker.css('height', height + header.outerHeight(true));
|
3140
|
+
|
3141
|
+
// set the container's width so all the views have 100% width
|
3142
|
+
datepicker.css('width', datepicker.outerWidth());
|
3143
|
+
|
3144
|
+
// // we have to set this now or Chrome will make the datepicker extend to the full width of the screen...
|
3145
|
+
// $('.dp_caption', header).css('width', '100%');
|
3146
|
+
|
3147
|
+
// hide the date picker again
|
3148
|
+
datepicker.addClass('dp_hidden');
|
3149
|
+
|
3150
|
+
// if the day picker was previously generated at least once
|
3151
|
+
// generate the day picker
|
3152
|
+
} else generate_daypicker();
|
3153
|
+
|
3154
|
+
// show header
|
3155
|
+
header.show();
|
3156
|
+
|
3157
|
+
// hide the year and the month pickers
|
3158
|
+
monthpicker.hide();
|
3159
|
+
yearpicker.hide();
|
3160
|
+
|
3161
|
+
// hide time-picker related elements
|
3162
|
+
timepicker.hide();
|
3163
|
+
view_toggler.hide();
|
3164
|
+
confirm_selection.hide();
|
3165
|
+
|
3166
|
+
// if the time picker is enabled, show the clock icon
|
3167
|
+
if (timepicker_config) view_toggler.show().removeClass('dp_calendar');
|
3168
|
+
|
3169
|
+
// if the view is "months"
|
3170
|
+
} else if (view === 'months') {
|
3171
|
+
|
3172
|
+
// generate the month picker
|
3173
|
+
generate_monthpicker();
|
3174
|
+
|
3175
|
+
// hide the day and the year pickers
|
3176
|
+
daypicker.hide();
|
3177
|
+
yearpicker.hide();
|
3178
|
+
|
3179
|
+
// hide time-picker related elements
|
3180
|
+
timepicker.hide();
|
3181
|
+
view_toggler.hide();
|
3182
|
+
confirm_selection.hide();
|
3183
|
+
|
3184
|
+
// if the view is "years"
|
3185
|
+
} else if (view === 'years') {
|
3186
|
+
|
3187
|
+
// generate the year picker
|
3188
|
+
generate_yearpicker();
|
3189
|
+
|
3190
|
+
// hide the day and the month pickers
|
3191
|
+
daypicker.hide();
|
3192
|
+
monthpicker.hide();
|
3193
|
+
|
3194
|
+
// hide time-picker related elements
|
3195
|
+
timepicker.hide();
|
3196
|
+
view_toggler.hide();
|
3197
|
+
confirm_selection.hide();
|
3198
|
+
|
3199
|
+
// if the view is "time"
|
3200
|
+
} else if (view === 'time') {
|
3201
|
+
|
3202
|
+
// generate the time picker
|
3203
|
+
generate_timepicker();
|
3204
|
+
|
3205
|
+
// if the "time" view is the only available view
|
3206
|
+
if (views.length === 1) {
|
3207
|
+
|
3208
|
+
// hide the time picker toggler button
|
3209
|
+
view_toggler.hide();
|
3210
|
+
|
3211
|
+
// show the confirmation button
|
3212
|
+
confirm_selection.show();
|
3213
|
+
|
3214
|
+
// if the "time" view is not the only available view
|
3215
|
+
} else {
|
3216
|
+
|
3217
|
+
// time picker toggler button, but change the icon
|
3218
|
+
view_toggler.show().addClass('dp_calendar');
|
3219
|
+
|
3220
|
+
// if no date is selected
|
3221
|
+
// hide the confirmation button
|
3222
|
+
if ($element.val() === '') confirm_selection.hide();
|
3223
|
+
|
3224
|
+
// show the confirmation button
|
3225
|
+
else confirm_selection.show();
|
3226
|
+
|
3227
|
+
}
|
3228
|
+
|
3229
|
+
// hide the header, day, month and year pickers
|
3230
|
+
header.hide();
|
3231
|
+
daypicker.hide();
|
3232
|
+
monthpicker.hide();
|
3233
|
+
yearpicker.hide();
|
3234
|
+
|
3235
|
+
}
|
3236
|
+
|
3237
|
+
// if a callback function exists for when navigating through months/years
|
3238
|
+
if (view !== 'time' && plugin.settings.onChange && typeof plugin.settings.onChange === 'function' && undefined !== view) {
|
3239
|
+
|
3240
|
+
// get the "active" elements in the view (ignoring the disabled ones)
|
3241
|
+
elements = (view === 'days' ?
|
3242
|
+
daypicker.find('td:not(.dp_disabled)') :
|
3243
|
+
(view === 'months' ?
|
3244
|
+
monthpicker.find('td:not(.dp_disabled)') :
|
3245
|
+
yearpicker.find('td:not(.dp_disabled)')));
|
3246
|
+
|
3247
|
+
// iterate through the active elements
|
3248
|
+
// and attach a "date" data attribute to each element in the form of
|
3249
|
+
// YYYY-MM-DD if the view is "days"
|
3250
|
+
// YYYY-MM if the view is "months"
|
3251
|
+
// YYYY if the view is "years"
|
3252
|
+
// so it's easy to identify elements in the list
|
3253
|
+
elements.each(function() {
|
3254
|
+
|
3255
|
+
var matches;
|
3256
|
+
|
3257
|
+
// if view is "days"
|
3258
|
+
if (view === 'days')
|
3259
|
+
|
3260
|
+
// if date is from a next/previous month and is selectable
|
3261
|
+
if ($(this).hasClass('dp_not_in_month') && !$(this).hasClass('dp_disabled')) {
|
3262
|
+
|
3263
|
+
// extract date from the attached class
|
3264
|
+
matches = $(this).attr('class').match(/date\_([0-9]{4})(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])/);
|
3265
|
+
|
3266
|
+
// attach a "date" data attribute to each element in the form of of YYYY-MM-DD for easily identifying sought elements
|
3267
|
+
$(this).data('date', matches[1] + '-' + matches[2] + '-' + matches[3]);
|
3268
|
+
|
3269
|
+
// if date is from the currently selected month
|
3270
|
+
} else
|
3271
|
+
|
3272
|
+
// attach a "date" data attribute to each element in the form of of YYYY-MM-DD for easily identifying sought elements
|
3273
|
+
$(this).data('date', selected_year + '-' + str_pad(selected_month + 1, 2) + '-' + str_pad(to_int($(this).text()), 2));
|
3274
|
+
|
3275
|
+
// if view is "months"
|
3276
|
+
else if (view === 'months') {
|
3277
|
+
|
3278
|
+
// get the month's number for the element's class
|
3279
|
+
matches = $(this).attr('class').match(/dp\_month\_([0-9]+)/);
|
3280
|
+
|
3281
|
+
// attach a "date" data attribute to each element in the form of of YYYY-MM for easily identifying sought elements
|
3282
|
+
$(this).data('date', selected_year + '-' + str_pad(to_int(matches[1]) + 1, 2));
|
3283
|
+
|
3284
|
+
// if view is "years"
|
3285
|
+
} else
|
3286
|
+
|
3287
|
+
// attach a "date" data attribute to each element in the form of of YYYY for easily identifying sought elements
|
3288
|
+
$(this).data('date', to_int($(this).text()));
|
3289
|
+
|
3290
|
+
});
|
3291
|
+
|
3292
|
+
// execute the callback function and send as arguments the current view, the elements in the view, and
|
3293
|
+
// the element the plugin is attached to
|
3294
|
+
plugin.settings.onChange.call($element, view, elements, $element);
|
3295
|
+
|
3296
|
+
}
|
3297
|
+
|
3298
|
+
// assume the footer is visible
|
3299
|
+
footer.show();
|
3300
|
+
|
3301
|
+
// if we are in the "time" view and there are more views available
|
3302
|
+
if (view === 'time' && views.length > 1) {
|
3303
|
+
|
3304
|
+
// hide the "Today" and the "Clear" buttons
|
3305
|
+
selecttoday.hide();
|
3306
|
+
cleardate.hide();
|
3307
|
+
|
3308
|
+
// for the other cases
|
3309
|
+
} else {
|
3310
|
+
|
3311
|
+
// assume both the "Today" and "Clear" buttons are visible
|
3312
|
+
selecttoday.show();
|
3313
|
+
cleardate.show();
|
3314
|
+
|
3315
|
+
// if the button for clearing a previously selected date needs to be visible all the time,
|
3316
|
+
// or the "Clear" button needs to be shown only when a date was previously selected, and now it's the case,
|
3317
|
+
// or the date picker is always visible and the "Clear" button was not explicitly disabled
|
3318
|
+
if (
|
3319
|
+
plugin.settings.show_clear_date === true ||
|
3320
|
+
(plugin.settings.show_clear_date === 0 && $element.val() !== '') ||
|
3321
|
+
(plugin.settings.always_visible && plugin.settings.show_clear_date !== false)
|
3322
|
+
)
|
3323
|
+
|
3324
|
+
// if the "Today" button is visible
|
3325
|
+
if (show_select_today) {
|
3326
|
+
|
3327
|
+
// show it, and set it's width to 50% of the available space
|
3328
|
+
selecttoday.css('width', '50%');
|
3329
|
+
|
3330
|
+
// the "Clear date" button only takes up 50% of the available space
|
3331
|
+
cleardate.css('width', '50%');
|
3332
|
+
|
3333
|
+
// if the "Today" button is not visible
|
3334
|
+
} else {
|
3335
|
+
|
3336
|
+
// hide the "Today" button
|
3337
|
+
selecttoday.hide();
|
3338
|
+
|
3339
|
+
// the "Clear date" button takes up 100% of the available space
|
3340
|
+
// unless the time picker is available, in which case take up 50% of the available space
|
3341
|
+
cleardate.css('width', views.indexOf('time') > -1 ? '50%' : '100%');
|
3342
|
+
|
3343
|
+
}
|
3344
|
+
|
3345
|
+
// otherwise
|
3346
|
+
else {
|
3347
|
+
|
3348
|
+
// hide the "Clear" button
|
3349
|
+
cleardate.hide();
|
3350
|
+
|
3351
|
+
// if the "Today" button is visible, it will now take up all the available space
|
3352
|
+
if (show_select_today) selecttoday.css('width', '100%');
|
3353
|
+
|
3354
|
+
// if the "Today" button should not be visible
|
3355
|
+
else {
|
3356
|
+
|
3357
|
+
// hide the "Today" button
|
3358
|
+
selecttoday.hide();
|
3359
|
+
|
3360
|
+
// if there's also no timepicker view, hide the footer entirely
|
3361
|
+
if (!timepicker_config || (view !== 'time' && view !== 'days')) footer.hide();
|
3362
|
+
|
3363
|
+
}
|
3364
|
+
|
3365
|
+
}
|
3366
|
+
|
3367
|
+
}
|
3368
|
+
|
3369
|
+
};
|
3370
|
+
|
3371
|
+
/**
|
3372
|
+
* Puts the specified date in the element the plugin is attached to, and hides the date picker.
|
3373
|
+
*
|
3374
|
+
* @param integer year The year
|
3375
|
+
*
|
3376
|
+
* @param integer month The month
|
3377
|
+
*
|
3378
|
+
* @param integer day The day
|
3379
|
+
*
|
3380
|
+
* @param string rview The view from where the method was called (the referrer view)
|
3381
|
+
*
|
3382
|
+
* @param object cell The element that was clicked
|
3383
|
+
*
|
3384
|
+
* @return void
|
3385
|
+
*
|
3386
|
+
* @access private
|
3387
|
+
*/
|
3388
|
+
var select_date = function(year, month, day, rview, cell) {
|
3389
|
+
|
3390
|
+
var
|
3391
|
+
|
3392
|
+
// construct a new date object from the arguments
|
3393
|
+
default_date = new Date(year, month, day, (timepicker_config && timepicker_config.hours ? selected_hour + (timepicker_config.ampm && selected_ampm === 'pm' ? 12 : 0) : 12), (timepicker_config && timepicker_config.minutes ? selected_minute : 0), (timepicker_config && timepicker_config.seconds ? selected_second : 0)),
|
3394
|
+
|
3395
|
+
// pointer to the cells in the current view
|
3396
|
+
view_cells = (rview === 'days' ? daypicker_cells : (rview === 'months' ? monthpicker_cells : yearpicker_cells)),
|
3397
|
+
|
3398
|
+
// the selected date, formatted correctly
|
3399
|
+
selected_value = format(default_date);
|
3400
|
+
|
3401
|
+
// set the currently selected and formated date as the value of the element the plugin is attached to
|
3402
|
+
$element.val(selected_value);
|
3403
|
+
|
3404
|
+
// if date picker is always visible or time picker is available
|
3405
|
+
if (plugin.settings.always_visible || timepicker_config) {
|
3406
|
+
|
3407
|
+
// extract the date parts and reassign values to these variables
|
3408
|
+
// so that everything will be correctly highlighted
|
3409
|
+
default_month = default_date.getMonth();
|
3410
|
+
selected_month = default_date.getMonth();
|
3411
|
+
default_year = default_date.getFullYear();
|
3412
|
+
selected_year = default_date.getFullYear();
|
3413
|
+
default_day = default_date.getDate();
|
3414
|
+
|
3415
|
+
// if "cell" is available (it isn't when called from increasing/decreasing values the time picker)
|
3416
|
+
if (cell && view_cells) {
|
3417
|
+
|
3418
|
+
// remove the "selected" class from all cells in the current view
|
3419
|
+
view_cells.removeClass('dp_selected');
|
3420
|
+
|
3421
|
+
// add the "selected" class to the currently selected cell
|
3422
|
+
cell.addClass('dp_selected');
|
3423
|
+
|
3424
|
+
// if we're on the "days" view and days from other months are selectable and one of those days was
|
3425
|
+
// selected, repaint the datepicker so it will take us to the selected month
|
3426
|
+
if (rview === 'days' && cell.hasClass('dp_not_in_month') && !cell.hasClass('dp_disabled')) plugin.show();
|
3427
|
+
|
3428
|
+
}
|
3429
|
+
|
3430
|
+
}
|
3431
|
+
|
3432
|
+
// if format contains time, switch to the time picker view
|
3433
|
+
if (timepicker_config) {
|
3434
|
+
|
3435
|
+
view = 'time';
|
3436
|
+
manage_views();
|
3437
|
+
|
3438
|
+
// if format doesn't contain time
|
3439
|
+
} else {
|
3440
|
+
|
3441
|
+
// move focus to the element the plugin is attached to
|
3442
|
+
$element.focus();
|
3443
|
+
|
3444
|
+
// hide the date picker
|
3445
|
+
plugin.hide();
|
3446
|
+
|
3447
|
+
}
|
3448
|
+
|
3449
|
+
// updates value for the date picker whose starting date depends on the selected date (if any)
|
3450
|
+
update_dependent(default_date);
|
3451
|
+
|
3452
|
+
// if a callback function exists for when selecting a date
|
3453
|
+
if (plugin.settings.onSelect && typeof plugin.settings.onSelect === 'function')
|
3454
|
+
|
3455
|
+
// execute the callback function
|
3456
|
+
// make "this" inside the callback function refer to the element the date picker is attached to
|
3457
|
+
plugin.settings.onSelect.call($element, selected_value, year + '-' + str_pad(month + 1, 2) + '-' + str_pad(day, 2), default_date, $element, getWeekNumber(default_date));
|
3458
|
+
|
3459
|
+
};
|
3460
|
+
|
3461
|
+
/**
|
3462
|
+
* Concatenates any number of arguments and returns them as string.
|
3463
|
+
*
|
3464
|
+
* @return string Returns the concatenated values.
|
3465
|
+
*
|
3466
|
+
* @access private
|
3467
|
+
*/
|
3468
|
+
var str_concat = function() {
|
3469
|
+
|
3470
|
+
var str = '', i;
|
3471
|
+
|
3472
|
+
// concatenate as string
|
3473
|
+
for (i = 0; i < arguments.length; i++) str += (arguments[i] + '');
|
3474
|
+
|
3475
|
+
// return the concatenated values
|
3476
|
+
return str;
|
3477
|
+
|
3478
|
+
};
|
3479
|
+
|
3480
|
+
/**
|
3481
|
+
* Left-pad a string to a certain length with zeroes.
|
3482
|
+
*
|
3483
|
+
* @param string str The string to be padded.
|
3484
|
+
*
|
3485
|
+
* @param integer len The length to which the string must be padded
|
3486
|
+
*
|
3487
|
+
* @return string Returns the string left-padded with leading zeroes
|
3488
|
+
*
|
3489
|
+
* @access private
|
3490
|
+
*/
|
3491
|
+
var str_pad = function(str, len) {
|
3492
|
+
|
3493
|
+
// make sure argument is a string
|
3494
|
+
str += '';
|
3495
|
+
|
3496
|
+
// pad with leading zeroes until we get to the desired length
|
3497
|
+
while (str.length < len) str = '0' + str;
|
3498
|
+
|
3499
|
+
// return padded string
|
3500
|
+
return str;
|
3501
|
+
|
3502
|
+
};
|
3503
|
+
|
3504
|
+
/**
|
3505
|
+
* Returns the integer representation of a string
|
3506
|
+
*
|
3507
|
+
* @return int Returns the integer representation of the string given as argument
|
3508
|
+
*
|
3509
|
+
* @access private
|
3510
|
+
*/
|
3511
|
+
var to_int = function(str) {
|
3512
|
+
|
3513
|
+
// return the integer representation of the string given as argument
|
3514
|
+
return parseInt(str, 10);
|
3515
|
+
|
3516
|
+
};
|
3517
|
+
|
3518
|
+
/**
|
3519
|
+
* Updates the paired date picker (whose starting date depends on the value of the current date picker)
|
3520
|
+
*
|
3521
|
+
* @param date date A JavaScript date object representing the currently selected date
|
3522
|
+
*
|
3523
|
+
* @return void
|
3524
|
+
*
|
3525
|
+
* @access private
|
3526
|
+
*/
|
3527
|
+
var update_dependent = function(date) {
|
3528
|
+
|
3529
|
+
// if the pair element exists
|
3530
|
+
if (plugin.settings.pair)
|
3531
|
+
|
3532
|
+
// iterate through the pair elements (as there may be more than just one)
|
3533
|
+
$.each(plugin.settings.pair, function() {
|
3534
|
+
|
3535
|
+
var $pair = $(this), dp;
|
3536
|
+
|
3537
|
+
// chances are that in the beginning the pair element doesn't have the Zebra_DatePicker attached to it yet
|
3538
|
+
// (as the "start" element is usually created before the "end" element)
|
3539
|
+
// so we'll have to rely on "data" to send the starting date to the pair element
|
3540
|
+
|
3541
|
+
// therefore, if Zebra_DatePicker is not yet attached
|
3542
|
+
if (!($pair.data && $pair.data('Zebra_DatePicker')))
|
3543
|
+
|
3544
|
+
// set the starting date like this
|
3545
|
+
$pair.data('zdp_reference_date', date);
|
3546
|
+
|
3547
|
+
// if Zebra_DatePicker is attached to the pair element
|
3548
|
+
else {
|
3549
|
+
|
3550
|
+
// reference the date picker object attached to the other element
|
3551
|
+
dp = $pair.data('Zebra_DatePicker');
|
3552
|
+
|
3553
|
+
// update the other date picker's starting date
|
3554
|
+
// the value depends on the original value of the "direction" attribute
|
3555
|
+
// (also, if the pair date picker does not have a direction, set it to 1)
|
3556
|
+
dp.update({
|
3557
|
+
reference_date: date,
|
3558
|
+
direction: dp.settings.direction === 0 ? 1 : dp.settings.direction
|
3559
|
+
});
|
3560
|
+
|
3561
|
+
// if the other date picker is always visible, update the visuals now
|
3562
|
+
if (dp.settings.always_visible) dp.show();
|
3563
|
+
|
3564
|
+
}
|
3565
|
+
|
3566
|
+
});
|
3567
|
+
|
3568
|
+
};
|
3569
|
+
|
3570
|
+
/**
|
3571
|
+
* Calculate the ISO 8601 week number for a given date.
|
3572
|
+
*
|
3573
|
+
* Code is based on the algorithm at http://www.tondering.dk/claus/cal/week.php#calcweekno
|
3574
|
+
*/
|
3575
|
+
var getWeekNumber = function(date) {
|
3576
|
+
|
3577
|
+
var y = date.getFullYear(),
|
3578
|
+
m = date.getMonth() + 1,
|
3579
|
+
d = date.getDate(),
|
3580
|
+
a, b, c, s, e, f, g, n, w;
|
3581
|
+
|
3582
|
+
// If month jan. or feb.
|
3583
|
+
if (m < 3) {
|
3584
|
+
|
3585
|
+
a = y - 1;
|
3586
|
+
b = (a / 4 | 0) - (a / 100 | 0) + (a / 400 | 0);
|
3587
|
+
c = ((a - 1) / 4 | 0) - ((a - 1) / 100 | 0) + ((a - 1) / 400 | 0);
|
3588
|
+
s = b - c;
|
3589
|
+
e = 0;
|
3590
|
+
f = d - 1 + 31 * (m - 1);
|
3591
|
+
|
3592
|
+
// If month mar. through dec.
|
3593
|
+
} else {
|
3594
|
+
|
3595
|
+
a = y;
|
3596
|
+
b = (a / 4 | 0) - (a / 100 | 0) + (a / 400 | 0);
|
3597
|
+
c = ((a - 1) / 4 | 0) - ((a - 1) / 100 | 0) + ((a - 1) / 400 | 0);
|
3598
|
+
s = b - c;
|
3599
|
+
e = s + 1;
|
3600
|
+
f = d + ((153 * (m - 3) + 2) / 5 | 0) + 58 + s;
|
3601
|
+
|
3602
|
+
}
|
3603
|
+
|
3604
|
+
g = (a + b) % 7;
|
3605
|
+
// ISO Weekday (0 is monday, 1 is tuesday etc.)
|
3606
|
+
d = (f + g - e) % 7;
|
3607
|
+
n = f + 3 - d;
|
3608
|
+
|
3609
|
+
if (n < 0) w = 53 - ((g - s) / 5 | 0);
|
3610
|
+
|
3611
|
+
else if (n > 364 + s) w = 1;
|
3612
|
+
|
3613
|
+
else w = (n / 7 | 0) + 1;
|
3614
|
+
|
3615
|
+
return w;
|
3616
|
+
|
3617
|
+
};
|
3618
|
+
|
3619
|
+
// since with jQuery 1.9.0 the $.browser object was removed, we rely on this piece of code from
|
3620
|
+
// http://www.quirksmode.org/js/detect.html to detect the browser
|
3621
|
+
var browser = {
|
3622
|
+
init: function() {
|
3623
|
+
this.name = this.searchString(this.dataBrowser) || '';
|
3624
|
+
this.version = this.searchVersion(navigator.userAgent) || this.searchVersion(navigator.appVersion) || '';
|
3625
|
+
},
|
3626
|
+
searchString: function(data) {
|
3627
|
+
var i, dataString, dataProp;
|
3628
|
+
|
3629
|
+
for (i = 0; i < data.length; i++) {
|
3630
|
+
dataString = data[i].string;
|
3631
|
+
dataProp = data[i].prop;
|
3632
|
+
this.versionSearchString = data[i].versionSearch || data[i].identity;
|
3633
|
+
if (dataString) {
|
3634
|
+
if (dataString.indexOf(data[i].subString) !== -1)
|
3635
|
+
return data[i].identity;
|
3636
|
+
} else if (dataProp)
|
3637
|
+
return data[i].identity;
|
3638
|
+
}
|
3639
|
+
},
|
3640
|
+
searchVersion: function(dataString) {
|
3641
|
+
var index = dataString.indexOf(this.versionSearchString);
|
3642
|
+
|
3643
|
+
if (index === -1) return;
|
3644
|
+
|
3645
|
+
return parseFloat(dataString.substring(index + this.versionSearchString.length + 1));
|
3646
|
+
},
|
3647
|
+
dataBrowser: [
|
3648
|
+
{
|
3649
|
+
string: navigator.userAgent,
|
3650
|
+
subString: 'Firefox',
|
3651
|
+
identity: 'firefox'
|
3652
|
+
},
|
3653
|
+
{
|
3654
|
+
string: navigator.userAgent,
|
3655
|
+
subString: 'MSIE',
|
3656
|
+
identity: 'explorer',
|
3657
|
+
versionSearch: 'MSIE'
|
3658
|
+
}
|
3659
|
+
]
|
3660
|
+
};
|
3661
|
+
|
3662
|
+
browser.init();
|
3663
|
+
|
3664
|
+
// initialize the plugin
|
3665
|
+
init();
|
3666
|
+
|
3667
|
+
};
|
3668
|
+
|
3669
|
+
$.fn.Zebra_DatePicker = function(options) {
|
3670
|
+
|
3671
|
+
// iterate through all the elements to which we need to attach the date picker to
|
3672
|
+
return this.each(function() {
|
3673
|
+
|
3674
|
+
// if element has a date picker already attached
|
3675
|
+
if (undefined !== $(this).data('Zebra_DatePicker'))
|
3676
|
+
|
3677
|
+
// remove the attached date picker
|
3678
|
+
$(this).data('Zebra_DatePicker').destroy();
|
3679
|
+
|
3680
|
+
// create an instance of the plugin
|
3681
|
+
var plugin = new $.Zebra_DatePicker(this, options);
|
3682
|
+
|
3683
|
+
// save a reference to the newly created object
|
3684
|
+
$(this).data('Zebra_DatePicker', plugin);
|
3685
|
+
|
3686
|
+
});
|
3687
|
+
|
3688
|
+
};
|
3689
|
+
|
3690
|
+
}));
|