diff --git a/angular-material-calendar.js b/angular-material-calendar.js index 8b41ad6..6a5938b 100644 --- a/angular-material-calendar.js +++ b/angular-material-calendar.js @@ -166,7 +166,7 @@ angular.module("materialCalendar").service("MaterialCalendarData", [function () angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse", "$templateRequest", "$q", "materialCalendar.Calendar", "MaterialCalendarData", function ($compile, $parse, $templateRequest, $q, Calendar, CalendarData) { - var defaultTemplate = "Previous month«{{ calendar.start | date:titleFormat:timezone }}Next month»{{ day | date:dayTooltipFormat:timezone }}{{ day | date:dayFormat:timezone }}{{ day | date:dayLabelTooltipFormat }}{{ day | date:dayLabelFormat }}{{ day | date:dayTooltipFormat }}{{ day | date:dayFormat }}"; + var defaultTemplate = "Previous month«{{ calendar.start | date:titleFormat:timezone }}Next month»{{ day | date:dayTooltipFormat:timezone }}{{ day | date:dayFormat:timezone }}{{ day | date:dayLabelTooltipFormat }}{{ day | date:dayLabelFormat }}{{ day | date:dayTooltipFormat }}{{ day | date:dayFormat }}"; var injectCss = function () { var styleId = "calendarMdCss"; @@ -202,7 +202,8 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse" startDateOfMonth: "=?", noOfDays: "=?", clearDataCacheOnLoad: "=?", - disableFutureSelection: "=?" + disableFutureSelection: "=?", + disableSelection: "=?" }, link: function ($scope, $element, $attrs) { @@ -239,7 +240,8 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse" $scope.dayFormat = $scope.dayFormat || "d"; $scope.dayTooltipFormat = $scope.dayTooltipFormat || "fullDate"; $scope.disableFutureSelection = $scope.disableFutureSelection || false; - + $scope.disableSelection = $scope.disableSelection || false; + $scope.sameMonth = function (date) { var d = angular.copy(date); return d.getFullYear() === $scope.calendar.year && @@ -252,11 +254,6 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse" return !$scope.sameMonth(date); }; - $scope.isCurrentDay = function(date) { - var currentDate = new Date(); - return angular.equals(date.getDate(), currentDate.getDate()) && angular.equals(date.getMonth(), currentDate.getMonth()) && angular.equals(date.getFullYear(), currentDate.getFullYear()); - }; - $scope.calendarDirection = $scope.calendarDirection || "horizontal"; $scope.$watch("calendarDirection", function (val) { @@ -323,7 +320,11 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse" if($scope.disableFutureSelection && date > new Date()) { return; } - + + if($scope.disableSelection) { + return; + } + var active = angular.copy($scope.active); if (angular.isArray(active)) { var idx = dateFind(active, date); diff --git a/angular-material-calendar.min.js b/angular-material-calendar.min.js index 2c1c9ec..c4a37b7 100644 --- a/angular-material-calendar.min.js +++ b/angular-material-calendar.min.js @@ -1 +1 @@ -angular.module("materialCalendar",["ngMaterial","ngSanitize"]),angular.module("materialCalendar").constant("materialCalendar.config",{version:"0.2.13",debug:document.domain.indexOf("localhost")>-1}),angular.module("materialCalendar").config(["materialCalendar.config","$logProvider","$compileProvider",function(t,a,e){t.debug&&(a.debugEnabled(!1),e.debugInfoEnabled(!1))}]),angular.module("materialCalendar").service("materialCalendar.Calendar",[function(){function t(t,a,e){var n=new Date;this.setWeekStartsOn=function(t){var a=parseInt(t||0,10);return this.weekStartsOn=!isNaN(a)&&a>=0&&6>=a?a:0,this.weekStartsOn},this.options=angular.isObject(e)?e:{},this.year=n.getFullYear(),this.month=n.getMonth(),this.weeks=[],this.weekStartsOn=this.setWeekStartsOn(this.options.weekStartsOn),this.next=function(){return this.start.getMonth()<11?void this.init(this.start.getFullYear(),this.start.getMonth()+1):void this.init(this.start.getFullYear()+1,0)},this.prev=function(){return this.month?void this.init(this.start.getFullYear(),this.start.getMonth()-1):void this.init(this.start.getFullYear()-1,11)},this.init=function(t,a){var e=new Date;this.year=angular.isDefined(t)?t:e.getFullYear(),this.month=angular.isDefined(a)?a:e.getMonth();var n=[31,28,31,30,31,30,31,31,30,31,30,31],o=n[this.month];1===this.month&&(this.year%4===0&&this.year%100!==0||this.year%400===0)&&(o=29),this.start=new Date(this.year,this.month,1);for(var r=angular.copy(this.start);r.getDay()!==this.weekStartsOn;)r.setDate(r.getDate()-1),o++;for(;o%7!==0;)o++;this.weeks=[];for(var i=0;o>i;++i)i%7===0&&this.weeks.push([]),this.weeks[this.weeks.length-1].push(angular.copy(r)),r.setDate(r.getDate()+1)},this.init(t,a)}return t}]),angular.module("materialCalendar").service("MaterialCalendarData",[function(){function t(){this.data={},this.getDayKey=function(t){return[t.getFullYear(),t.getMonth()+1,t.getDate()].join("-")},this.setDayContent=function(t,a){this.data[this.getDayKey(t)]=a||this.data[this.getDayKey(t)]||""}}return new t}]),angular.module("materialCalendar").directive("calendarMd",["$compile","$parse","$templateRequest","$q","materialCalendar.Calendar","MaterialCalendarData",function(t,a,e,n,o,r){var i="Previous month«{{ calendar.start | date:titleFormat:timezone }}Next month»{{ day | date:dayTooltipFormat:timezone }}{{ day | date:dayFormat:timezone }}{{ day | date:dayLabelTooltipFormat }}{{ day | date:dayLabelFormat }}{{ day | date:dayTooltipFormat }}{{ day | date:dayFormat }}",d=function(){var t="calendarMdCss";if(!document.getElementById(t)){var a=document.getElementsByTagName("head")[0],e=document.createElement("style");e.type="text/css",e.id=t,e.innerHTML="calendar-md md-content>md-content.agenda>*>* :not(:first-child),calendar-md md-content>md-content.calendar>:not(:first-child)>* :last-child{overflow:hidden;text-overflow:ellipsis}calendar-md{display:block;max-height:100%}calendar-md .md-toolbar-tools h2{overflow-x:hidden;text-overflow:ellipsis;white-space:nowrap}calendar-md md-content>md-content{border:1px solid rgba(0,0,0,.12)}calendar-md md-content>md-content.agenda>*>*{border-bottom:1px solid rgba(0,0,0,.12)}calendar-md md-content>md-content.agenda>*>.disabled{color:rgba(0,0,0,.3);pointer-events:none;cursor:auto}calendar-md md-content>md-content.agenda>*>* :first-child{padding:12px;width:200px;text-align:right;color:rgba(0,0,0,.75);font-weight:100;overflow-x:hidden;text-overflow:ellipsis;white-space:nowrap}calendar-md md-content>md-content>*>*{min-width:48px}calendar-md md-content>md-content.calendar>:first-child{background:rgba(0,0,0,.02);border-bottom:1px solid rgba(0,0,0,.12);margin-right:0;min-height:36px}calendar-md md-content>md-content.calendar>:not(:first-child)>*{border-bottom:1px solid rgba(0,0,0,.12);border-right:1px solid rgba(0,0,0,.12);cursor:pointer}calendar-md md-content>md-content.calendar>:not(:first-child)>:hover{background:rgba(0,0,0,.04)}calendar-md md-content>md-content.calendar>:not(:first-child)>.disabled{color:rgba(0,0,0,.3);pointer-events:none;cursor:auto}calendar-md md-content>md-content.calendar>:not(:first-child)>.active{box-shadow:0 1px 3px 0 rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 2px 1px -1px rgba(0,0,0,.12);background:rgba(0,0,0,.02)}calendar-md md-content>md-content.calendar>:not(:first-child)>* :first-child{padding:0}",a.insertBefore(e,a.firstChild)}};return{restrict:"E",scope:{ngModel:"=?",template:"&",templateUrl:"=?",onDayClick:"=?",onPrevMonth:"=?",onNextMonth:"=?",calendarDirection:"=?",dayContent:"&?",timezone:"=?",titleFormat:"=?",dayFormat:"=?",dayLabelFormat:"=?",dayLabelTooltipFormat:"=?",dayTooltipFormat:"=?",weekStartsOn:"=?",tooltips:"&?",clearDataCacheOnLoad:"=?",disableFutureSelection:"=?"},link:function(l,c,s){d();var u=new Date,m=parseInt(s.startMonth||u.getMonth()),h=parseInt(s.startYear||u.getFullYear());l.columnWeekLayout="column",l.weekLayout="row",l.timezone=l.timezone||null,l.noCache=s.clearDataCacheOnLoad||!1,s.ngModel?(l.active=l.$parent.$eval(s.ngModel),s.ngModel&&l.$watch("$parent."+s.ngModel,function(t){l.active=t})):l.active=null,l.titleFormat=l.titleFormat||"MMMM yyyy",l.dayLabelFormat=l.dayLabelFormat||"EEE",l.dayLabelTooltipFormat=l.dayLabelTooltipFormat||"EEEE",l.dayFormat=l.dayFormat||"d",l.dayTooltipFormat=l.dayTooltipFormat||"fullDate",l.disableFutureSelection=l.disableFutureSelection||!1,l.sameMonth=function(t){var a=angular.copy(t);return a.getFullYear()===l.calendar.year&&a.getMonth()===l.calendar.month},l.isDisabled=function(t){return l.disableFutureSelection&&t>new Date?!0:!l.sameMonth(t)},l.calendarDirection=l.calendarDirection||"horizontal",l.$watch("calendarDirection",function(t){l.weekLayout="horizontal"===t?"row":"column"}),l.$watch("weekLayout",function(){h=l.calendar.year,m=l.calendar.month,k()});var g=function(t,a){(t||angular.noop)(a)},y=function(t,a){var e=-1;return angular.forEach(t,function(t,n){0>e&&angular.equals(a,t)&&(e=n)}),e};l.isActive=function(t){var a,e=angular.copy(l.active);return angular.isArray(e)?a=y(e,t)>-1:angular.equals(e.getYear(),t.getYear())&&angular.equals(e.getMonth(),t.getMonth())&&angular.equals(e.getDate(),t.getDate())&&(a=!0),a},l.prev=function(){l.calendar.prev();var t={year:l.calendar.year,month:l.calendar.month+1};w(),g(l.onPrevMonth,t)},l.next=function(){l.calendar.next();var t={year:l.calendar.year,month:l.calendar.month+1};w(),g(l.onNextMonth,t)},l.handleDayClick=function(t){if(!(l.disableFutureSelection&&t>new Date)){var e=angular.copy(l.active);if(angular.isArray(e)){var n=y(e,t);n>-1?e.splice(n,1):e.push(t)}else e=angular.equals(e,t)?null:t;l.active=e,s.ngModel&&a(s.ngModel).assign(l.$parent,angular.copy(l.active)),g(l.onDayClick,angular.copy(t))}};var p=function(a){c.html(a),t(c.contents())(l)},v=function(){return l.calendar=new o(h,m,{weekStartsOn:l.weekStartsOn||0}),l.templateUrl?e(l.templateUrl):n.resolve(l.template()||i)};l.dataService=r;var f=function(t){return l.dataService.getDayKey(t)};l.dayKey=f;var b=function(t){l.noCache?l.dataService.setDayContent(t,""):l.dataService.setDayContent(t,l.dataService.data[f(t)]||"");var a=(l.dayContent||angular.noop)(),e=(a||angular.noop)(t);angular.isObject(e)&&"function"==typeof e.success?e.success(function(a){l.dataService.setDayContent(t,a)}):angular.isObject(e)&&"function"==typeof e.then?e.then(function(a){l.dataService.setDayContent(t,a)}):l.dataService.setDayContent(t,e)},w=function(){angular.forEach(l.calendar.weeks,function(t){angular.forEach(t,b)})};window.data=l.data;var k=function(){v().then(function(t){p(t),w()})};l.$watch("weekStartsOn",v),k(),l._$$init=v,l._$$setTemplate=p,l._$$bootstrap=k}}}]); \ No newline at end of file +angular.module("materialCalendar",["ngMaterial","ngSanitize"]),angular.module("materialCalendar").constant("materialCalendar.config",{version:"0.2.13",debug:document.domain.indexOf("localhost")>-1}),angular.module("materialCalendar").config(["materialCalendar.config","$logProvider","$compileProvider",function(t,a,e){t.debug&&(a.debugEnabled(!1),e.debugInfoEnabled(!1))}]),angular.module("materialCalendar").service("materialCalendar.Calendar",[function(){function t(t,a,e){var n=new Date;this.setWeekStartsOn=function(t){var a=parseInt(t||0,10);return this.weekStartsOn=!isNaN(a)&&a>=0&&6>=a?a:0,this.weekStartsOn},this.setStartDateOfMonth=function(t){var a=parseInt(t||1,10);return this.startDateOfMonth=!isNaN(a)&&a>=1&&31>=a?a:1,this.startDateOfMonth},this.setNoOfDays=function(t){var a=parseInt(t||0,10);return this.noOfDays=!isNaN(a)&&a>0?a:0,this.noOfDays},this.options=angular.isObject(e)?e:{},this.year=n.getFullYear(),this.month=n.getMonth(),this.weeks=[],this.weekStartsOn=this.setWeekStartsOn(this.options.weekStartsOn),this.startDateOfMonth=this.setStartDateOfMonth(this.options.startDateOfMonth),this.noOfDays=this.setNoOfDays(this.options.noOfDays),this.next=function(){return this.start.getMonth()<11?void this.init(this.start.getFullYear(),this.start.getMonth()+1):void this.init(this.start.getFullYear()+1,0)},this.prev=function(){return this.month?void this.init(this.start.getFullYear(),this.start.getMonth()-1):void this.init(this.start.getFullYear()-1,11)},this.init=function(t,a){var e=new Date;this.year=angular.isDefined(t)?t:e.getFullYear(),this.month=angular.isDefined(a)?a:e.getMonth();var n=[31,28,31,30,31,30,31,31,30,31,30,31],o=n[this.month];1===this.month&&(this.year%4===0&&this.year%100!==0||this.year%400===0)&&(o=29),this.start=angular.isDefined(this.options.startDateOfMonth)?new Date(this.year,this.month,this.startDateOfMonth):new Date(this.year,this.month,1);var i=angular.copy(this.start);if(1===i.getDate())for(;i.getDay()!==this.weekStartsOn;)i.setDate(i.getDate()-1),o++;if(0!==this.noOfDays){for(;this.noOfDays%7!==0;)this.noOfDays++;o=this.noOfDays}else for(;o%7!==0;)o++;for(;o%7!==0;)o++;this.weeks=[];for(var r=0;o>r;++r)r%7===0&&this.weeks.push([]),this.weeks[this.weeks.length-1].push(angular.copy(i)),i.setDate(i.getDate()+1)},this.init(t,a)}return t}]),angular.module("materialCalendar").service("MaterialCalendarData",[function(){function t(){this.data={},this.getDayKey=function(t){return[t.getFullYear(),t.getMonth()+1,t.getDate()].join("-")},this.setDayContent=function(t,a){this.data[this.getDayKey(t)]=a||this.data[this.getDayKey(t)]||""}}return new t}]),angular.module("materialCalendar").directive("calendarMd",["$compile","$parse","$templateRequest","$q","materialCalendar.Calendar","MaterialCalendarData",function(t,a,e,n,o,i){var r="Previous month«{{ calendar.start | date:titleFormat:timezone }}Next month»{{ day | date:dayTooltipFormat:timezone }}{{ day | date:dayFormat:timezone }}{{ day | date:dayLabelTooltipFormat }}{{ day | date:dayLabelFormat }}{{ day | date:dayTooltipFormat }}{{ day | date:dayFormat }}",d=function(){var t="calendarMdCss";if(!document.getElementById(t)){var a=document.getElementsByTagName("head")[0],e=document.createElement("style");e.type="text/css",e.id=t,e.innerHTML="calendar-md md-content>md-content.agenda>*>* :not(:first-child),calendar-md md-content>md-content.calendar>:not(:first-child)>* :last-child{overflow:hidden;text-overflow:ellipsis}calendar-md{display:block;max-height:100%}calendar-md .md-toolbar-tools h2{overflow-x:hidden;text-overflow:ellipsis;white-space:nowrap}calendar-md md-content>md-content{border:1px solid rgba(0,0,0,.12)}calendar-md md-content>md-content.agenda>*>*{border-bottom:1px solid rgba(0,0,0,.12)}calendar-md md-content>md-content.agenda>*>.disabled{color:rgba(0,0,0,.3);pointer-events:none;cursor:auto}calendar-md md-content>md-content.agenda>*>* :first-child{padding:12px;width:200px;text-align:right;color:rgba(0,0,0,.75);font-weight:100;overflow-x:hidden;text-overflow:ellipsis;white-space:nowrap}calendar-md md-content>md-content>*>*{min-width:48px}calendar-md md-content>md-content.calendar>:first-child{background:rgba(0,0,0,.02);border-bottom:1px solid rgba(0,0,0,.12);margin-right:0;min-height:36px}calendar-md md-content>md-content.calendar>:not(:first-child)>*{border-bottom:1px solid rgba(0,0,0,.12);border-right:1px solid rgba(0,0,0,.12);cursor:pointer}calendar-md md-content>md-content.calendar>:not(:first-child)>:hover{background:rgba(0,0,0,.04)}calendar-md md-content>md-content.calendar>:not(:first-child)>.disabled{color:rgba(0,0,0,.3);pointer-events:none;cursor:auto}calendar-md md-content>md-content.calendar>:not(:first-child)>.active{box-shadow:0 1px 3px 0 rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 2px 1px -1px rgba(0,0,0,.12);background:rgba(0,0,0,.02)}calendar-md md-content>md-content.calendar>:not(:first-child)>* :first-child{padding:0}",a.insertBefore(e,a.firstChild)}};return{restrict:"E",scope:{ngModel:"=?",template:"&",templateUrl:"=?",onDayClick:"=?",onPrevMonth:"=?",onNextMonth:"=?",calendarDirection:"=?",dayContent:"&?",timezone:"=?",titleFormat:"=?",dayFormat:"=?",dayLabelFormat:"=?",dayLabelTooltipFormat:"=?",dayTooltipFormat:"=?",weekStartsOn:"=?",tooltips:"&?",startDateOfMonth:"=?",noOfDays:"=?",clearDataCacheOnLoad:"=?",disableFutureSelection:"=?",disableSelection:"=?"},link:function(l,s,c){d();var u=new Date,h=parseInt(c.startMonth||u.getMonth()),m=parseInt(c.startYear||u.getFullYear());l.columnWeekLayout="column",l.weekLayout="row",l.timezone=l.timezone||null,l.noCache=c.clearDataCacheOnLoad||!1,c.ngModel?(l.active=l.$parent.$eval(c.ngModel),c.ngModel&&l.$watch("$parent."+c.ngModel,function(t){l.active=t})):l.active=null,l.titleFormat=l.titleFormat||"MMMM yyyy",l.dayLabelFormat=l.dayLabelFormat||"EEE",l.dayLabelTooltipFormat=l.dayLabelTooltipFormat||"EEEE",l.dayFormat=l.dayFormat||"d",l.dayTooltipFormat=l.dayTooltipFormat||"fullDate",l.disableFutureSelection=l.disableFutureSelection||!1,l.disableSelection=l.disableSelection||!1,l.sameMonth=function(t){var a=angular.copy(t);return a.getFullYear()===l.calendar.year&&a.getMonth()===l.calendar.month},l.isDisabled=function(t,a,e){return 0!=e&&t.getDate()>=a+e?!0:l.disableFutureSelection&&t>new Date?!0:!l.sameMonth(t)},l.calendarDirection=l.calendarDirection||"horizontal",l.$watch("calendarDirection",function(t){l.weekLayout="horizontal"===t?"row":"column"}),l.$watch("weekLayout",function(){m=l.calendar.year,h=l.calendar.month,w()});var g=function(t,a){(t||angular.noop)(a)},y=function(t,a){var e=-1;return angular.forEach(t,function(t,n){0>e&&angular.equals(a,t)&&(e=n)}),e};l.isActive=function(t){var a,e=angular.copy(l.active);return angular.isArray(e)?a=y(e,t)>-1:angular.equals(e.getYear(),t.getYear())&&angular.equals(e.getMonth(),t.getMonth())&&angular.equals(e.getDate(),t.getDate())&&(a=!0),a},l.prev=function(){l.calendar.prev();var t={year:l.calendar.year,month:l.calendar.month+1};D(),g(l.onPrevMonth,t)},l.next=function(){l.calendar.next();var t={year:l.calendar.year,month:l.calendar.month+1};D(),g(l.onNextMonth,t)},l.handleDayClick=function(t){if(!(l.disableFutureSelection&&t>new Date||l.disableSelection)){var e=angular.copy(l.active);if(angular.isArray(e)){var n=y(e,t);n>-1?e.splice(n,1):e.push(t)}else e=angular.equals(e,t)?null:t;l.active=e,c.ngModel&&a(c.ngModel).assign(l.$parent,angular.copy(l.active)),g(l.onDayClick,angular.copy(t))}};var f=function(a){s.html(a),t(s.contents())(l)},p=function(){return l.calendar=new o(m,h,{weekStartsOn:l.weekStartsOn||0,startDateOfMonth:l.startDateOfMonth||1,noOfDays:l.noOfDays||0}),l.templateUrl?e(l.templateUrl):n.resolve(l.template()||r)};l.dataService=i;var v=function(t){return l.dataService.getDayKey(t)};l.dayKey=v;var b=function(t){l.noCache?l.dataService.setDayContent(t,""):l.dataService.setDayContent(t,l.dataService.data[v(t)]||"");var a=(l.dayContent||angular.noop)(),e=(a||angular.noop)(t);angular.isObject(e)&&"function"==typeof e.success?e.success(function(a){l.dataService.setDayContent(t,a)}):angular.isObject(e)&&"function"==typeof e.then?e.then(function(a){l.dataService.setDayContent(t,a)}):l.dataService.setDayContent(t,e)},D=function(){angular.forEach(l.calendar.weeks,function(t){angular.forEach(t,b)})};window.data=l.data;var w=function(){p().then(function(t){f(t),D()})};l.$watchGroup(["weekStartsOn","startDateOfMonth","noOfDays"],p),w(),l._$$init=p,l._$$setTemplate=f,l._$$bootstrap=w}}}]); \ No newline at end of file diff --git a/dist/angular-material-calendar.js b/dist/angular-material-calendar.js index 9920d4a..6a5938b 100644 --- a/dist/angular-material-calendar.js +++ b/dist/angular-material-calendar.js @@ -28,11 +28,33 @@ angular.module("materialCalendar").service("materialCalendar.Calendar", [functio return this.weekStartsOn; }; + this.setStartDateOfMonth = function (i) { + var d = parseInt(i || 1, 10); + if (!isNaN(d) && d >= 1 && d <= 31) { + this.startDateOfMonth = d; + } else { + this.startDateOfMonth = 1; + } + return this.startDateOfMonth; + }; + + this.setNoOfDays = function (i) { + var d = parseInt(i || 0, 10); + if (!isNaN(d) && d > 0 ) { + this.noOfDays = d; + } else { + this.noOfDays = 0; + } + return this.noOfDays; + }; + this.options = angular.isObject(options) ? options : {}; this.year = now.getFullYear(); this.month = now.getMonth(); this.weeks = []; this.weekStartsOn = this.setWeekStartsOn(this.options.weekStartsOn); + this.startDateOfMonth = this.setStartDateOfMonth(this.options.startDateOfMonth); + this.noOfDays = this.setNoOfDays(this.options.noOfDays); this.next = function () { if (this.start.getMonth() < 11) { @@ -68,11 +90,30 @@ angular.module("materialCalendar").service("materialCalendar.Calendar", [functio } // First day of calendar month. - this.start = new Date(this.year, this.month, 1); + if ( angular.isDefined(this.options.startDateOfMonth) ) { + this.start = new Date(this.year, this.month, this.startDateOfMonth); + } else { + this.start = new Date(this.year, this.month, 1); + } + var date = angular.copy(this.start); - while (date.getDay() !== this.weekStartsOn) { - date.setDate(date.getDate() - 1); - monthLength++; + if ( date.getDate() === 1) { + while ( date.getDay() !== this.weekStartsOn) { + date.setDate(date.getDate() - 1); + monthLength++; + } + } + + if ( this.noOfDays !== 0) { + while (this.noOfDays % 7 !== 0) { + this.noOfDays++; + } + monthLength = this.noOfDays; + } else { + // Last day of calendar month. + while (monthLength % 7 !== 0) { + monthLength++; + } } // Last day of calendar month. @@ -158,8 +199,11 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse" dayTooltipFormat: "=?", weekStartsOn: "=?", tooltips: "&?", + startDateOfMonth: "=?", + noOfDays: "=?", clearDataCacheOnLoad: "=?", - disableFutureSelection: "=?" + disableFutureSelection: "=?", + disableSelection: "=?" }, link: function ($scope, $element, $attrs) { @@ -196,14 +240,16 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse" $scope.dayFormat = $scope.dayFormat || "d"; $scope.dayTooltipFormat = $scope.dayTooltipFormat || "fullDate"; $scope.disableFutureSelection = $scope.disableFutureSelection || false; - + $scope.disableSelection = $scope.disableSelection || false; + $scope.sameMonth = function (date) { var d = angular.copy(date); return d.getFullYear() === $scope.calendar.year && d.getMonth() === $scope.calendar.month; }; - $scope.isDisabled = function (date) { + $scope.isDisabled = function (date,startDateOfMonth,noOfDays) { + if (noOfDays!=0 && date.getDate() >= (startDateOfMonth+noOfDays)) {return true;} if ($scope.disableFutureSelection && date > new Date()) { return true; } return !$scope.sameMonth(date); }; @@ -274,7 +320,11 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse" if($scope.disableFutureSelection && date > new Date()) { return; } - + + if($scope.disableSelection) { + return; + } + var active = angular.copy($scope.active); if (angular.isArray(active)) { var idx = dateFind(active, date); @@ -309,7 +359,9 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse" var init = function () { $scope.calendar = new Calendar(year, month, { - weekStartsOn: $scope.weekStartsOn || 0 + weekStartsOn: $scope.weekStartsOn || 0, + startDateOfMonth: $scope.startDateOfMonth || 1, + noOfDays: $scope.noOfDays || 0 }); // Allows fetching of dynamic templates via $templateCache. @@ -373,7 +425,7 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse" }); }; - $scope.$watch("weekStartsOn", init); + $scope.$watchGroup(["weekStartsOn","startDateOfMonth","noOfDays"], init); bootstrap(); // These are for tests, don't remove them.. diff --git a/dist/angular-material-calendar.min.js b/dist/angular-material-calendar.min.js index 2c1c9ec..c4a37b7 100644 --- a/dist/angular-material-calendar.min.js +++ b/dist/angular-material-calendar.min.js @@ -1 +1 @@ -angular.module("materialCalendar",["ngMaterial","ngSanitize"]),angular.module("materialCalendar").constant("materialCalendar.config",{version:"0.2.13",debug:document.domain.indexOf("localhost")>-1}),angular.module("materialCalendar").config(["materialCalendar.config","$logProvider","$compileProvider",function(t,a,e){t.debug&&(a.debugEnabled(!1),e.debugInfoEnabled(!1))}]),angular.module("materialCalendar").service("materialCalendar.Calendar",[function(){function t(t,a,e){var n=new Date;this.setWeekStartsOn=function(t){var a=parseInt(t||0,10);return this.weekStartsOn=!isNaN(a)&&a>=0&&6>=a?a:0,this.weekStartsOn},this.options=angular.isObject(e)?e:{},this.year=n.getFullYear(),this.month=n.getMonth(),this.weeks=[],this.weekStartsOn=this.setWeekStartsOn(this.options.weekStartsOn),this.next=function(){return this.start.getMonth()<11?void this.init(this.start.getFullYear(),this.start.getMonth()+1):void this.init(this.start.getFullYear()+1,0)},this.prev=function(){return this.month?void this.init(this.start.getFullYear(),this.start.getMonth()-1):void this.init(this.start.getFullYear()-1,11)},this.init=function(t,a){var e=new Date;this.year=angular.isDefined(t)?t:e.getFullYear(),this.month=angular.isDefined(a)?a:e.getMonth();var n=[31,28,31,30,31,30,31,31,30,31,30,31],o=n[this.month];1===this.month&&(this.year%4===0&&this.year%100!==0||this.year%400===0)&&(o=29),this.start=new Date(this.year,this.month,1);for(var r=angular.copy(this.start);r.getDay()!==this.weekStartsOn;)r.setDate(r.getDate()-1),o++;for(;o%7!==0;)o++;this.weeks=[];for(var i=0;o>i;++i)i%7===0&&this.weeks.push([]),this.weeks[this.weeks.length-1].push(angular.copy(r)),r.setDate(r.getDate()+1)},this.init(t,a)}return t}]),angular.module("materialCalendar").service("MaterialCalendarData",[function(){function t(){this.data={},this.getDayKey=function(t){return[t.getFullYear(),t.getMonth()+1,t.getDate()].join("-")},this.setDayContent=function(t,a){this.data[this.getDayKey(t)]=a||this.data[this.getDayKey(t)]||""}}return new t}]),angular.module("materialCalendar").directive("calendarMd",["$compile","$parse","$templateRequest","$q","materialCalendar.Calendar","MaterialCalendarData",function(t,a,e,n,o,r){var i="Previous month«{{ calendar.start | date:titleFormat:timezone }}Next month»{{ day | date:dayTooltipFormat:timezone }}{{ day | date:dayFormat:timezone }}{{ day | date:dayLabelTooltipFormat }}{{ day | date:dayLabelFormat }}{{ day | date:dayTooltipFormat }}{{ day | date:dayFormat }}",d=function(){var t="calendarMdCss";if(!document.getElementById(t)){var a=document.getElementsByTagName("head")[0],e=document.createElement("style");e.type="text/css",e.id=t,e.innerHTML="calendar-md md-content>md-content.agenda>*>* :not(:first-child),calendar-md md-content>md-content.calendar>:not(:first-child)>* :last-child{overflow:hidden;text-overflow:ellipsis}calendar-md{display:block;max-height:100%}calendar-md .md-toolbar-tools h2{overflow-x:hidden;text-overflow:ellipsis;white-space:nowrap}calendar-md md-content>md-content{border:1px solid rgba(0,0,0,.12)}calendar-md md-content>md-content.agenda>*>*{border-bottom:1px solid rgba(0,0,0,.12)}calendar-md md-content>md-content.agenda>*>.disabled{color:rgba(0,0,0,.3);pointer-events:none;cursor:auto}calendar-md md-content>md-content.agenda>*>* :first-child{padding:12px;width:200px;text-align:right;color:rgba(0,0,0,.75);font-weight:100;overflow-x:hidden;text-overflow:ellipsis;white-space:nowrap}calendar-md md-content>md-content>*>*{min-width:48px}calendar-md md-content>md-content.calendar>:first-child{background:rgba(0,0,0,.02);border-bottom:1px solid rgba(0,0,0,.12);margin-right:0;min-height:36px}calendar-md md-content>md-content.calendar>:not(:first-child)>*{border-bottom:1px solid rgba(0,0,0,.12);border-right:1px solid rgba(0,0,0,.12);cursor:pointer}calendar-md md-content>md-content.calendar>:not(:first-child)>:hover{background:rgba(0,0,0,.04)}calendar-md md-content>md-content.calendar>:not(:first-child)>.disabled{color:rgba(0,0,0,.3);pointer-events:none;cursor:auto}calendar-md md-content>md-content.calendar>:not(:first-child)>.active{box-shadow:0 1px 3px 0 rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 2px 1px -1px rgba(0,0,0,.12);background:rgba(0,0,0,.02)}calendar-md md-content>md-content.calendar>:not(:first-child)>* :first-child{padding:0}",a.insertBefore(e,a.firstChild)}};return{restrict:"E",scope:{ngModel:"=?",template:"&",templateUrl:"=?",onDayClick:"=?",onPrevMonth:"=?",onNextMonth:"=?",calendarDirection:"=?",dayContent:"&?",timezone:"=?",titleFormat:"=?",dayFormat:"=?",dayLabelFormat:"=?",dayLabelTooltipFormat:"=?",dayTooltipFormat:"=?",weekStartsOn:"=?",tooltips:"&?",clearDataCacheOnLoad:"=?",disableFutureSelection:"=?"},link:function(l,c,s){d();var u=new Date,m=parseInt(s.startMonth||u.getMonth()),h=parseInt(s.startYear||u.getFullYear());l.columnWeekLayout="column",l.weekLayout="row",l.timezone=l.timezone||null,l.noCache=s.clearDataCacheOnLoad||!1,s.ngModel?(l.active=l.$parent.$eval(s.ngModel),s.ngModel&&l.$watch("$parent."+s.ngModel,function(t){l.active=t})):l.active=null,l.titleFormat=l.titleFormat||"MMMM yyyy",l.dayLabelFormat=l.dayLabelFormat||"EEE",l.dayLabelTooltipFormat=l.dayLabelTooltipFormat||"EEEE",l.dayFormat=l.dayFormat||"d",l.dayTooltipFormat=l.dayTooltipFormat||"fullDate",l.disableFutureSelection=l.disableFutureSelection||!1,l.sameMonth=function(t){var a=angular.copy(t);return a.getFullYear()===l.calendar.year&&a.getMonth()===l.calendar.month},l.isDisabled=function(t){return l.disableFutureSelection&&t>new Date?!0:!l.sameMonth(t)},l.calendarDirection=l.calendarDirection||"horizontal",l.$watch("calendarDirection",function(t){l.weekLayout="horizontal"===t?"row":"column"}),l.$watch("weekLayout",function(){h=l.calendar.year,m=l.calendar.month,k()});var g=function(t,a){(t||angular.noop)(a)},y=function(t,a){var e=-1;return angular.forEach(t,function(t,n){0>e&&angular.equals(a,t)&&(e=n)}),e};l.isActive=function(t){var a,e=angular.copy(l.active);return angular.isArray(e)?a=y(e,t)>-1:angular.equals(e.getYear(),t.getYear())&&angular.equals(e.getMonth(),t.getMonth())&&angular.equals(e.getDate(),t.getDate())&&(a=!0),a},l.prev=function(){l.calendar.prev();var t={year:l.calendar.year,month:l.calendar.month+1};w(),g(l.onPrevMonth,t)},l.next=function(){l.calendar.next();var t={year:l.calendar.year,month:l.calendar.month+1};w(),g(l.onNextMonth,t)},l.handleDayClick=function(t){if(!(l.disableFutureSelection&&t>new Date)){var e=angular.copy(l.active);if(angular.isArray(e)){var n=y(e,t);n>-1?e.splice(n,1):e.push(t)}else e=angular.equals(e,t)?null:t;l.active=e,s.ngModel&&a(s.ngModel).assign(l.$parent,angular.copy(l.active)),g(l.onDayClick,angular.copy(t))}};var p=function(a){c.html(a),t(c.contents())(l)},v=function(){return l.calendar=new o(h,m,{weekStartsOn:l.weekStartsOn||0}),l.templateUrl?e(l.templateUrl):n.resolve(l.template()||i)};l.dataService=r;var f=function(t){return l.dataService.getDayKey(t)};l.dayKey=f;var b=function(t){l.noCache?l.dataService.setDayContent(t,""):l.dataService.setDayContent(t,l.dataService.data[f(t)]||"");var a=(l.dayContent||angular.noop)(),e=(a||angular.noop)(t);angular.isObject(e)&&"function"==typeof e.success?e.success(function(a){l.dataService.setDayContent(t,a)}):angular.isObject(e)&&"function"==typeof e.then?e.then(function(a){l.dataService.setDayContent(t,a)}):l.dataService.setDayContent(t,e)},w=function(){angular.forEach(l.calendar.weeks,function(t){angular.forEach(t,b)})};window.data=l.data;var k=function(){v().then(function(t){p(t),w()})};l.$watch("weekStartsOn",v),k(),l._$$init=v,l._$$setTemplate=p,l._$$bootstrap=k}}}]); \ No newline at end of file +angular.module("materialCalendar",["ngMaterial","ngSanitize"]),angular.module("materialCalendar").constant("materialCalendar.config",{version:"0.2.13",debug:document.domain.indexOf("localhost")>-1}),angular.module("materialCalendar").config(["materialCalendar.config","$logProvider","$compileProvider",function(t,a,e){t.debug&&(a.debugEnabled(!1),e.debugInfoEnabled(!1))}]),angular.module("materialCalendar").service("materialCalendar.Calendar",[function(){function t(t,a,e){var n=new Date;this.setWeekStartsOn=function(t){var a=parseInt(t||0,10);return this.weekStartsOn=!isNaN(a)&&a>=0&&6>=a?a:0,this.weekStartsOn},this.setStartDateOfMonth=function(t){var a=parseInt(t||1,10);return this.startDateOfMonth=!isNaN(a)&&a>=1&&31>=a?a:1,this.startDateOfMonth},this.setNoOfDays=function(t){var a=parseInt(t||0,10);return this.noOfDays=!isNaN(a)&&a>0?a:0,this.noOfDays},this.options=angular.isObject(e)?e:{},this.year=n.getFullYear(),this.month=n.getMonth(),this.weeks=[],this.weekStartsOn=this.setWeekStartsOn(this.options.weekStartsOn),this.startDateOfMonth=this.setStartDateOfMonth(this.options.startDateOfMonth),this.noOfDays=this.setNoOfDays(this.options.noOfDays),this.next=function(){return this.start.getMonth()<11?void this.init(this.start.getFullYear(),this.start.getMonth()+1):void this.init(this.start.getFullYear()+1,0)},this.prev=function(){return this.month?void this.init(this.start.getFullYear(),this.start.getMonth()-1):void this.init(this.start.getFullYear()-1,11)},this.init=function(t,a){var e=new Date;this.year=angular.isDefined(t)?t:e.getFullYear(),this.month=angular.isDefined(a)?a:e.getMonth();var n=[31,28,31,30,31,30,31,31,30,31,30,31],o=n[this.month];1===this.month&&(this.year%4===0&&this.year%100!==0||this.year%400===0)&&(o=29),this.start=angular.isDefined(this.options.startDateOfMonth)?new Date(this.year,this.month,this.startDateOfMonth):new Date(this.year,this.month,1);var i=angular.copy(this.start);if(1===i.getDate())for(;i.getDay()!==this.weekStartsOn;)i.setDate(i.getDate()-1),o++;if(0!==this.noOfDays){for(;this.noOfDays%7!==0;)this.noOfDays++;o=this.noOfDays}else for(;o%7!==0;)o++;for(;o%7!==0;)o++;this.weeks=[];for(var r=0;o>r;++r)r%7===0&&this.weeks.push([]),this.weeks[this.weeks.length-1].push(angular.copy(i)),i.setDate(i.getDate()+1)},this.init(t,a)}return t}]),angular.module("materialCalendar").service("MaterialCalendarData",[function(){function t(){this.data={},this.getDayKey=function(t){return[t.getFullYear(),t.getMonth()+1,t.getDate()].join("-")},this.setDayContent=function(t,a){this.data[this.getDayKey(t)]=a||this.data[this.getDayKey(t)]||""}}return new t}]),angular.module("materialCalendar").directive("calendarMd",["$compile","$parse","$templateRequest","$q","materialCalendar.Calendar","MaterialCalendarData",function(t,a,e,n,o,i){var r="Previous month«{{ calendar.start | date:titleFormat:timezone }}Next month»{{ day | date:dayTooltipFormat:timezone }}{{ day | date:dayFormat:timezone }}{{ day | date:dayLabelTooltipFormat }}{{ day | date:dayLabelFormat }}{{ day | date:dayTooltipFormat }}{{ day | date:dayFormat }}",d=function(){var t="calendarMdCss";if(!document.getElementById(t)){var a=document.getElementsByTagName("head")[0],e=document.createElement("style");e.type="text/css",e.id=t,e.innerHTML="calendar-md md-content>md-content.agenda>*>* :not(:first-child),calendar-md md-content>md-content.calendar>:not(:first-child)>* :last-child{overflow:hidden;text-overflow:ellipsis}calendar-md{display:block;max-height:100%}calendar-md .md-toolbar-tools h2{overflow-x:hidden;text-overflow:ellipsis;white-space:nowrap}calendar-md md-content>md-content{border:1px solid rgba(0,0,0,.12)}calendar-md md-content>md-content.agenda>*>*{border-bottom:1px solid rgba(0,0,0,.12)}calendar-md md-content>md-content.agenda>*>.disabled{color:rgba(0,0,0,.3);pointer-events:none;cursor:auto}calendar-md md-content>md-content.agenda>*>* :first-child{padding:12px;width:200px;text-align:right;color:rgba(0,0,0,.75);font-weight:100;overflow-x:hidden;text-overflow:ellipsis;white-space:nowrap}calendar-md md-content>md-content>*>*{min-width:48px}calendar-md md-content>md-content.calendar>:first-child{background:rgba(0,0,0,.02);border-bottom:1px solid rgba(0,0,0,.12);margin-right:0;min-height:36px}calendar-md md-content>md-content.calendar>:not(:first-child)>*{border-bottom:1px solid rgba(0,0,0,.12);border-right:1px solid rgba(0,0,0,.12);cursor:pointer}calendar-md md-content>md-content.calendar>:not(:first-child)>:hover{background:rgba(0,0,0,.04)}calendar-md md-content>md-content.calendar>:not(:first-child)>.disabled{color:rgba(0,0,0,.3);pointer-events:none;cursor:auto}calendar-md md-content>md-content.calendar>:not(:first-child)>.active{box-shadow:0 1px 3px 0 rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 2px 1px -1px rgba(0,0,0,.12);background:rgba(0,0,0,.02)}calendar-md md-content>md-content.calendar>:not(:first-child)>* :first-child{padding:0}",a.insertBefore(e,a.firstChild)}};return{restrict:"E",scope:{ngModel:"=?",template:"&",templateUrl:"=?",onDayClick:"=?",onPrevMonth:"=?",onNextMonth:"=?",calendarDirection:"=?",dayContent:"&?",timezone:"=?",titleFormat:"=?",dayFormat:"=?",dayLabelFormat:"=?",dayLabelTooltipFormat:"=?",dayTooltipFormat:"=?",weekStartsOn:"=?",tooltips:"&?",startDateOfMonth:"=?",noOfDays:"=?",clearDataCacheOnLoad:"=?",disableFutureSelection:"=?",disableSelection:"=?"},link:function(l,s,c){d();var u=new Date,h=parseInt(c.startMonth||u.getMonth()),m=parseInt(c.startYear||u.getFullYear());l.columnWeekLayout="column",l.weekLayout="row",l.timezone=l.timezone||null,l.noCache=c.clearDataCacheOnLoad||!1,c.ngModel?(l.active=l.$parent.$eval(c.ngModel),c.ngModel&&l.$watch("$parent."+c.ngModel,function(t){l.active=t})):l.active=null,l.titleFormat=l.titleFormat||"MMMM yyyy",l.dayLabelFormat=l.dayLabelFormat||"EEE",l.dayLabelTooltipFormat=l.dayLabelTooltipFormat||"EEEE",l.dayFormat=l.dayFormat||"d",l.dayTooltipFormat=l.dayTooltipFormat||"fullDate",l.disableFutureSelection=l.disableFutureSelection||!1,l.disableSelection=l.disableSelection||!1,l.sameMonth=function(t){var a=angular.copy(t);return a.getFullYear()===l.calendar.year&&a.getMonth()===l.calendar.month},l.isDisabled=function(t,a,e){return 0!=e&&t.getDate()>=a+e?!0:l.disableFutureSelection&&t>new Date?!0:!l.sameMonth(t)},l.calendarDirection=l.calendarDirection||"horizontal",l.$watch("calendarDirection",function(t){l.weekLayout="horizontal"===t?"row":"column"}),l.$watch("weekLayout",function(){m=l.calendar.year,h=l.calendar.month,w()});var g=function(t,a){(t||angular.noop)(a)},y=function(t,a){var e=-1;return angular.forEach(t,function(t,n){0>e&&angular.equals(a,t)&&(e=n)}),e};l.isActive=function(t){var a,e=angular.copy(l.active);return angular.isArray(e)?a=y(e,t)>-1:angular.equals(e.getYear(),t.getYear())&&angular.equals(e.getMonth(),t.getMonth())&&angular.equals(e.getDate(),t.getDate())&&(a=!0),a},l.prev=function(){l.calendar.prev();var t={year:l.calendar.year,month:l.calendar.month+1};D(),g(l.onPrevMonth,t)},l.next=function(){l.calendar.next();var t={year:l.calendar.year,month:l.calendar.month+1};D(),g(l.onNextMonth,t)},l.handleDayClick=function(t){if(!(l.disableFutureSelection&&t>new Date||l.disableSelection)){var e=angular.copy(l.active);if(angular.isArray(e)){var n=y(e,t);n>-1?e.splice(n,1):e.push(t)}else e=angular.equals(e,t)?null:t;l.active=e,c.ngModel&&a(c.ngModel).assign(l.$parent,angular.copy(l.active)),g(l.onDayClick,angular.copy(t))}};var f=function(a){s.html(a),t(s.contents())(l)},p=function(){return l.calendar=new o(m,h,{weekStartsOn:l.weekStartsOn||0,startDateOfMonth:l.startDateOfMonth||1,noOfDays:l.noOfDays||0}),l.templateUrl?e(l.templateUrl):n.resolve(l.template()||r)};l.dataService=i;var v=function(t){return l.dataService.getDayKey(t)};l.dayKey=v;var b=function(t){l.noCache?l.dataService.setDayContent(t,""):l.dataService.setDayContent(t,l.dataService.data[v(t)]||"");var a=(l.dayContent||angular.noop)(),e=(a||angular.noop)(t);angular.isObject(e)&&"function"==typeof e.success?e.success(function(a){l.dataService.setDayContent(t,a)}):angular.isObject(e)&&"function"==typeof e.then?e.then(function(a){l.dataService.setDayContent(t,a)}):l.dataService.setDayContent(t,e)},D=function(){angular.forEach(l.calendar.weeks,function(t){angular.forEach(t,b)})};window.data=l.data;var w=function(){p().then(function(t){f(t),D()})};l.$watchGroup(["weekStartsOn","startDateOfMonth","noOfDays"],p),w(),l._$$init=p,l._$$setTemplate=f,l._$$bootstrap=w}}}]); \ No newline at end of file diff --git a/src/angular-material-calendar.js b/src/angular-material-calendar.js index 41f648d..e0186f1 100644 --- a/src/angular-material-calendar.js +++ b/src/angular-material-calendar.js @@ -202,7 +202,8 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse" startDateOfMonth: "=?", noOfDays: "=?", clearDataCacheOnLoad: "=?", - disableFutureSelection: "=?" + disableFutureSelection: "=?", + disableSelection: "=?" }, link: function ($scope, $element, $attrs) { @@ -239,6 +240,7 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse" $scope.dayFormat = $scope.dayFormat || "d"; $scope.dayTooltipFormat = $scope.dayTooltipFormat || "fullDate"; $scope.disableFutureSelection = $scope.disableFutureSelection || false; + $scope.disableSelection = $scope.disableSelection || false; $scope.sameMonth = function (date) { var d = angular.copy(date); @@ -247,7 +249,8 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse" }; $scope.isDisabled = function (date,startDateOfMonth,noOfDays) { - if (noOfDays!=0 && date.getDate() >= (startDateOfMonth+noOfDays)) {return true;} + if (noOfDays!=0 && date.getDate() >= (startDateOfMonth+noOfDays)) { return true; } + if ($scope.disableSelection) { return true; } if ($scope.disableFutureSelection && date > new Date()) { return true; } return !$scope.sameMonth(date); }; @@ -319,6 +322,10 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse" return; } + if($scope.disableSelection) { + return; + } + var active = angular.copy($scope.active); if (angular.isArray(active)) { var idx = dateFind(active, date);