Skip to content

Instantly share code, notes, and snippets.

@v-fedorov
Created February 23, 2017 18:42
Show Gist options
  • Save v-fedorov/945e33ffec6c7ad74133436aa23dd56c to your computer and use it in GitHub Desktop.
Save v-fedorov/945e33ffec6c7ad74133436aa23dd56c to your computer and use it in GitHub Desktop.
import { NgModule, ModuleWithProviders } from '@angular/core';
// angular
import {Injectable} from '@angular/core';
// nativescript
import {knownFolders} from 'file-system';
// libs
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {Pipe, PipeTransform, OnDestroy, ChangeDetectorRef } from '@angular/core';
@Pipe({
name: 'fonticon',
pure: false
})
export class TNSFontIconPipe implements PipeTransform, OnDestroy {
private _collectionName: string;
private _value: '';
private _iconSub: any;
constructor(private fonticon: TNSFontIconService, private _ref: ChangeDetectorRef) { }
transform(className: string, args: any[]) {
if (!this._collectionName)
this._collectionName = getCollectionName(className, args);
if (!this._value || (this.fonticon.css && this.fonticon.css[this._collectionName] && this._value !== this.fonticon.css[this._collectionName][className])) {
// only subscribe if value is changing
// if there is a subscription to iconSub, clean it
this._dispose();
this._iconSub = this.fonticon.filesLoaded.subscribe((data: any) => {
if (data && data[this._collectionName] && data[this._collectionName][className]) {
if (this._value !== data[this._collectionName][className]) {
// only markForCheck if value has changed
this._value = data[this._collectionName][className];
this._ref.markForCheck();
this._dispose();
}
}
});
}
return this._value;
}
_dispose(): void {
if (this._iconSub) {
this._iconSub.unsubscribe();
this._iconSub = undefined;
}
}
ngOnDestroy(): void {
this._dispose();
}
}
function getCollectionName(className: string, args: any[]): string {
if (args && args.length && args[0] !== null) {
return args[0];
} else if (className && className.indexOf('-') > -1) {
// derive from classname
return className.split('-')[0];
} else {
return '';
}
}
@Injectable()
export class TNSFontIconService {
public static config: any = {};
public static debug: boolean = false;
public filesLoaded: BehaviorSubject<any>;
public css: any = {}; // font icon collections containing maps of classnames to unicode
private _currentName: string; // current collection name
constructor() {
TNSFontIconService.config = {
'fa': 'font-awesome.css'
};
this.filesLoaded = new BehaviorSubject(null);
this.loadCss();
}
public loadCss(): void {
let cnt = 0;
let fontIconCollections = Object.keys(TNSFontIconService.config);
if (TNSFontIconService.debug) {
console.log(`Collections to load: ${fontIconCollections}`);
}
let initCollection = () => {
this._currentName = fontIconCollections[cnt];
this.css[this._currentName] = {};
};
let loadFiles = () => {
initCollection();
if (cnt === fontIconCollections.length) {
this.filesLoaded.next(this.css);
} else {
this.loadFile(TNSFontIconService.config[this._currentName]).then(() => {
cnt++;
loadFiles();
});
}
};
loadFiles();
}
private loadFile(path: string): Promise<any> {
if (TNSFontIconService.debug) {
console.log(`----------`);
console.log(`Loading collection '${this._currentName}' from file: ${path}`);
}
let cssFile = knownFolders.currentApp().getFile(path);
return new Promise((resolve, reject) => {
cssFile.readText().then((data) => {
this.mapCss(data);
resolve();
}, (err) => {
reject(err);
});
});
}
private mapCss(data: any): void {
let sets = data.split('}');
let cleanValue = (val) => {
let v = val.split('content:')[1].toLowerCase().replace(/\\e/, '\\ue').replace(/\\f/, '\\uf').trim().replace(/\"/g, '').replace(/;/g, '');
return v;
};
for (let set of sets) {
let pair = set.replace(/ /g, '').split(':before{');
let keyGroups = pair[0];
let keys = keyGroups.split(',');
if (pair[1]) {
let value = cleanValue(pair[1]);
for (let key of keys) {
key = key.trim().slice(1).split(':before')[0];
this.css[this._currentName][key] = String.fromCharCode(parseInt(value.substring(2), 16));
if (TNSFontIconService.debug) {
console.log(`${key}: ${value}`);
}
}
}
}
}
}
const PIPES: Array<any> = [
TNSFontIconPipe,
];
@NgModule({
declarations: PIPES,
exports: PIPES
})
export class TNSFontIconModule {
static forRoot(config?: any): ModuleWithProviders {
return {
ngModule: TNSFontIconModule,
providers: [
TNSFontIconService
]
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment