angular-holiday-planner
Version: 
A calendar for Angular 2+ focused on displaying long intervals, with an infinite scrollable view.
2 lines • 16.4 kB
JavaScript
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@angular/core"),require("dayjs"),require("dayjs/plugin/weekday"),require("dayjs/plugin/isoWeek"),require("dayjs/plugin/minMax"),require("lodash-es"),require("@angular/common")):"function"==typeof define&&define.amd?define("angular-holiday-planner",["exports","@angular/core","dayjs","dayjs/plugin/weekday","dayjs/plugin/isoWeek","dayjs/plugin/minMax","lodash-es","@angular/common"],t):t((e=e||self)["angular-holiday-planner"]={},e.ng.core,e.dayjs,e.weekday,e.isoWeek,e.minMax,e.lodashEs,e.ng.common)}(this,(function(e,t,r,a,o,n,i,s){"use strict";r=r&&Object.prototype.hasOwnProperty.call(r,"default")?r.default:r,a=a&&Object.prototype.hasOwnProperty.call(a,"default")?a.default:a,o=o&&Object.prototype.hasOwnProperty.call(o,"default")?o.default:o,n=n&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n;Object.create;function l(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],a=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&a>=e.length&&(e=void 0),{value:e&&e[a++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function c(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var a,o,n=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(a=n.next()).done;)i.push(a.value)}catch(e){o={error:e}}finally{try{a&&!a.done&&(r=n.return)&&r.call(n)}finally{if(o)throw o.error}}return i}Object.create;var d=function(){function e(){this.months=[],this.numCols=7,this.dayClick=new t.EventEmitter,this._from=r().startOf("year").add(6,"month"),this._to=r().endOf("year"),r.extend(a),r.extend(o),this.customDays={};var e=r().startOf("day");this.customDays[this.getKey(e)]="today",this.weekDayNames=this.getWeekDayNames(),this.createMonths()}return Object.defineProperty(e.prototype,"days",{set:function(e){var t,r;this._classes={};try{for(var a=l(e),o=a.next();!o.done;o=a.next()){var n=o.value,i=this.getKey(n.date),s=this.customDays[i];this._classes[i]=s?[s,n.class]:n.class}}catch(e){t={error:e}}finally{try{o&&!o.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"from",{get:function(){return this._from},set:function(e){this._from=e,this.createMonths()},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"to",{get:function(){return this._to},set:function(e){this._to=e,this.createMonths()},enumerable:!1,configurable:!0}),e.prototype.ngOnInit=function(){},e.prototype.getWeekDayNames=function(){for(var e=[],t=r().startOf("isoWeek"),a=0;a<7;a++)e.push(t.format("dd")[0]),t=t.add(1,"day");return e},e.prototype.createMonths=function(){var e=this.from;for(this.months=[];e<this.to;){var t=(7+e.day()-e.startOf("isoWeek").day())%7,r=this._createWeekCells(e,t);this.months.push(r),e=e.add(1,"month")}},e.prototype.getKey=function(e){return e.format("DDMMYYYY")},e.prototype._dateClass=function(e){var t=[],r=e.day();6!==r&&0!==r||t.push("weekend");var a=e.format("DDMMYYYY"),o=this.customDays[a];return o&&t.push(o.class),t},e.prototype._cellClicked=function(e,t){this.dayClick.emit({event:t,date:e.date})},e.prototype._createWeekCells=function(e,t){for(var r=e.daysInMonth(),a=e,o={startOf:e,firstWeekOffset:t,weeks:[[]]},n=0,i=t;n<r;n++,i++)7===i&&(o.weeks.push([]),i=0),o.weeks[o.weeks.length-1].push({date:a,value:a.date(),key:this.getKey(a),class:this._dateClass(a),weekend:6===a.day()||0===a.day()}),a=a.add(1,"day");return o},e}();d.decorators=[{type:t.Component,args:[{selector:"ahp-calendar-view",template:'<div class="year">\n    <table *ngFor="let month of months" class="month" cellspacing="0" cellpadding="0">\n        <tr class="month-title">\n            <th [attr.colspan]="numCols">{{ month.startOf.format(\'MMMM\') }}</th>\n        </tr>\n        <tr class="month-header">\n            <th *ngFor="let dayName of weekDayNames" class="cell-header">{{ dayName }}</th>\n        </tr>\n        <tr *ngFor="let row of month.weeks; let rowIndex = index">\n            <td *ngIf="rowIndex === 0 && month.firstWeekOffset" class="month-offset"\n                [attr.colspan]="month.firstWeekOffset">\n            </td>\n            <td *ngFor="let item of row; let colIndex = index" class="day cell" \n                [ngClass]="_classes[item.key]" \n                [class.weekend]="item.weekend" \n                (click)="_cellClicked(item, $event)">\n                <div class="day-content">\n                    {{ item.value }}\n                </div>\n            </td>\n        </tr>\n    </table>\n</div>',changeDetection:t.ChangeDetectionStrategy.OnPush,styles:[".day{font-weight:500;height:40px;padding:0}.day-content{align-items:center;display:flex;height:100%;justify-content:center}.day-content:hover{background-color:rgba(0,0,0,.04)}.month{flex-basis:33.3%;max-width:290px;padding:15px}.year{display:flex;flex-flow:wrap;justify-content:space-between}.cell{color:#676565;cursor:pointer}th{color:#7c7979;font-weight:400;height:1.5rem}.month-title{font-size:19px;height:32px}.month-header{-webkit-user-select:none;height:1.5rem;user-select:none}.month-offset{background-color:#f8f7f9}:host{background-color:#fafbfb}"]}]}],d.ctorParameters=function(){return[]},d.propDecorators={days:[{type:t.Input}],from:[{type:t.Input}],to:[{type:t.Input}],dayClick:[{type:t.Output}]};var h=function(e){this.template=e};h.decorators=[{type:t.Directive,args:[{selector:"[resourceViewRow]"}]}],h.ctorParameters=function(){return[{type:t.TemplateRef}]};var y=function(e){this.template=e};y.decorators=[{type:t.Directive,args:[{selector:"[resourceViewTitle]"}]}],y.ctorParameters=function(){return[{type:t.TemplateRef}]};var f=200,p=function(){function e(e,a){var o=this;this.cdr=e,this.zone=a,this.startDate=r().startOf("day"),this.sideContainerWidth="200px",this.maxDate=r().startOf("year").add(12,"month"),this.minDate=r().startOf("year").add(6,"month"),this.infiniteScroll=!0,this.customDays={},this.getClassFn=function(e){var t=e.day();if(6===t||0===t)return"weekend"},this.getHeaderClassFn=function(e){return{today:e.isSame(o._today,"day"),"start-of-month":1===e.date()}},this.getDayValueFn=function(e){return e.date()},this.getDayHeaderFn=function(e){return e.format("dd")[0]},this._classes={},this.days=[],this._rows=[],this._today=r(),this.rowClick=new t.EventEmitter,this.dayClick=new t.EventEmitter,this.headerClick=new t.EventEmitter,this.checkScrollableThresholdHit=i.debounce(this._checkScrollableThresholdHit.bind(this),250),this.updateRange=i.throttle(this._updateRange.bind(this),250),r.extend(n),this._referenceDate=this.startDate,this._scrollableLeft=-1200,this._scrollableRight=1200,this._scrollableFrom=this.positionToDate(this._scrollableLeft),this._scrollableTo=this.positionToDate(this._scrollableRight),this._scrollableLeftThreshold=this._scrollableLeft+f,this._scrollableRightThreshold=this._scrollableRight-f}return Object.defineProperty(e.prototype,"rows",{get:function(){return this._rows},set:function(e){var t,r,a,o;this._classes={};var n=[];try{for(var i=l(e),s=i.next();!s.done;s=i.next()){var c=s.value;if(this._classes[c.id]={},c.days)try{for(var d=(a=void 0,l(c.days)),h=d.next();!h.done;h=d.next()){var y=h.value,f=this.getKey(y.date);this._classes[c.id][f]=y.class}}catch(e){a={error:e}}finally{try{h&&!h.done&&(o=d.return)&&o.call(d)}finally{if(a)throw a.error}}n.push(c)}}catch(e){t={error:e}}finally{try{s&&!s.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}this._rows=n},enumerable:!1,configurable:!0}),e.prototype.createDays=function(){var e=this._scrollableFrom;this.days=[];for(var t=0;e<this._scrollableTo;){var r=this.getKey(e),a={title:this.getDayHeaderFn(e),value:this.getDayValueFn(e),key:r,date:e,headerClass:this.getHeaderClassFn(e),class:this._dateClass(e),left:t};this.days.push(a),t+=40,e=e.add(1,"day")}},e.prototype.ngAfterViewChecked=function(){console.log("view checked")},e.prototype.getKey=function(e){return e.format("DDMMYYYY")},e.prototype.ngAfterViewInit=function(){this.centerOn(this.startDate,"auto"),this.cdr.detectChanges()},e.prototype.ngOnInit=function(){var e=this;this.createDays();var t=this.scrollBody.nativeElement,r=t.scrollLeft,a=t.clientWidth;this._updateRange(r,r+a),this._referenceScrollLeft=this.dateToPosition(this._referenceDate),this.zone.runOutsideAngular((function(){e.scrollBody.nativeElement.addEventListener("scroll",e.onBodyScroll.bind(e))}))},e.prototype.centerOn=function(e,t){void 0===t&&(t="smooth");var r=this.scrollBody.nativeElement.clientWidth,a=this.dateToPosition(e);this.scrollBody.nativeElement.scrollTo({left:a+20-r/2,behavior:t})},e.prototype.onBodyScroll=function(e){var t=this.scrollBody.nativeElement,r=t.scrollLeft,a=t.clientWidth;this.scrollHeader.nativeElement.scrollLeft=r,this.checkScrollableThresholdHit(r,a),this.updateRange(r,r+a)},e.prototype._checkScrollableThresholdHit=function(e,t){e-this._referenceScrollLeft<this._scrollableLeftThreshold&&(console.debug("left threshold hit"),this._expandScrollableRange(this._scrollableLeft-400,this._scrollableRight)),e+t-this._referenceScrollLeft>this._scrollableRightThreshold&&(console.debug("right threshold hit"),this._expandScrollableRange(this._scrollableLeft,this._scrollableRight+400))},e.prototype._expandScrollableRange=function(e,t){var a=this._scrollableLeft-e;this._scrollableLeft=e,this._scrollableRight=t,this._scrollableFrom=this.minDate&&!this.infiniteScroll?r.max(this.positionToDate(this._scrollableLeft),this.minDate):this.positionToDate(this._scrollableLeft),this._scrollableTo=this.maxDate&&!this.infiniteScroll?r.min(this.positionToDate(this._scrollableRight),this.maxDate):this.positionToDate(this._scrollableRight),this._scrollableLeftThreshold=this._scrollableLeft+f,this._scrollableRightThreshold=this._scrollableRight-f,this.scrollBody.nativeElement.scrollLeft+=a,this.scrollHeader.nativeElement.scrollLeft=this.scrollBody.nativeElement.scrollLeft,this.createDays(),this.cdr.detectChanges(),this._referenceScrollLeft=this.dateToPosition(this._referenceDate)},e.prototype._updateRange=function(e,t){var r=Math.floor(e/40),a=Math.floor(t/40)-1,o=this.days[r].date,n=this.days[a].date;this.from=o,this.to=n,this.cdr.detectChanges()},e.prototype._getDateClasses=function(e,t){return(this._classes[e.id][t.key]||"")+(t.class?" "+t.class:"")},e.prototype._getHeaderClasses=function(e){console.log(1)},e.prototype._dateClass=function(e){var t=[],r=this.getKey(e),a=this.customDays[r];if(a&&t.push(a.class),this.getClassFn){var o=this.getClassFn(e);o&&(Array.isArray(o)?t.push.apply(t,function(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(c(arguments[t]));return e}(o)):t.push(o))}return t.join(" ")},e.prototype.onWindowResize=function(){var e=this.scrollBody.nativeElement,t=e.scrollLeft,r=e.clientWidth;this.checkScrollableThresholdHit(t,r),this.updateRange(t,t+r)},e.prototype.positionToDate=function(e){var t=Math.floor(e/40);return this._referenceDate.add(t,"day")},e.prototype.dateToPosition=function(e){var t=e.diff(this._scrollableFrom,"day");return this.days[t].left},e.prototype.onBodyClick=function(e){var t=e.target,r=t.closest("[data-row-id]");r&&this.rowClick.emit({event:e,row:this.rows[+r.dataset.rowId]});var a=t.closest("[data-day-id]");r&&this.dayClick.emit({event:e,row:r&&this.rows[+r.dataset.rowId],date:a&&this.days[+a.dataset.dayId].date})},e.prototype.onHeaderClick=function(e){var t=e.target;if(null!=t.dataset.dayId){var r=this.days[+t.dataset.dayId];this.headerClick.emit({event:e,date:r&&r.date}),this.centerOn(r.date)}},e.prototype.trackById=function(e,t){return t.id},e.prototype.trackByKey=function(e,t){return t.key},e}();p.decorators=[{type:t.Component,args:[{selector:"ahp-resource-view",template:'<div class="container">\n    <div class="header">\n        <ng-container *ngTemplateOutlet="titleTemplate ? titleTemplate.template : defaultTitle"></ng-container>\n    </div>\n    <div class="header">\n        <div class="side-header side" [style.width]="sideContainerWidth">\n\n        </div>\n        <div class="main-header" #scrollHeader (click)="onHeaderClick($event)">\n            <div *ngFor="let item of days; let i = index; trackBy: trackByKey" class="header-day"\n                [ngClass]="item.headerClass" [attr.data-day-id]="i">\n                {{item.title}}\n            </div>\n        </div>\n    </div>\n    <div class="body">\n        <div class="side-body side" [style.width]="sideContainerWidth">\n            <div *ngFor="let row of rows" class="row row-side card">\n                <ng-container *ngTemplateOutlet="rowTemplate ? rowTemplate.template : defaultRow; context: { $implicit: row }"></ng-container>\n            </div>\n        </div>\n        <div class="main-body" #scrollBody (click)="onBodyClick($event)">\n            <div *ngFor="let row of rows; let row_i = index; trackBy: trackById" class="row row-main" [attr.data-row-id]="row_i">\n\n                <div *ngFor="let item of days; let i = index; trackBy: trackByKey" class="main-day" \n                    [ngClass]="_getDateClasses(row, item)"\n                    [attr.data-day-id]="i">\n                    <div class="day-content">\n                        {{ item.value }}\n                    </div>\n                </div>\n\n            </div>\n        </div>\n    </div>\n</div>\n\n<ng-template #defaultTitle>\n    <div class="range" *ngIf="from != null && to != null" [style.marginLeft]="sideContainerWidth">\n        {{from | amDateFormat:\'MMM YYYY\'}} ― {{to | amDateFormat:\'MMM YYYY\'}}\n    </div>\n</ng-template>\n\n<ng-template #defaultRow let-row>\n    <img class="avatar" [src]="row.img">\n    <div class="card-content">\n        <div class="title">\n            {{row.title}}\n        </div>\n        <div class="subtitle">\n            {{row.subtitle}}\n        </div>\n    </div>\n</ng-template>',changeDetection:t.ChangeDetectionStrategy.OnPush,styles:[".container{display:flex;flex-direction:column;width:100%}.body{display:flex;flex-grow:1}.main-body{background-color:#fafbfb;flex:1 1 0;overflow:auto}.header{display:flex}.main-header{display:flex;flex:1 1 0;height:40px;overflow:hidden}.side{margin-right:35px}.header-day{align-items:center;color:#cc6799;display:flex;font-weight:500;justify-content:center;transition:background .2s ease-out}.header-day,.main-day{cursor:pointer;flex:0 0 40px}.main-day{color:#676565;height:40px}.row{align-items:center;display:flex;height:70px}.range{color:#676565;font-size:24px;padding:30px}.card .avatar{border-radius:50%;height:56px;margin-right:20px;width:56px}.card .title{color:#333;font-weight:500;margin-bottom:4px}.card .subtitle{color:#8c8c8c}.card .subtitle,.card .title{font-size:16px;letter-spacing:-.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.card-content{overflow:auto}.main-body,.main-header{-webkit-user-select:none;user-select:none}.day-content{align-items:center;display:flex;height:100%;justify-content:center}.day-content:hover{background-color:rgba(0,0,0,.04)}"]}]}],p.ctorParameters=function(){return[{type:t.ChangeDetectorRef},{type:t.NgZone}]},p.propDecorators={rows:[{type:t.Input}],startDate:[{type:t.Input}],sideContainerWidth:[{type:t.Input}],maxDate:[{type:t.Input}],minDate:[{type:t.Input}],infiniteScroll:[{type:t.Input}],customDays:[{type:t.Input}],getClassFn:[{type:t.Input}],getHeaderClassFn:[{type:t.Input}],getDayValueFn:[{type:t.Input}],getDayHeaderFn:[{type:t.Input}],scrollHeader:[{type:t.ViewChild,args:["scrollHeader",{static:!0}]}],scrollBody:[{type:t.ViewChild,args:["scrollBody",{static:!0}]}],rowTemplate:[{type:t.ContentChild,args:[h]}],titleTemplate:[{type:t.ContentChild,args:[y]}],rowClick:[{type:t.Output}],dayClick:[{type:t.Output}],headerClick:[{type:t.Output}],onWindowResize:[{type:t.HostListener,args:["window:resize",["$event"]]}]};var u=function(){function e(){}return e.prototype.transform=function(e){for(var t=[],a=1;a<arguments.length;a++)t[a-1]=arguments[a];return e?r(e).format(t[0]):""},e}();u.decorators=[{type:t.Pipe,args:[{name:"amDateFormat"}]}];var m=function(){};m.decorators=[{type:t.NgModule,args:[{declarations:[d,u,p,h,y],imports:[s.CommonModule],exports:[d,p,h,y]}]}],e.AngularHolidayPlannerModule=m,e.CalendarViewComponent=d,e.ResourceViewComponent=p,e.ResourceViewRowDirective=h,e.ResourceViewTitleDirective=y,e.ɵa=u,Object.defineProperty(e,"__esModule",{value:!0})}));
//# sourceMappingURL=angular-holiday-planner.umd.min.js.map