<!DOCTYPE html>
<html>
<head>
<base href="." />
<script type="text/javascript" charset="utf-8">
window.AngularVersionForThisPlunker = 'latest'
</script>
<title>angular playground</title>
<link rel="stylesheet" href="style.css" />
<script src="https://unpkg.com/core-js@2.4.1/client/shim.min.js"></script>
<script src="https://unpkg.com/zone.js/dist/zone.js"></script>
<script src="https://unpkg.com/zone.js/dist/long-stack-trace-zone.js"></script>
<script src="https://unpkg.com/reflect-metadata@0.1.3/Reflect.js"></script>
<script src="https://unpkg.com/systemjs@0.19.31/dist/system.js"></script>
<script src="config.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
</script>
</head>
<body>
<my-app>
loading...
</my-app>
</body>
</html>
/* Styles go here */
.json-formatter-dark.json-formatter-row,.json-formatter-row{font-family:monospace}.json-formatter-dark.json-formatter-row .toggler.open:after,.json-formatter-row .toggler.open:after{transform:rotate(90deg)}.json-formatter-row,.json-formatter-row a,.json-formatter-row a:hover{color:#000;text-decoration:none}.json-formatter-row .json-formatter-row{margin-left:1em}.json-formatter-row .children.empty{opacity:.5;margin-left:1em}.json-formatter-row .children.empty.object:after{content:"No properties"}.json-formatter-row .children.empty.array:after{content:"[]"}.json-formatter-row .string{color:green;white-space:pre;word-wrap:break-word}.json-formatter-row .number{color:#00f}.json-formatter-row .boolean{color:red}.json-formatter-row .null{color:#855a00}.json-formatter-row .undefined{color:#ca0b69}.json-formatter-row .function{color:#ff20ed}.json-formatter-row .date{background-color:rgba(0,0,0,.05)}.json-formatter-row .url{text-decoration:underline;color:#00f;cursor:pointer}.json-formatter-row .bracket{color:#00f}.json-formatter-row .key{color:#00008b;cursor:pointer}.json-formatter-row .constructor-name{cursor:pointer}.json-formatter-row .toggler{font-size:.8em;line-height:1.2em;vertical-align:middle;opacity:.6;cursor:pointer}.json-formatter-row .toggler:after{display:inline-block;transition:transform .1s ease-in;content:"►"}.json-formatter-row>a>.thumbnail-text{opacity:0;transition:opacity .15s ease-in;font-style:italic}.json-formatter-row:hover>a>.thumbnail-text{opacity:.6}.json-formatter-dark.json-formatter-row,.json-formatter-dark.json-formatter-row a,.json-formatter-dark.json-formatter-row a:hover{color:#fff;text-decoration:none}.json-formatter-dark.json-formatter-row .json-formatter-row{margin-left:1em}.json-formatter-dark.json-formatter-row .children.empty{opacity:.5;margin-left:1em}.json-formatter-dark.json-formatter-row .children.empty.object:after{content:"No properties"}.json-formatter-dark.json-formatter-row .children.empty.array:after{content:"[]"}.json-formatter-dark.json-formatter-row .string{color:#31f031;white-space:pre;word-wrap:break-word}.json-formatter-dark.json-formatter-row .number{color:#66c2ff}.json-formatter-dark.json-formatter-row .boolean{color:#ec4242}.json-formatter-dark.json-formatter-row .null{color:#eec97d}.json-formatter-dark.json-formatter-row .undefined{color:#ef8fbe}.json-formatter-dark.json-formatter-row .function{color:#fd48cb}.json-formatter-dark.json-formatter-row .date{background-color:rgba(255,255,255,.05)}.json-formatter-dark.json-formatter-row .url{text-decoration:underline;color:#027bff;cursor:pointer}.json-formatter-dark.json-formatter-row .bracket{color:#9494ff}.json-formatter-dark.json-formatter-row .key{color:#23a0db;cursor:pointer}.json-formatter-dark.json-formatter-row .constructor-name{cursor:pointer}.json-formatter-dark.json-formatter-row .toggler{font-size:.8em;line-height:1.2em;vertical-align:middle;opacity:.6;cursor:pointer}.json-formatter-dark.json-formatter-row .toggler:after{display:inline-block;transition:transform .1s ease-in;content:"►"}.json-formatter-dark.json-formatter-row>a>.thumbnail-text{opacity:0;transition:opacity .15s ease-in;font-style:italic}.json-formatter-dark.json-formatter-row:hover>a>.thumbnail-text{opacity:.6}
### Angular Starter Plunker - Typescript
var angularVersion;
if(window.AngularVersionForThisPlunker === 'latest'){
angularVersion = ''; //picks up latest
}
else {
angularVersion = '@' + window.AngularVersionForThisPlunker;
}
System.config({
//use typescript for compilation
transpiler: 'typescript',
//typescript compiler options
typescriptOptions: {
emitDecoratorMetadata: true
},
paths: {
'npm:': 'https://unpkg.com/'
},
//map tells the System loader where to look for things
map: {
'app': './src',
'@angular/core': 'npm:@angular/core'+ angularVersion + '/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common' + angularVersion + '/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler' + angularVersion + '/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser' + angularVersion + '/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic' + angularVersion + '/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http' + angularVersion + '/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router' + angularVersion +'/bundles/router.umd.js',
'@angular/forms': 'npm:@angular/forms' + angularVersion + '/bundles/forms.umd.js',
'@angular/animations': 'npm:@angular/animations' + angularVersion + '/bundles/animations.umd.js',
'@angular/platform-browser/animations': 'npm:@angular/platform-browser' + angularVersion + '/bundles/platform-browser-animations.umd.js',
'@angular/animations/browser': 'npm:@angular/animations' + angularVersion + '/bundles/animations-browser.umd.js',
'@angular/core/testing': 'npm:@angular/core' + angularVersion + '/bundles/core-testing.umd.js',
'@angular/common/testing': 'npm:@angular/common' + angularVersion + '/bundles/common-testing.umd.js',
'@angular/compiler/testing': 'npm:@angular/compiler' + angularVersion + '/bundles/compiler-testing.umd.js',
'@angular/platform-browser/testing': 'npm:@angular/platform-browser' + angularVersion + '/bundles/platform-browser-testing.umd.js',
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic' + angularVersion + '/bundles/platform-browser-dynamic-testing.umd.js',
'@angular/http/testing': 'npm:@angular/http' + angularVersion + '/bundles/http-testing.umd.js',
'@angular/router/testing': 'npm:@angular/router' + angularVersion + '/bundles/router-testing.umd.js',
'tslib': 'npm:tslib@1.6.1',
'rxjs': 'npm:rxjs',
'typescript': 'npm:typescript@2.2.1/lib/typescript.js'
},
//packages defines our app package
packages: {
app: {
main: './main.ts',
defaultExtension: 'ts'
},
rxjs: {
defaultExtension: 'js'
}
}
});
//main entry point
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app';
platformBrowserDynamic().bootstrapModule(AppModule)
//our root app component
import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { JsonFormatterModule } from './json-formatter/json-formatter.module';
@Component({
selector: 'my-app',
template: `
<h2>Json formatter angular2 based on https://github.com/mohsen1/json-formatter </h2>
<json-formatter [open]="true" [json]="obj"></json-formatter>
`,
})
export class App {
obj = {
numbers: [
1,
2,
3
],
boolean: true,
'null': null,
number: 123,
anObject: {
a: 'b',
c: 'd',
e: 'f\"'
},
string: 'Hello World',
url: 'https://github.com/mohsen1/json-formatter',
date: 'Sun Aug 03 2014 20:46:55 GMT-0700 (PDT)',
func: function add(a, b) {
return a + b;
}
}
}
@NgModule({
imports: [ BrowserModule, JsonFormatterModule ],
declarations: [ App ],
bootstrap: [ App ]
})
export class AppModule {}
import { NgModule } from '@angular/core';
import { JsonFormatterComponent } from './json-formatter.component';
import { CommonModule } from '@angular/common';
@NgModule({
imports: [CommonModule],
exports: [JsonFormatterComponent],
declarations: [JsonFormatterComponent],
providers: [],
})
export class JsonFormatterModule { }
import { Component, Input, OnInit } from '@angular/core';
import { getObjectName, getPreview, getType, getValuePreview } from './utils';
const JSONFormatterConfig = {
hoverPreviewEnabled: false,
hoverPreviewArrayCount: 100,
hoverPreviewFieldCount: 5
};
@Component({
selector: 'json-formatter',
template: `
<div class="json-formatter-row">
<a (click)="toggleOpen()">
<span class="toggler" [class.open]="isOpen" *ngIf="isObject"></span>
<span class="key" *ngIf="hasKey"><span class="key-text">{{key}}</span><span class="colon">:</span></span>
<span class="value">
<span *ngIf="isObject">
<span class="constructor-name">{{ constructorName }}</span>
<span *ngIf="isArray"><span class="bracket">[</span><span class="number">{{json.length}}</span><span
class="bracket">]</span></span>
</span>
<span *ngIf="!isObject" (click)="openLink(isUrl)" class="{{type}}"
[ngClass]="{date: isDate, url: isUrl}">{{parseValue(json)}}</span>
</span>
<span *ngIf="showThumbnail()" class="thumbnail-text">
{{getThumbnail()}}
</span>
</a>
<div class="children" *ngIf="keys?.length && isOpen">
<json-formatter *ngFor="let key of keys; trackBy: trackByFn" [json]="json[key]" [key]="key"
[open]="childrenOpen()"></json-formatter>
</div>
<div class="children empty object" *ngIf="isEmptyObject()"></div>
<div class="children empty array" *ngIf="!keys?.length && isOpen && isArray"></div>
</div>
`
})
export class JsonFormatterComponent implements OnInit {
@Input() json: any;
@Input() key;
@Input() open: number;
isArray;
isObject;
isUrl;
isDate;
type;
hasKey;
keys: any;
isOpen: boolean;
constructorName: string;
ngOnInit() {
this.isArray = Array.isArray(this.json);
this.isObject = this.json != null && typeof this.json === 'object';
this.type = getType(this.json);
this.hasKey = typeof this.key !== 'undefined';
this.isOpen = this.open && this.open > 0
this.constructorName = getObjectName(this.json);
if (this.isObject) {
this.keys = Object.keys(this.json).map((key) => key === '' ? '""' : key);
}
if (this.type === 'string') {
if ((new Date(this.json)).toString() !== 'Invalid Date') {
this.isDate = true;
}
if (this.json.indexOf('http') === 0) {
this.isUrl = true;
}
}
}
isEmptyObject() {
return this.keys && !this.keys.length && this.isOpen && !this.isArray;
}
toggleOpen() {
this.isOpen = !this.isOpen;
}
childrenOpen() {
return this.open > 1 ? this.open - 1 : 0;
}
openLink(isUrl) {
if (isUrl) {
window.location.href = this.json;
}
}
parseValue(value) {
return getValuePreview(this.json, value);
}
showThumbnail() {
return this.isObject && !this.isOpen;
}
getThumbnail() {
if (this.isArray) {
// if array length is greater then 100 it shows "Array[101]"
if (this.json.length > JSONFormatterConfig.hoverPreviewArrayCount) {
return 'Array[' + this.json.length + ']';
} else {
return '[' + this.json.map(getPreview).join(', ') + ']';
}
} else {
// the first five keys (like Chrome Developer Tool)
const narrowKeys = this.keys.slice(0, JSONFormatterConfig.hoverPreviewFieldCount);
// json value schematic information
const kvs = narrowKeys.map(key => key + ':' + getPreview(this.json[key]));
// if keys count greater then 5 then show ellipsis
const ellipsis = this.keys.length >= 5 ? '…' : '';
return '{' + kvs.join(', ') + ellipsis + '}';
}
}
trackByFn(i) {
return i;
}
}
export function escapeString(str) {
return str.replace('"', '\"');
}
// From http://stackoverflow.com/a/332429
export function getObjectName(object) {
if (object === undefined) {
return '';
}
if (object === null) {
return 'Object';
}
if (typeof object === 'object' && !object.constructor) {
return 'Object';
}
//ES6 default gives name to constructor
if (object.__proto__ !== undefined && object.__proto__.constructor !== undefined && object.__proto__.constructor.name !== undefined) {
return object.__proto__.constructor.name;
}
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec((object).constructor.toString());
if (results && results.length > 1) {
return results[1];
} else {
return '';
}
}
export function getType(object) {
if (object === null) { return 'null'; }
return typeof object;
}
export function getValuePreview (object, value) {
var type = getType(object);
if (type === 'null' || type === 'undefined') { return type; }
if (type === 'string') {
value = '"' + escapeString(value) + '"';
}
if (type === 'function'){
// Remove content of the function
return object.toString()
.replace(/[\r\n]/g, '')
.replace(/\{.*\}/, '') + '{…}';
}
return value;
}
export function getPreview(object) {
var value = '';
if (typeof object === 'object') {
value = getObjectName(object);
if (Array.isArray(object)) {
value += '[' + object.length + ']';
}
} else {
value = getValuePreview(object, object);
}
return value;
}