Added the sample into the repository

This commit is contained in:
ROOT\soundarapandianr 2018-03-07 17:27:15 +05:30
Коммит f6792917da
18 изменённых файлов: 2196 добавлений и 0 удалений

1
README.md Normal file
Просмотреть файл

@ -0,0 +1 @@
# Essential JS 2 for TypeScript - Loan Calculator

7
config.json Normal file
Просмотреть файл

@ -0,0 +1,7 @@
{
"sasslint": ["./styles/**/*.scss"],
"tslint": ["./src/**/*.ts"],
"styleDependency": ["ej2"],
"ts": ["./src/**/*.ts"],
"isShowCase": true
}

Двоичные данные
favicon.ico Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.4 KiB

80
gulpfile.js Normal file
Просмотреть файл

@ -0,0 +1,80 @@
var fs = require('fs');
var gulp = require('gulp');
var webpack = require('webpack');
var webpackGulp = require('webpack-stream');
/**
* Compile script files
*/
gulp.task('scripts', function(done) {
var ts = require('gulp-typescript');
var tsProject = ts.createProject('tsconfig.json', { typescript: require('typescript') });
var tsResult = gulp.src(['./src/**/*.ts', './spec/**/*.ts'], { base: '.' })
.pipe(ts(tsProject));
tsResult.js
.pipe(gulp.dest('./'))
.on('end', function() {
done();
});
});
/**
* Compile scss files
*/
gulp.task('styles', function() {
var sass = require('gulp-sass');
return gulp.src(['./styles/**/*.scss'], { base: './' })
.pipe(sass({
outputStyle: 'expanded',
includePaths: './node_modules/@syncfusion/'
}))
.pipe(gulp.dest('.'));
});
/**
* Bundle all module using webpack
*/
gulp.task('bundle', function() {
var webpackConfig = require(fs.realpathSync('./webpack.config.js'));
return gulp.src('')
.pipe(webpackGulp(webpackConfig, webpack))
.pipe(gulp.dest('.'));
});
/**
* Build ts and scss files
*/
gulp.task('build', function(done) {
var runSequence = require('run-sequence');
runSequence('scripts', 'styles', 'bundle', done);
});
/**
* Run test for samplebrowser
*/
gulp.task('test', function(done) {
var karma = require('karma');
new karma.Server({
configFile: __dirname + '/karma.conf.js',
singleRun: true,
browsers: ['ChromeHeadless'],
browserNoActivityTimeout: 30000
}, function(e) {
done(e === 0 ? null : 'karma exited with status ' + e);
}).start();
});
/**
* Load the samples
*/
gulp.task('serve', ['build'], function (done) {
var browserSync = require('browser-sync');
var bs = browserSync.create('Essential JS 2');
var options = {
server: {
baseDir: './'
},
ui: false
};
bs.init(options, done);
});

24
index.html Normal file
Просмотреть файл

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Essential JS 2 for TypeScript - Loan Calculator</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
<meta name="description" content="Essential JS 2 for TypeScript - Loan Calculator" />
<meta name="author" content="Syncfusion" />
<link rel="shortcut icon" href="favicon.ico" />
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Raleway:500,600" rel="stylesheet">
<link href="styles/styles.css" rel="stylesheet" />
<link href="styles/index.css" rel="stylesheet" />
</head>
<body>
<h2 class="header-style">Loan Calculator</h2>
<div class="container main-content" id="content"></div>
<script src="./dist/common.js"></script>
</body>
</html>

97
karma.conf.js Normal file
Просмотреть файл

@ -0,0 +1,97 @@
// Karma configuration
// Generated on Wed Oct 26 2017 10:10:05 GMT+0530 (India Standard Time)
module.exports = function (config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine-ajax', 'jasmine', 'requirejs'],
proxies: {
'/src/': '/base/src/',
'/node_modules/': '/base/node_modules/',
'/styles/': '/base/styles/'
},
// list of files / patterns to load in the browser
files: [
"test-main.js",
{ pattern: "src/**/*.*", included: false },
{ pattern: "styles/**/*.*", included: false },
{ pattern: "dist/common.js", included: true },
{ pattern: "spec/**/*.spec.js", included: false },
{ pattern: "node_modules/@syncfusion/ej2-base/**/*.js", included: false },
{ pattern: 'node_modules/es6-promise/dist/es6-promise.js', included: false },
{ pattern: "styles/index.css", included: true },
{ pattern: "node_modules/@syncfusion/ej2/material.css", included: false },
{ pattern: "index.html", included: false },
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['dots', 'html'],
// the default html configuration
htmlReporter: {
outputFile: "test-report/units.html",
pageTitle: "Unit Tests",
subPageTitle: "Asampleprojectdescription"
},
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['ChromeHeadless', 'Chrome', 'Firefox'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity,
coverageReporter: {
type: "html",
check: {
each: {
statements: 90,
branches: 90,
functions: 100,
lines: 90
}
}
}
})
}

10
license Normal file
Просмотреть файл

@ -0,0 +1,10 @@
Essential JS 2 library is available under the Syncfusion Essential Studio program, and can be licensed either under the Syncfusion Community License Program or the Syncfusion commercial license.
To be qualified for the Syncfusion Community License Program you must have a gross revenue of less than one (1) million U.S. dollars ($1,000,000.00 USD) per year and have less than five (5) developers in your organization, and agree to be bound by Syncfusions terms and conditions.
Customers who do not qualify for the community license can contact sales@syncfusion.com for commercial licensing options.
Under no circumstances can you use this product without (1) either a Community License or a commercial license and (2) without agreeing and abiding by Syncfusions license containing all terms and conditions.
The Syncfusion license that contains the terms and conditions can be found at
https://www.syncfusion.com/content/downloads/syncfusion_license.pdf

60
package.json Normal file
Просмотреть файл

