Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(calendar): add amCalendar pipe #6

Merged
merged 1 commit into from
Jan 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ typings
TimeAgoPipe.js
TimeAgoPipe.js.map
TimeAgoPipe.d.ts
CalendarPipe.js
CalendarPipe.js.map
CalendarPipe.d.ts
42 changes: 42 additions & 0 deletions CalendarPipe.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import 'es6-shim';
import 'es6-symbol/implement';
import 'reflect-metadata';
import * as moment from 'moment';
import {CalendarPipe} from './CalendarPipe.ts';

describe('Calendar', () => {

describe('CalendarPipe', () => {
var pipe:CalendarPipe;

beforeEach(() => {
pipe = new CalendarPipe(null);
});

describe('#support', () => {

it('should support Date objects', () => {
expect(pipe.supports(new Date())).toBe(true);
});

it('should support moment instances', () => {
expect(pipe.supports(moment())).toBe(true);
});

it('should not support string', () => {
expect(pipe.supports('foobar')).toBe(false);
});

it('should not support null', () => {
expect(pipe.supports(null)).toBe(false);
});

});

describe('#transform', () => {
it('should transform the start of the current day to "Today at 12:00 AM"', () => {
expect(pipe.transform(moment().startOf('day'))).toBe('Today at 12:00 AM');
});
});
});
});
80 changes: 80 additions & 0 deletions CalendarPipe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/* angular2-moment / v0.1.1 / (c) 2015 Uri Shaked / MIT Licence */

import {Pipe, ChangeDetectorRef, PipeTransform, EventEmitter} from 'angular2/core';
import * as moment_ from 'moment';

// under systemjs, moment is actually exported as the default export, so we account for that
const moment:moment.MomentStatic = (<any>moment_)['default'] || moment_;

@Pipe({name: 'amCalendar', pure: false})
export class CalendarPipe implements PipeTransform {

/**
* @private Internal reference counter, so we can clean up when no instances are in use
* @type {number}
*/
private static _refs: number = 0;

private static _timer: number;
private static _midnight: EventEmitter<Date>;

constructor(private _cdRef:ChangeDetectorRef) {
// using a single static timer for all instances of this pipe for performance reasons
CalendarPipe._initTimer();

CalendarPipe._refs++;

// values such as Today will need to be replaced with Yesterday after midnight,
// so make sure we subscribe to an EventEmitter that we set up to emit at midnight
CalendarPipe._midnight.subscribe(() => this._cdRef.markForCheck());
}

supports(value:any):boolean {
return value instanceof Date || moment.isMoment(value);
}

transform(value:Date | moment.Moment, args?:any[]):any {
return moment(value).calendar();
}

onDestroy():void {
if (CalendarPipe._refs > 0) {
CalendarPipe._refs--;
}

if (CalendarPipe._refs === 0) {
CalendarPipe._removeTimer();
}
}

private static _initTimer() {
// initialize the timer
if (!CalendarPipe._midnight) {
CalendarPipe._midnight = new EventEmitter();
let timeToUpdate = CalendarPipe._getMillisecondsUntilUpdate();
CalendarPipe._timer = window.setTimeout(() => {
// emit the current date
CalendarPipe._midnight.emit(new Date());

// refresh the timer
CalendarPipe._removeTimer();
CalendarPipe._initTimer();
}, timeToUpdate);
}
}

private static _removeTimer() {
if (CalendarPipe._timer) {
window.clearTimeout(CalendarPipe._timer);
CalendarPipe._timer = null;
CalendarPipe._midnight = null;
}
}

private static _getMillisecondsUntilUpdate() {
var now = moment();
var tomorrow = moment().startOf('day').add(1, 'days');
var timeToMidnight = tomorrow.valueOf() - now.valueOf();
return timeToMidnight + 1000; // 1 second after midnight
}
}
2 changes: 2 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './TimeAgoPipe';
export * from './CalendarPipe';
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@
"name": "angular2-moment",
"version": "0.1.1",
"description": "Moment.JS pipes for Angular2 (timeago and more)",
"main": "TimeAgoPipe.js",
"typings": "./TimeAgoPipe.d.ts",
"main": "index.js",
"typings": "./index.d.ts",
"files": [
"TimeAgoPipe.js",
"TimeAgoPipe.js.map",
"TimeAgoPipe.d.ts",
"TimeAgoPipe.ts",
"CalendarPipe.js",
"CalendarPipe.js.map",
"CalendarPipe.d.ts",
"CalendarPipe.ts",
"typings",
"CHANGELOG.md"
],
Expand Down
4 changes: 3 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
},
"files": [
"typings/moment/moment.d.ts",
"TimeAgoPipe.ts"
"TimeAgoPipe.ts",
"CalendarPipe.ts",
"index.ts"
],
"exclude": [
"node_modules"
Expand Down