zebra-datepicker-rails 1.9.5 → 1.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
}));
|