@ -0,0 +1,60 @@
{
"name": "@syncfusion/ej2-ts-loan-calculator",
"version": "0.0.1",
"description": "Essential JS 2 - Loan Calculator",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
"dependencies": {
"@syncfusion/ej2-base": "*",
"@syncfusion/ej2-buttons": "*",
"@syncfusion/ej2-calendars": "*",
"@syncfusion/ej2-charts": "*",
"@syncfusion/ej2-data": "*",
"@syncfusion/ej2-grids": "*",
"@syncfusion/ej2-inputs": "*",
"@syncfusion/ej2-lists": "*",
"@syncfusion/ej2-popups": "*",
"browser-sync": "^2.23.6",
"crossroads": "^0.12.2",
"hasher": "^1.2.0"
},
"devDependencies": {
"@types/chai": "^3.4.28",
"@types/hasher": "0.0.27",
"@types/crossroads": "0.0.28",
"@types/jasmine": "^2.2.29",
"@types/jasmine-ajax": "^3.1.27",
"@types/requirejs": "^2.1.26",
"gulp": "^3.9.0",
"gulp-sass": "^3.1.0",
"gulp-print": "^2.0.1",
"gulp-tslint": "^7.0.1",
"gulp-sass-lint": "^1.1.1",
"gulp-typescript": "^2.13.0",
"tslint": "4.0.2",
"run-sequence": "2.2.0",
"typescript": "2.3.3",
"webpack": "2.5.1",
"webpack-stream": "^3.2.0"
},
"keywords": [
"ej2",
"syncfusion",
"loan-calculator",
"emi",
"emi-calculator"
],
"scripts": {
"test": "gulp ci-test",
"compile": "gulp ci-compile",
"ci-publish": "gulp publish-samples",
"build": "gulp lint && gulp build"
},
"config": {
"ghooks": {
"pre-commit": "gulp pre-commit",
"pre-push": "gulp pre-push",
"commit-msg": "gulp commit-msg"
}
}
}

45
spec/sample.spec.ts Normal file
Просмотреть файл

@ -0,0 +1,45 @@
/**
* Sample spec
*/
import { Ajax } from '@syncfusion/ej2-base';
import '../node_modules/es6-promise/dist/es6-promise';
interface MyWindow extends Window {
customError: any;
navigateSample: any;
}
declare let window: MyWindow;
describe('Showcase sample', (): void => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
beforeAll((done: Function) => {
let ajax: Ajax = new Ajax('../base/index.html', 'GET', true);
ajax.send().then((value: Object): void => {
document.body.innerHTML = document.body.innerHTML + value.toString();
require(
['../dist/common'],
(): void => {
done();
});
});
});
describe('testing -', () => {
beforeEach(() => {
window.customError = (): boolean => {
return false;
};
spyOn(window, 'customError');
window.addEventListener('error', window.customError);
});
afterEach(() => {
window.customError.calls.reset();
});
it('Initial rendering console error testing', (done: Function) => {
expect(window.customError).not.toHaveBeenCalled();
done();
});
});
});

6
src/about/about.html Normal file
Просмотреть файл

@ -0,0 +1,6 @@
<div class="row">
<div class="col-lg-12">
<h1>Sample Routing Content.</h1>
<h1>Sample Routing Content. 2</h1>
</div>
</div>

136
src/default/default.html Normal file
Просмотреть файл

@ -0,0 +1,136 @@
<div class="row left-content-wrap">
<div class="row loan-content">
<div class="left-content col-lg-12">
<div class="row form-space">
<div class="col-lg-12">
<div class="content-space">
<table>
<tr>
<td>
<label class="pricipal">Loan Amount</label>
</td>
<td>
<div class="editor-space">
<input id="principal_txt" type="tel">
</div>
</td>
</tr>
</table>
</div>
<div id="pricipal"></div>
</div>
</div>
<div class="row form-space">
<div class="col-lg-12">
<div class="content-space">
<table>
<tr>
<td>
<label class="interestrate">Interest Rate</label>
</td>
<td>
<div class="editor-space">
<input id="interest_txt">
</div>
</td>
</tr>
</table>
</div>
<div id="interestrate"></div>
</div>
</div>
<div class="row form-space">
<div class="col-lg-12">
<div class="content-space">
<table>
<tr>
<td>
<label class="loantenure">Loan Term</label>
<ul class="tenure-value" style="float: left;">
<li>
<input type="radio" id="radio1" name="tenure" value="month">
</li>
<li>
<input type="radio" id="radio2" name="tenure" value="year">
</li>
</ul>
</td>
<td>
<div class="editor-space">
<input id="loan_txt">
</div>
</td>
</tr>
</table>
</div>
<div id="loantenure"></div>
</div>
</div>
</div>
</div>
<div class="row loan-content">
<div class="col-lg-12 emi-content">
<div>
<h6 class="emi-header">Break-up of Total Payment</h6>
</div>
<div class="row">
<div class="col-lg-7">
<div id="payment_pieChart"></div>
</div>
<div class="col-lg-5 pie-content" id="pieContent">
<div>
<p><span class="pie-icon pie-principal"></span>Principal Amount</p>
<h5 id="loan_principal"></h5>
</div>
<div>
<p><span class="pie-icon pie-interest"></span>Total Interest</p>
<h5 id="loan_interest"></h5>
</div>
<div class="pie-total">
<span>
<p>Total Payment</p>
<p>(Principal + Interest)</p>
</span>
<h5 id="loan_total_payment"></h5>
</div>
</div>
</div>
<div>
<h6 class="emi-footer">Your Monthly Payment</h6>
<h1 id="loan_emi"></h1>
</div>
</div>
</div>
</div>
<div class="row top-space loan-content" style="text-align: center">
<div class="graph-text">Monthly payments starting from</div>
<div class="graph-input">
<input id='monthStarter' type="text" />
</div>
</div>
<div class="row top-space loan-content max-content">
<h6 class="center-heading">Amortization Chart</h6>
<div class="col-lg-12 graph-container">
<div id="paymentGraph" class="component-content"></div>
</div>
</div>
<div class="row top-space loan-content max-content">
<h6 class="center-heading">Amortization Schedule</h6>
<div id="scheduleGrid" class="schedule-grid"></div>
</div>
<svg style="height: 0; width: 0;">
<defs>
<linearGradient id="principal_svg" x1="0" x2="0" y1="0" y2="1">
<stop offset="0"></stop>
<stop offset="1"></stop>
</linearGradient>
<linearGradient id="interest_svg" x1="0" x2="0" y1="0" y2="1">
<stop offset="0"></stop>
<stop offset="1"></stop>
</linearGradient>
</defs>
</svg>
<script id="columntemplate" type="text/x-template">
<div class="e-icons e-icon-grightarrow e-row-toggle"></div>
<span style="padding-left: 12px;">${year}</span>
</script>

695
src/default/default.ts Normal file
Просмотреть файл

@ -0,0 +1,695 @@
/**
* Default page code.
*/
import { Slider, SliderTickRenderedEventArgs } from '@syncfusion/ej2-inputs';
import { NumericTextBox, ChangeEventArgs } from '@syncfusion/ej2-inputs';
import { RadioButton } from '@syncfusion/ej2-buttons';
import { closest, Internationalization, isNullOrUndefined as isNOU } from '@syncfusion/ej2-base';
import {
AccumulationChart, AccumulationLegend, PieSeries, AccumulationTooltip,
AccumulationDataLabel, IAxisLabelRenderEventArgs
} from '@syncfusion/ej2-charts';
import { Grid, DetailRow } from '@syncfusion/ej2-grids';
import {
Chart, LineSeries, DateTime, Legend, Tooltip, IAccLoadedEventArgs, AccumulationTheme, IAccPointRenderEventArgs,
StackingColumnSeries, Crosshair, DataLabel, ColumnSeries, IMouseEventArgs, Series
} from '@syncfusion/ej2-charts';
import { IPages, DataSketch } from '../index';
import { DatePicker } from '@syncfusion/ej2-calendars';
//creates a datepicker with decade view and navigate up to year view.
Chart.Inject(LineSeries, StackingColumnSeries, Crosshair, DataLabel, ColumnSeries, DateTime, Legend, Tooltip);
Grid.Inject(DetailRow);
AccumulationChart.Inject(AccumulationLegend, PieSeries, AccumulationTooltip, AccumulationDataLabel);
declare let window: IPages;
let pricipalObj2: Slider;
let loantenureObj: Slider;
let interestrateObj1: Slider;
let principal: NumericTextBox;
let interest: NumericTextBox;
let tenure: NumericTextBox;
let pie: AccumulationChart;
let yearValue: RadioButton;
let monthValue: RadioButton;
let yearTenure: boolean = true;
let chart: Chart;
let grid: Grid;
let emi: number;
let princ: number;
let totalPrincipalYear: number = 0;
let totalInterestYear: number = 0;
let tent: number;
let inter: number;
let dataUnits: [Object] = <[Object]>[];
let yearWiseData: [Object] = <[Object]>[];
let dateObj: Date = new Date();
let totalInterest: number = 0;
let totalAmount: number = 0;
let totalPrincipal: number = 0;
let endBalance: number;
let beginBalance: number;
let yearTotal: number = 0;
let monthNames: [string] = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'];
let datepickerObj: DatePicker;
let intl: Internationalization = new Internationalization();
let legendSettings: Object = {
textStyle: {
color: '#FFFFFF',
fontFamily: 'Raleway, sans-serif',
fontWeight: '600',
opacity: 0.62,
size: '16px',
}
};
function getCurrencyVal(value: number): string {
return intl.formatNumber(value, { format: 'C0' });
}
function renderSliderControls(): void {
pricipalObj2 = new Slider({
min: 0,
value: 300000,
max: 500000,
step: 10000,
type: 'MinRange',
ticks: { placement: 'After', largeStep: 100000, smallStep: 10000, showSmallTicks: false, format: 'c0' },
change: () => {
principal.setProperties({ value: pricipalObj2.value });
setInitValues();
},
changed: () => {
refreshUI();
},
renderedTicks: (args: SliderTickRenderedEventArgs) => {
let li: NodeListOf<Element> = args.ticksWrapper.getElementsByClassName('e-large');
for (let i: number = 0; i < li.length; ++i) {
let ele: HTMLElement = (li[i].querySelectorAll('.e-tick-value')[0] as HTMLElement);
let num: number = parseInt(ele.innerText.substring(1).replace(/,/g , ''), 10) / 1000;
ele.innerText = num === 0 ? ('' + num) : (num + 'K');
}
}
});
pricipalObj2.appendTo('#pricipal');
loantenureObj = new Slider({
min: 0,
value: 15,
max: 40,
step: 1,
type: 'MinRange',
ticks: { placement: 'After', largeStep: 10, smallStep: 1, showSmallTicks: false },
change: () => {
tenure.setProperties({ value: loantenureObj.value });
setInitValues();
},
changed: () => {
refreshUI();
}
});
loantenureObj.appendTo('#loantenure');
interestrateObj1 = new Slider({
min: 0,
value: 5.5,
max: 20,
step: .25,
type: 'MinRange',
ticks: { placement: 'After', largeStep: 5, smallStep: 1, showSmallTicks: false },
change: () => {
interest.setProperties({ value: interestrateObj1.value });
setInitValues();
},
changed: () => {
refreshUI();
}
});
interestrateObj1.appendTo('#interestrate');
}
function renderInputControls(): void {
renderSliderControls();
monthValue = new RadioButton({
label: 'Month', name: 'tenure', value: 'month',
change: () => {
yearTenure = false;
let currVal: number = (tenure.value * 12);
tenure.setProperties({
min: 12,
max: 480,
step: 12,
value: currVal
});
loantenureObj.setProperties({
min: 0,
value: currVal,
max: 480,
step: 12,
ticks: { placement: 'after', largeStep: 120, smallStep: 12, showSmallTicks: false }
});
}
});
monthValue.appendTo('#radio1');
yearValue = new RadioButton({
label: 'Year', name: 'tenure', value: 'year', checked: true,
change: () => {
yearTenure = true;
let currVal: number = (tenure.value / 12);
loantenureObj.setProperties({
min: 0,
value: currVal,
max: 40,
step: 1,
ticks: { largeStep: 10, smallStep: 1, showSmallTicks: false }
});
tenure.setProperties({
min: 1,
max: 40,
step: 1,
value: currVal
});
}
});
yearValue.appendTo('#radio2');
principal = new NumericTextBox({
min: 1000,
value: 300000,
max: 5000000,
step: 10000,
format: 'c0',
change: (args: ChangeEventArgs) => {
if (args.isInteraction) {
pricipalObj2.setProperties({ value: principal.value });
refreshUI();
}
},
width: '200px'
});
principal.appendTo('#principal_txt');
interest = new NumericTextBox({
min: 0,
value: 5.5,
format: '#.##\' %\'',
max: 20,
step: .25,
change: (args: ChangeEventArgs) => {
if (args.isInteraction) {
interestrateObj1.setProperties({ value: interest.value });
refreshUI();
}
},
width: '165px'
});
interest.appendTo('#interest_txt');
tenure = new NumericTextBox({
min: 1,
value: 15,
max: 40,
step: 1,
format: '#.##',
change: (args: ChangeEventArgs) => {
if (args.isInteraction) {
if (tenure.value) {
loantenureObj.setProperties({ value: tenure.value });
}
refreshUI();
}
},
width: '150px'
});
tenure.appendTo('#loan_txt');
}
function renderVisalComponents(): void {
pie = new AccumulationChart({
series: [
{
dataSource: [
{ 'x': 'Principal Amount', y: princ },
{ 'x': 'Interest Amount', y: ((emi * tent) - princ) }
],
radius: '80%', xName: 'x',
animation: { enable: true },
yName: 'y',
startAngle: 290,
endAngle: 290, innerRadius: '60%',
explode: true, explodeOffset: '10%', explodeIndex: 3,
}
],
pointRender: (args: IAccPointRenderEventArgs) => {
if (args.point.index) {
args.border.width = 7;
args.fill = 'url(#interest_svg)';
} else {
args.border.width = 7;
args.border.color = '#162036';
args.fill = 'url(#principal_svg)';
}
},
enableSmartLabels: true,
legendSettings: {
visible: false,
},
height: '365px',
width: '100%',
tooltip: { enable: false },
load: (args: IAccLoadedEventArgs) => {
let selectedTheme: string = location.hash.split('/')[1];
selectedTheme = selectedTheme ? selectedTheme : 'Material';
args.accumulation.theme = <AccumulationTheme>(selectedTheme.charAt(0).toUpperCase() + selectedTheme.slice(1));
},
border: '#27304c',
background: '#27304c'
});
pie.appendTo('#payment_pieChart');
updateChart();
chart.appendTo('#paymentGraph');
grid = new Grid({
dataSource: [],
columns: [
{ field: 'year', headerText: 'Year', minWidth: '80px', textAlign: 'Center', template: '#columntemplate' },
{
field: 'yearTotal', format: 'C0',
hideAtMedia: '(min-width: 480px)', headerText: 'Payment', minWidth: '120px', textAlign: 'Center'
},
{ field: 'yearPrincipal', format: 'C0', headerText: 'Principal Paid', minWidth: '120px', textAlign: 'Center' },
{ field: 'yearInterest', format: 'C0', headerText: 'Interest Paid', minWidth: '120px', textAlign: 'Center' },
{ field: 'endingBalance', format: 'C0', headerText: 'Balance', minWidth: '80px', textAlign: 'Center' }
],
width: '100%',
childGrid: {
},
});
grid.appendTo('#scheduleGrid');
(grid.element as HTMLElement).addEventListener('click', (args: MouseEvent) => {
let target: Element = args.target as Element;
if (target.classList.contains('e-row-toggle') || target.parentElement.querySelector('.e-row-toggle')) {
target = target.parentElement.querySelector('.e-row-toggle') ? target.parentElement.querySelector('.e-row-toggle') : target;
if (target.classList.contains('e-icon-gdownarrow')) {
target.classList.remove('e-icon-gdownarrow');
target.classList.add('e-icon-grightarrow');
grid.detailRowModule.collapse(parseInt((closest(target, 'tr') as HTMLElement).getAttribute('aria-rowindex'), 10));
} else {
target.classList.remove('e-icon-grightarrow');
target.classList.add('e-icon-gdownarrow');
grid.detailRowModule.expand(parseInt((closest(target, 'tr') as HTMLElement).getAttribute('aria-rowindex'), 10));
}
}
});
}
/* tslint:disable */
function childCreated(args: any): void {
this.getHeaderContent().style.display = 'none';
this.element.style.display = 'none';
}
function childDataBound(args: any): void {
this.element.style.display = '';
}
/* tslint:enable */
function updateChart(): void {
chart = new Chart({
primaryXAxis: {
title: 'Years',
valueType: 'DateTime',
labelFormat: 'y',
intervalType: 'Years',
majorGridLines: { width: 0 },
minorGridLines: { width: 0 },
majorTickLines: { width: 0 },
minorTickLines: { width: 0 },
lineStyle: { width: 1, dashArray: '2', color: 'rgba(255,255,255,0.2)' },
labelStyle: {
color: '#989CA9',
fontFamily: 'Roboto',
fontWeight: '400',
size: '12px',
},
titleStyle: {
color: '#FFFFFF',
fontFamily: 'Raleway, sans-serif',
fontWeight: '600',
opacity: 0.62,
size: '16px',
}
},
primaryYAxis: {
title: 'Balance',
labelFormat: 'c0',
rangePadding: 'None',
lineStyle: { width: 0 },
majorTickLines: { width: 0 },
majorGridLines: { width: 1, dashArray: '2', color: 'rgba(255,255,255,0.2)' },
minorGridLines: { width: 0 },
minorTickLines: { width: 0 },
labelStyle: {
color: '#989CA9',
fontFamily: 'Roboto',
fontWeight: '400',
size: '16px',
},
titleStyle: {
color: '#FFFFFF',
fontFamily: 'Raleway, sans-serif',
fontWeight: '600',
opacity: 0.62,
size: '16px',
}
},
axes: [{
majorGridLines: { width: 0 },
minorGridLines: { width: 0 },
majorTickLines: { width: 0 },
minorTickLines: { width: 0 },
rowIndex: 0, opposedPosition: true,
lineStyle: { width: 0 },
name: 'yAxis',
title: 'Payment',
labelFormat: 'c0',
labelStyle: {
color: '#989CA9',
fontFamily: 'Roboto',
fontWeight: '400',
size: '16px',
},
titleStyle: {
color: '#FFFFFF',
fontFamily: 'Raleway, sans-serif',
fontWeight: '600',
opacity: 0.62,
size: '16px',
}
}],
chartMouseUp: (args: IMouseEventArgs) => {
onChartMouseUp(args);
},
tooltip: {
enable: true, shared: true,
format: '${series.name} : ${point.y}',
header: '<b>${point.x}<b>',
fill: '#FFFFFF',
opacity: 1,
textStyle: {
color: '#555555',
fontFamily: 'Roboto',
size: '12px',
fontWeight: '400',
},
},
chartArea: {
border: {
width: 0
}
},
height: '500px',
palettes: ['#FB6589', '#3AC8DC', '#FFFFFF'],
legendSettings: legendSettings, useGroupingSeparator: true,
border: '#27304c', background: '#27304c',
axisLabelRender: axisLabelRender
});
}
function onChartMouseUp(args: IMouseEventArgs): void {
if (args.target.indexOf('_chart_legend_') > -1 && (args.target.indexOf('shape') > -1 || args.target.indexOf('text') > -1)) {
let id: string[] = [args.target];
id = (args.target.indexOf('shape') > -1) ? id[0].split('chart_legend_shape_') : id[0].split('chart_legend_text_');
let index: number = parseInt(id[1], 10);
let series: Series = chart.visibleSeries[index];
let yName: string = series.yAxisName;
let ySName: string;
let visibility: boolean = false;
if (series.visible) {
for (let i: number = 0, len: number = chart.series.length; i < len; i++) {
ySName = chart.series[i].yAxisName;
if (len === 1 || (chart.series[i].visible &&
(<Series>chart.series[i]).index !== series.index && yName === ySName)) {
visibility = true;
}
}
series.yAxis.visible = visibility;
} else {
series.yAxis.visible = true;
}
}
}
function axisLabelRender(args: IAxisLabelRenderEventArgs): void {
if (window.innerWidth < 576) {
if (args.axis.name === 'primaryYAxis' || args.axis.name === 'yAxis') {
let value: number = Number(args.value) / 1000;
args.text = value === 0 ? String(value) : (String(value) + 'K');
}
}
}
function refreshUI1(): void {
setInitValues();
let interestPercent: number = parseFloat((Math.round((emi * tent) - princ) / Math.round((emi * tent)) * 100).toFixed(2));
pie.setProperties({
series: [
{
dataSource: [
{
'x': 'Principal Amount',
y: princ,
text: parseFloat(((princ) / Math.round((emi * tent)) * 100).toFixed(2)) + '%'
},
{
'x': 'Interest Amount',
y: (tent ? Math.round((emi * tent) - princ) : 0),
text: interestPercent ? interestPercent + '%' : ' '
}
],
radius: '80%', xName: 'x',
animation: { enable: true },
yName: 'y',
startAngle: 290,
endAngle: 290, innerRadius: '60%',
explode: true, explodeOffset: '10%', explodeIndex: 3
}
],
});
pie.refresh();
}
function refreshUI(): void {
refreshUI1();
calRangeValues();
renderControls();
chart.refresh();
grid.refresh();
}
function setInitValues(): void {
emi = calculateEMI();
princ = principal.value;
tent = yearTenure ? (tenure.value * 12) : tenure.value;
dataUnits = <[Object]>[];
yearWiseData = <[Object]>[];
dateObj = new Date(datepickerObj.value.getTime());
totalInterest = 0;
totalAmount = 0;
totalPrincipal = 0;
totalPrincipalYear = 0;
totalInterestYear = 0;
document.getElementById('loan_emi').innerHTML = getCurrencyVal(tent ? Math.round(emi) : 0);
document.getElementById('loan_interest').innerHTML = getCurrencyVal(tent ? Math.round((emi * tent) - princ) : 0);
document.getElementById('loan_total_payment').innerHTML = getCurrencyVal(tent ? Math.round((emi * tent)) : 0);
document.getElementById('loan_principal').innerHTML = getCurrencyVal(princ);
}
function calRangeValues(): void {
for (let i: number = 0; i < tent; i++) {
inter = getInterest ? (princ * getInterest()) : princ;
totalInterest += inter;
totalAmount += emi;
totalPrincipal += parseFloat((emi - inter).toFixed(2));
endBalance = princ - (emi - inter);
yearTotal += emi;
totalPrincipalYear += parseFloat((emi - inter).toFixed(2));
totalInterestYear += inter;
dataUnits.push({
month: monthNames[dateObj.getMonth()],
index: (i + 1),
totalInterest: Math.round(totalInterest),
totalAmount: totalAmount,
emi: Math.round(emi),
year: dateObj.getFullYear(),
beginningBalance: Math.round(princ),
interest: Math.round(inter),
pricipalPaid: Math.round((emi - inter)),
endingBalance: Math.round(endBalance)
});
if (i === 0 || dateObj.getMonth() === 0) {
beginBalance = princ;
}
if (dateObj.getMonth() === 11 || (i === tent - 1)) {
yearWiseData.push({
beginningBalance: Math.round(beginBalance),
totalInterest: Math.round(totalInterest),
totalPrincipal: Math.round(totalPrincipal),
totalAmount: Math.round(totalAmount),
yearTotal: Math.round(yearTotal),
endingBalance: Math.round(endBalance),
yearN: new Date(dateObj.getFullYear(), 0, 1),
year: dateObj.getFullYear(),
yearPrincipal: totalPrincipalYear,
yearInterest: totalInterestYear
});
yearTotal = 0;
totalPrincipalYear = 0;
totalInterestYear = 0;
}
princ = endBalance;
if (i < tent - 1) {
dateObj.setMonth(dateObj.getMonth() + 1);
}
}
}
function renderControls(): void {
grid.setProperties({
dataSource: yearWiseData, childGrid: {
created: childCreated,
dataBound: childDataBound,
queryString: 'year',
columns: [
{ field: 'month', headerText: 'Month', textAlign: 'center', minWidth: '80px' },
{
field: 'emi', format: 'C0',
hideAtMedia: '(min-width: 480px)', headerText: 'Payment', minWidth: '80px', textAlign: 'center'
},
{ field: 'pricipalPaid', format: 'C0', headerText: 'Principal Paid', minWidth: '80px', textAlign: 'center' },
{ field: 'interest', format: 'C0', headerText: 'Interest Paid', minWidth: '80px', textAlign: 'center' },
{ field: 'endingBalance', format: 'C0', headerText: 'Balance', minWidth: '80px', textAlign: 'center' }
],
dataSource: dataUnits
}
});
chart.setProperties({
//Initializing Chart Series
enableSideBySidePlacement: false,
series: [
// {
// type: 'Column',
// columnWidth: 0.7,
// dataSource: yearWiseData,
// xName: 'yearN', width: 2, marker: {
// visible: true,
// width: 10,
// height: 10,
// },
// yName: 'yearTotal', name: 'Total Amount Paid', yAxisName: 'yAxis',
// },
{
type: 'StackingColumn',
columnWidth: 0.425,
dataSource: yearWiseData,
xName: 'yearN', width: 2, marker: {
visible: true,
width: 10,
height: 10,
},
yName: 'yearPrincipal', name: 'Principal Paid', yAxisName: 'yAxis'
},
{
type: 'StackingColumn',
columnWidth: 0.425,
dataSource: yearWiseData,
xName: 'yearN', width: 2, marker: {
visible: true,
width: 10,
height: 10,
},
yName: 'yearInterest', name: 'Interest Paid', yAxisName: 'yAxis'
},
{
type: 'Line',
dataSource: yearWiseData,
xName: 'yearN', width: 2, marker: {
visible: true,
width: 10,
height: 10,
fill: '#60448D',
},
yName: 'endingBalance', name: 'Balance',
},
]
});
}
function getInterest(): number {
return interest.value ? parseFloat('' + interest.value / 12 / 100) : 0;
}
function calculateEMI(): number {
let interestValue: number = getInterest();
let tent: number = yearTenure ? (tenure.value * 12) : tenure.value;
if (interestValue) {
return principal.value * interestValue *
(Math.pow((1 + interestValue), tent)) / ((Math.pow((1 + interestValue), tent)) - 1);
}
return principal.value / tent;
}
function dateChanged(): void {
if (isNOU(datepickerObj.value)) {
datepickerObj.setProperties({ value: new Date() });
} else {
refreshUI();
}
}
window.default = () => {
renderInputControls();
datepickerObj = new DatePicker({
start: 'Year',
//sets the depth
depth: 'Year',
// sets the placeholder
placeholder: 'Enter date',
format: 'MMM yyy',
value: new Date(),
change: dateChanged,
showClearButton: false,
width: '250px',
strictMode: true,
showTodayButton: false
});
datepickerObj.appendTo('#monthStarter');
emi = calculateEMI();
princ = principal.value;
tent = yearTenure ? (tenure.value * 12) : tenure.value;
renderVisalComponents();
dataUnits = <[Object]>[];
yearWiseData = <[Object]>[];
dateObj = new Date();
totalInterest = 0;
totalAmount = 0;
totalPrincipal = 0;
refreshUI();
window.destroy = () => {
destroyComponents();
window.destroy = null;
};
};
function destroyComponents(): void {
pricipalObj2.destroy();
loantenureObj.destroy();
interestrateObj1.destroy();
principal.destroy();
interest.destroy();
tenure.destroy();
pie.destroy();
chart.destroy();
grid.destroy();
yearValue.destroy();
monthValue.destroy();
datepickerObj.destroy();
}
window.getDataState = () => {
let data: DataSketch = <DataSketch>{};
data.dataUnits = dataUnits;
data.yearWiseData = yearWiseData;
return data;
};

47
src/index.ts Normal file
Просмотреть файл

@ -0,0 +1,47 @@
/**
* Loan Calculator Application.
*/
import { addRoute, parse } from 'crossroads';
import { Ajax } from '@syncfusion/ej2-base';
import * as hasher from 'hasher';
declare let window: IPages;
routeDefault();
addRoute('/about', () => {
let ajaxHTML: Ajax = new Ajax('src/about/about.html', 'GET', true);
ajaxHTML.send().then((value: Object): void => {
document.getElementById('content').innerHTML = value.toString();
if (window.destroy) {
window.destroy();
}
});
});
addRoute('/default', () => {
let ajaxHTML: Ajax = new Ajax('src/default/default.html', 'GET', true);
ajaxHTML.send().then((value: Object): void => {
document.getElementById('content').innerHTML = value.toString();
window.default();
});
});
hasher.initialized.add((h: string) => {
parse(h);
});
hasher.changed.add((h: string) => {
parse(h);
});
hasher.init();
function routeDefault(): void {
addRoute('', () => {
window.location.href = '#/default';
});
}
export interface IPages extends Window {
default: () => void;
destroy: () => void;
about: () => void;
getDataState: () => DataSketch;
}
export interface DataSketch {
dataUnits: [object];
yearWiseData: [object];
}

894
styles/index.scss Normal file
Просмотреть файл

@ -0,0 +1,894 @@
//sass-lint:disable-all
$border-color: #e4e2e2;
$bg-color: #fbfbfb;
$body-bg-color: rgb(22, 32, 54);
$header-bg-color: #27304c;
$header-font-color: rgb(255, 255, 255);
$input-bg-color: #3A4360;
$input-font-color: #fff;
$input-icon-color: #95979c;
$input-border-color: #475274;
$main-bg-color: #27304c;
$text-color: #E7E7E7;
$text-color1: #989CA9;
$text-color2: #F5F5F5;
$header-color: #4a4a4a 100%;
$range-color: #3B9ED4;
$slider-color: #20273E;
$row-bg-color: #27304c;
$altrow-bg-color: #313B5A;
$row-font-color: #fff;
$hover-color: #404D75;
$active-color: #5B6BC0;
$principal-color: linear-gradient(#3AC8DC, #5B6BC0);
$interest-color: linear-gradient(#F3A55B, #FB6589);
$tick-color: #ABABAB;
@mixin Raleway-600 {
font-family: 'Raleway', sans-serif;
font-weight: 600;
}
@mixin Raleway-500 {
font-family: 'Raleway', sans-serif;
font-weight: 500;
}
@mixin Raleway-400 {
font-family: 'Raleway', sans-serif;
font-weight: 500;
}
@mixin Roboto-400 {
font-family: "Roboto";
font-weight: 400;
}
@mixin Roboto-500 {
font-family: "Roboto";
font-weight: 500;
}
.content-space {
display: block;
margin-top: 25px;
margin-bottom: 25px;
width: 100%;
table {
width: 100%;
}
label {
float: left;
margin-top: 6px;
color: $text-color;
font-size: 16px;
@include Raleway-400();
}
}
.editor-space {
display: flex;
justify-content: left;
float: right;
}
.form-space {
margin-bottom: 25px;
&:not(:first-child) {
margin-top: 25px;
}
}
.navbar {
border-radius: 0;
}
.component-content {
border-radius: 3px;
height: 300px;
}
.parent {
min-height: 85px;
position: relative;
text-align: center;
}
.child {
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
}
.top-space {
margin-top: 30px;
margin-bottom: 15px;
h6 {
position: relative;
}
}
// .emi-content > div {
// background-color: $bg-color;
// }
.emi-content {
max-width: 634px;
max-height: 660px;
margin: 30px 0 25px 0;
padding: 0 44px;
h6 {
@include Raleway-500();
text-align: center;
}
.emi-header {
font-size: 20px;
color: $text-color;
letter-spacing: 0.7px;
line-height: 29px;
}
.emi-footer {
font-size: 18px;
color: $text-color1;
margin-top: 5px;
text-align: center;
}
h1 {
color: $text-color2;
font-size: 32px;
@include Roboto-500();
text-align: center;
}
> div {
> h6 {
text-align: left;
}
}
}
.top-margin {
margin-top: 10px;
}
.bottom-margin {
margin-bottom: 35px;
}
.pie-content {
height: 100%;
padding: 0;
p {
text-align: center;
font-size: 15px;
@include Raleway-400();
color: $text-color1;
}
.pie-icon {
height: 21px;
width: 21px;
display: inline-block;
border-radius: 10px;
margin: 0 14px 0 0;
vertical-align: text-top;
&.pie-principal {
background: $principal-color;
}
&.pie-interest {
background: $interest-color;
}
}
h5 {
font-size: 18px;
@include Roboto-500();
color: $text-color2;
padding: 5px 0 10px;
text-align: center;
}
> div {
margin: 35px 0;
&:first-child {
margin-top: 43px;
}
&.pie-total {
p:first-child {
margin-bottom: 0;
}
p + p {
font-size: 14px;
letter-spacing: 1px;
}
}
}
}
.center-heading {
padding: 10px;
font-size: 20px;
text-align: center;
font-weight: 500;
}
.border-set {
border: 1px solid $border-color;
}
.tenure-value {
display: flex;
padding: 4px 5px 4px 10px;
position: relative;
li {
float: left;
}
.e-radio {
& + label {
&::before {
height: 20px;
width: 20px;
border-width: 2px;
}
&::before, &:hover::before {
border-color: $range-color;
background-color: $input-bg-color;
}
&::after, &:hover::after {
background-color: $range-color;
}
.e-label {
color: $text-color;
font-size: 16px;
@include Raleway-500()
}
}
&:focus + label {
&::before {
border-color: $range-color;
background-color: $input-bg-color;
}
&::after{
background-color: $range-color;
}
}
}
>li {
padding-left: 10px;
}
}
.graph-container {
height: 520px;
padding: 0 33px;
}
li {
list-style: none;
}
.border-unset-left {
border-left: 0;
}
.border-unset-right {
border-right: 0;
}
.main-content {
margin-top: 40px;
max-width: 1300px;
.loan-content {
background-color: $main-bg-color;
color: $text-color;
}
.e-slider-container {
.e-scale {
color: $tick-color;
.e-tick {
&.e-large {
top: 14px;
}
.e-tick-value {
@include Roboto-400();
font-size: 13px;
}
}
}
.e-slider {
.e-slider-track {
background: $slider-color;
border-color: $slider-color;
}
.e-handle {
height: 26px;
width: 26px;
top: calc(50% - 13px);
margin-left: -13px;
&::before {
content: '';
background: $range-color;
width: 14px;
height: 14px;
position: absolute;
border-radius: 16px;
top: 5px;
left: 5px;
}
}
.e-range {
background-color: $range-color;
top: calc(50% - 5px);
}
& .e-slider-track, & .e-range {
height: 12px;
}
& .e-handle, & .e-slider-track, & .e-range {
border-radius: 15px;
}
}
}
.e-input-group.e-control-wrapper {
&:not(.e-success):not(.e-warning):not(.e-error) {
border-color: $input-border-color;
background: $input-bg-color;
}
&:not(.e-disabled):active:not(.e-success):not(.e-warning):not(.e-error):not(.e-input-focus) {
border-color: $hover-color;
}
.e-input-group-icon {
background: $input-bg-color;
color: $input-icon-color;
border-color: $input-border-color;
&:hover {
background: $hover-color;
color: $input-icon-color;
}
}
.e-spin-down {
border-right-width: 0;
}
input.e-input {
@include Roboto-400();
font-size: 16px;
height: 38px;
background-color: $input-bg-color;
color: $input-font-color;
}
}
.graph-text {
color: $text-color;
font-size: 20px;
@include Raleway-500();
letter-spacing: 0.7px;
margin: 0 22px;
display: inline-block;
vertical-align: middle;
}
.graph-input {
display: inline-block;
margin: 34px 22px;
}
.e-grid {
border-color: $main-bg-color;
border-radius: 0;
.e-row {
cursor: pointer;
}
.e-gridheader {
border-width: 0;
}
.e-icon-grightarrow, .e-icon-gdownarrow {
width: 11px;
height: 11px;
border: 1px solid #fff;
margin: auto;
text-indent: 0;
&::before {
position: absolute;
font-size: 13px;
}
}
.e-icon-grightarrow::before {
content: '+';
margin: -4px 0 0 -4px;
}
.e-icon-gdownarrow::before {
content: '-';
margin: -6px 0 0 -2px;
}
.e-headercelldiv {
font-size: 14px;
height: 55px;
line-height: 55px;
@include Raleway-400();
white-space: normal;
}
& .e-columnheader {
background: linear-gradient(-90deg, #5B6BC0, #3AC8DC);
}
& .e-headercell, & .e-detailheadercell {
background: transparent;
color: #fff;
}
& .e-rowcell, & .e-detailrowcollapse, & .e-detailrowexpand, & .e-detailindentcell, & .e-detailrow .e-altrow .e-rowcell {
background: $row-bg-color;
border-width: 0;
font-size: 13px;
@include Roboto-400();
}
.e-altrow {
& .e-rowcell, & .e-detailrowcollapse, & .e-detailrowexpand {
background: $altrow-bg-color;
}
}
& .e-icons, & .e-rowcell, & .e-detailrowcollapse, & .e-detailrowexpand {
color: $row-font-color;
}
.e-detailcell {
padding: 0;
border-width: 0;
}
&.e-gridhover tr[role='row'] {
&:not(.e-editedrow):hover .e-rowcell:not(.e-cellselectionbackground), &:hover .e-detailrowcollapse:not(.e-cellselectionbackground), &:hover .e-detailrowexpand:not(.e-cellselectionbackground) {
&:not(.e-active):not(.e-updatedtd):not(.e-indentcell) {
background: $hover-color;
}
}
}
& [aria-selected] + tr .e-detailindentcell {
border-width: 0;
}
}
}
#control-container {
padding: 0px !important;
}
#principal_svg stop {
stop-color: #3AC8DC;
}
#principal_svg stop[offset="0"] {
stop-color: #3AC8DC;
}
#principal_svg stop[offset="1"] {
stop-color: #5B6BC0;
}
#interest_svg stop {
stop-color: #F3A55B;
}
#interest_svg stop[offset="0"] {
stop-color: #e97c11;
}
#interest_svg stop[offset="1"] {
stop-color: #FB6589;
}
.navbar-right {
float: right;
}
.navbar-header {
float: left;
}
.flex-container {
display: flex;
flex-wrap: wrap;
.col-lg-4 {
width: 33.33333333%;
}
@media (max-width: 500px) {
.col-lg-4 {
width: 100%;
}
}
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 600;
}
body {
background-color: $body-bg-color;
color: $text-color;
}
.left-content {
background-color: $main-bg-color;
max-height: 660px;
margin: 25px 0;
padding: 0 44px;
border-right: 1px solid $input-border-color;
}
.header-style {
background: $header-bg-color;
color: $header-font-color;
margin: 0;
padding: 15px;
text-align: center;
text-transform: uppercase;
font-size: 26px;
@include Raleway-500();
}
.margin-setter {
margin: 35px;
}
.start-setter {
margin: 17px 0;
}
.e-datepicker.e-popup-wrapper {
border-color: $input-border-color;
}
.e-datepicker .e-calendar {
background-color: $input-bg-color;
}
.e-calendar .e-header .e-title, .e-calendar .e-content span, .e-calendar .e-header.e-decade .e-title,
.e-calendar .e-header .e-title:hover {
color: $input-font-color;
}
.e-calendar .e-header .e-icon-container span, .e-calendar .e-header .e-prev:hover > span, .e-calendar .e-header .e-next:hover > span,
.e-calendar .e-header button.e-prev:active span, .e-calendar .e-header button.e-next:active span {
color: $input-icon-color;
}
.e-calendar .e-content td.e-selected span.e-day, .e-calendar .e-header .e-prev:active, .e-calendar .e-header .e-next:active {
background: $active-color;
}
.e-calendar .e-content.e-decade tr:first-child .e-cell:first-child span.e-day, .e-calendar .e-content.e-decade tr:last-child .e-cell:last-child span.e-day {
color: $tick-color;
}
.e-calendar .e-header .e-prev:hover, .e-calendar .e-header .e-next:hover, .e-calendar .e-content td.e-focused-date span.e-day,
.e-calendar .e-content.e-year td:hover span.e-day, .e-calendar .e-content.e-decade td:hover span.e-day,
.e-calendar .e-content.e-year td.e-selected:hover span.e-day, .e-calendar .e-content.e-decade td.e-selected:hover span.e-day {
background: $hover-color;
color: $input-font-color;
}
@media (max-width: 319px) {
.container {
min-width: 300px;
}
}
@media (max-width: 576px) {
.header-style {
font-size: 20px;
padding: 13px 0;
}
.container {
padding: 10px;
margin: 0;
.e-slider-container .e-scale .e-tick .e-tick-value {
font-size: 12px;
}
}
.top-space {
margin: 10px;
}
.row {
margin-left: 0;
margin-right: 0;
}
.left-content-wrap .loan-content:first-child {
margin-bottom: 10px;
}
.left-content {
padding: 0;
margin: 0;
border-right-width: 0;
.col-lg-12 {
padding: 12px 12px 18px 12px;
}
.content-space {
margin: 0 0 12px 0;
td {
display: block;
}
label {
font-size: 15px;
margin: 0 0 12px;
}
.tenure-value .e-radio + label {
margin: 0;
.e-label {
font-size: 13px;
}
}
}
.editor-space {
float: left;
width: 100%;
}
.form-space {
margin-bottom: 23px;
&:last-child {
margin-bottom: 0;
}
}
.e-input-group {
width: 100% !important;
}
}
.emi-content {
padding: 0;
margin-top: 0;
.emi-header {
text-align: center;
font-size: 18px;
}
}
.tenure-value {
padding: 0;
float: none;
}
.emi-content {
h6 {
font-size: 23px;
}
h1 {
font-size: 30px;
}
.col-lg-7 {
width: 100%;
float: left;
}
.col-lg-5 {
width: 100%;
float: left;
}
}
.pie-content {
div {
margin: 10px 0;
text-align: center;
&:first-child {
margin-top: 0;
}
}
p {
display: inline-block;
margin: 0;
}
h5 {
display: inline-block;
margin: 0;
padding: 5px;
}
.pie-total {
span {
display: inline-block;
}
p {
display: block;
}
}
}
.main-content .loan-content {
.graph-text {
margin: 12px;
font-size: 18px;
}
.graph-input {
padding: 0 12px 12px;
width: 100%;
margin: 0;
}
}
.center-heading {
font-size: 18px;
}
.graph-container {
padding: 0 2px;
}
}
@media (min-width: 576px) and (max-width: 991px) {
.container {
padding: 0 30px;
width: 100%;
}
.left-content-wrap {
.loan-content {
width: 100%;
float: left;
margin: 0;
padding-bottom: 25px;
& + .loan-content {
margin-top: 30px;
padding-top: 25px;
padding-bottom: 0px;
}
}
}
.left-content {
border-right-width: 0;
}
.emi-content {
max-width: 100%;
.col-lg-7 {
width: 60%;
float: left;
}
.col-lg-5 {
width: 40%;
float: left;
}
}
}
@media (max-width: 700px) {
.main-content .graph-text {
margin-top: 15px;
}
.main-content .graph-input {
margin: 21px;
}
}
@media (min-width: 992px) {
.container {
padding: 0 35px;
width: 100%;
}
.left-content-wrap {
.loan-content {
width: 50%;
float: left;
margin: 0;
& + .loan-content {
margin: 0;
}
}
}
.left-content {
border-right-width: 1px;
}
}
@media (min-width: 992px) and (max-width: 1200px) {
.left-content {
min-width: 450px;
padding: 0 20px;
margin-bottom: 40px;
}
.emi-content {
max-width: 100%;
padding: 0 20px;
.col-lg-7 {
width: 60%;
float: left;
}
.col-lg-5 {
width: 40%;
float: left;
}
.emi-footer {
margin-top: 15px;
}
}
.graph-container {
padding: 0 10px;
}
}
@media (min-width: 1200px) and (max-width: 1329px) {
.container {
padding: 0 35px;
}
}
@media (min-width: 1330px) {
.container {
width: 1300px;
}
}
.e-grid#scheduleGrid > .e-gridheader .e-headercontent .e-table colgroup col:first-child,
.e-grid .e-content .e-table#scheduleGrid_content_table > colgroup col:first-child {
width: 0px !important;
}
.e-grid .e-detailrowexpand > div,
.e-grid .e-detailrowcollapse > div {
display: none;
}
.e-grid .e-row .e-row-toggle {
display: inline-block;
}

3
styles/styles.scss Normal file
Просмотреть файл

@ -0,0 +1,3 @@
//sass-lint:disable-all
@import 'ej2-inputs/styles/bootstrap.scss';
@import 'ej2-grids/styles/bootstrap.scss';

32
test-main.js Normal file
Просмотреть файл

@ -0,0 +1,32 @@
var allTestFiles = [];
var TEST_REGEXP = /(spec)\.js$/i;
// Get a list of all the test files to include
Object.keys(window.__karma__.files).forEach(function (file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
// If you require sub-dependencies of test files to be loaded as-is (requiring file extension)
// then do not normalize the paths
var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, '');
allTestFiles.push(normalizedTestModule);
}
});
require.config({
// Karma serves files under /base, which is the basePath from your config file
baseUrl: '/base',
paths: {},
packages: [{
name: '@syncfusion/ej2-base',
location: 'node_modules/@syncfusion/ej2-base',
main: 'index.js'
}],
// dynamically load all test files
deps: allTestFiles,
// we have to kickoff jasmine, as it is asynchronous
callback: window.__karma__.start
});

31
tsconfig.json Normal file
Просмотреть файл

@ -0,0 +1,31 @@
{
"compilerOptions": {
"target": "es5",
"module": "amd",
"declaration": true,
"removeComments": true,
"noLib": false,
"experimentalDecorators": true,
"sourceMap": true,
"pretty": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitUseStrict": false,
"noFallthroughCasesInSwitch": true,
"allowJs": false,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"lib": ["es5", "es2015.promise", "dom"],
"types": ["jasmine","jasmine-ajax","requirejs","chai"]
},
"exclude": [
"node_modules",
"dist",
"public",
"coverage",
"test-report"
],
"compileOnSave": false
}

28
webpack.config.js Normal file
Просмотреть файл

@ -0,0 +1,28 @@
var fs = require('fs');
var glob = require('glob');
var webpack = require('webpack');
var path = require('path');
module.exports = {
entry: {
js: glob.sync("./src/**/*.js"),
},
output: {
path: __dirname + '/',
filename: "./dist/common.js"
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: true,
dead_code: true,
unused: true
},
output: {
beautify: true,
comments: false
},
sourceMap: true
}),
]
}