├── demo
├── src
│ ├── assets
│ │ └── .gitkeep
│ ├── app
│ │ ├── app.component.css
│ │ ├── app.module.ts
│ │ ├── app.component.ts
│ │ └── app.component.html
│ ├── favicon.ico
│ ├── environments
│ │ ├── environment.prod.ts
│ │ └── environment.ts
│ ├── styles.css
│ ├── index.html
│ ├── main.ts
│ ├── tsconfig.json
│ ├── test.ts
│ └── polyfills.ts
├── e2e
│ ├── app.po.ts
│ ├── app.e2e-spec.ts
│ └── tsconfig.json
├── .editorconfig
├── .gitignore
├── protractor.conf.js
├── README.md
├── .angular-cli.json
├── karma.conf.js
├── package.json
└── tslint.json
├── index.ts
├── src
├── odometer
│ ├── odometer.d.ts
│ ├── index.ts
│ ├── themes
│ │ ├── index.ts
│ │ ├── minimal.theme.ts
│ │ ├── default.theme.ts
│ │ ├── plaza.theme.ts
│ │ ├── digital.theme.ts
│ │ ├── train-station.theme.ts
│ │ ├── car.theme.ts
│ │ └── slot-machine.theme.ts
│ ├── odometer.config.ts
│ ├── odometer.model.ts
│ └── odometer.component.ts
└── index.ts
├── travis.bak
├── .travis.yml.bak
├── .github
├── PULL_REQUEST_TEMPLATE.md
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE.md
└── CODE_OF_CONDUCT.md
├── .editorconfig
├── .gitignore
├── .npmignore
├── LICENSE
├── tsconfig.json
├── tslint.json
├── package.json
└── README.md
/demo/src/assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/demo/src/app/app.component.css:
--------------------------------------------------------------------------------
1 | ng2-odometer {
2 | font-size: 20px;
3 | }
4 |
--------------------------------------------------------------------------------
/demo/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jmandreslopez/ng2-odometer/HEAD/demo/src/favicon.ico
--------------------------------------------------------------------------------
/demo/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Jose Andres on 02.19.17
3 | */
4 |
5 | export * from './dist/odometer';
6 |
--------------------------------------------------------------------------------
/src/odometer/odometer.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Jose Andres on 02.23.17
3 | */
4 |
5 | declare module 'odometer';
6 |
--------------------------------------------------------------------------------
/src/odometer/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Jose Andres on 02.23.17
3 | */
4 |
5 | export * from './odometer.component';
6 |
--------------------------------------------------------------------------------
/demo/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
3 | body {
4 | padding: 20px;
5 | margin: 0;
6 | }
7 |
8 | .hide {
9 | display: block;
10 | }
11 |
--------------------------------------------------------------------------------
/demo/e2e/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, element, by } from 'protractor';
2 |
3 | export class DemoPage {
4 | navigateTo() {
5 | return browser.get('/');
6 | }
7 |
8 | getParagraphText() {
9 | return element(by.css('app-root h1')).getText();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/travis.bak:
--------------------------------------------------------------------------------
1 | language: node_js
2 | cache:
3 | directories:
4 | - node_modules
5 | notifications:
6 | email: false
7 | node_js:
8 | - '7'
9 | before_script:
10 | - npm prune
11 | after_success:
12 | - npm run semantic-release
13 | branches:
14 | except:
15 | - /^v\d+\.\d+\.\d+$/
16 |
--------------------------------------------------------------------------------
/.travis.yml.bak:
--------------------------------------------------------------------------------
1 | language: node_js
2 | cache:
3 | directories:
4 | - node_modules
5 | notifications:
6 | email: false
7 | node_js:
8 | - '7'
9 | before_script:
10 | - npm prune
11 | after_success:
12 | - npm run semantic-release
13 | branches:
14 | except:
15 | - /^v\d+\.\d+\.\d+$/
16 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | * **What kind of change does this PR introduce?** (Bug fix, feature, docs update, ...)
2 |
3 |
4 |
5 | * **What is the current behavior?** (You can also link to an open issue here)
6 |
7 |
8 |
9 | * **What is the new behavior (if this is a feature change)?**
10 |
11 |
12 |
13 | * **Other information**:
14 |
--------------------------------------------------------------------------------
/src/odometer/themes/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Jose Andres on 02.23.17
3 | */
4 |
5 | export * from './car.theme';
6 | export * from './default.theme';
7 | export * from './digital.theme';
8 | export * from './minimal.theme';
9 | export * from './plaza.theme';
10 | export * from './slot-machine.theme';
11 | export * from './train-station.theme';
12 |
--------------------------------------------------------------------------------
/demo/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Demo
6 |
7 |
8 |
9 |
10 |
11 |
12 | Loading...
13 |
14 |
15 |
--------------------------------------------------------------------------------
/demo/e2e/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { DemoPage } from './app.po';
2 |
3 | describe('demo App', () => {
4 | let page: DemoPage;
5 |
6 | beforeEach(() => {
7 | page = new DemoPage();
8 | });
9 |
10 | it('should display message saying app works', () => {
11 | page.navigateTo();
12 | expect(page.getParagraphText()).toEqual('app works!');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/demo/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 |
3 | root = true
4 |
5 | [*]
6 | charset = utf-8
7 | indent_style = space
8 | indent_size = 2
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [**.ts]
13 | indent_style = space
14 | indent_size = 4
15 |
16 | [*.md]
17 | max_line_length = off
18 | trim_trailing_whitespace = false
19 |
--------------------------------------------------------------------------------
/demo/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 |
4 | import { AppModule } from './app/app.module';
5 | import { environment } from './environments/environment';
6 |
7 | if (environment.production) {
8 | enableProdMode();
9 | }
10 |
11 | platformBrowserDynamic().bootstrapModule(AppModule);
12 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 |
3 | root = true
4 |
5 | [*]
6 | charset = utf-8
7 | indent_style = space
8 | indent_size = 2
9 | end_of_line = lf
10 | insert_final_newline = true
11 | trim_trailing_whitespace = true
12 |
13 | [**.ts]
14 | indent_style = space
15 | indent_size = 4
16 |
17 | [*.md]
18 | max_line_length = false
19 | trim_trailing_whitespace = false
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | /node_modules
3 | /bower_components
4 |
5 | # IDEs and editors
6 | /.idea
7 | /.vscode
8 | .project
9 | .classpath
10 | *.launch
11 | .settings/
12 |
13 | # Misc
14 | npm-debug.log
15 | npm-debug.log.*
16 |
17 | # Build and dist for now
18 | /dist
19 | /temp
20 | /logs
21 |
22 | # System Files
23 | .DS_Store
24 | Thumbs.db
25 |
26 | # App
27 | src/**/*.js
28 | src/**/*.map
29 |
--------------------------------------------------------------------------------
/demo/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // The file contents for the current environment will overwrite these during build.
2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do
3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead.
4 | // The list of which env maps to which file can be found in `.angular-cli.json`.
5 |
6 | export const environment = {
7 | production: false
8 | };
9 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 |
2 | # Misc
3 | .DS_Store
4 | .github
5 | **/.DS_Store
6 | nbproject
7 | manifest.mf
8 | build.xml
9 | node_modules/*
10 | npm-debug.log
11 | npm-debug.log.*
12 | Thumbs.db
13 | coverage
14 | *.ts
15 | !*.d.ts
16 | tests
17 | *.spec.*
18 | *.test.*
19 |
20 | # IDE
21 | .idea
22 | .project
23 | .settings
24 | .vscode
25 | .idea/*
26 | *.iml
27 |
28 | # Misc Project
29 | *.yml
30 | demo
31 | karma*
32 | typings
33 | tsconfig.json
34 | tslint.json
35 | typings.json
36 |
--------------------------------------------------------------------------------
/demo/e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "declaration": false,
5 | "emitDecoratorMetadata": true,
6 | "experimentalDecorators": true,
7 | "lib": [
8 | "es2016"
9 | ],
10 | "module": "commonjs",
11 | "moduleResolution": "node",
12 | "outDir": "../dist/out-tsc-e2e",
13 | "sourceMap": true,
14 | "target": "es6",
15 | "typeRoots": [
16 | "../node_modules/@types"
17 | ]
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/demo/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { BrowserModule } from '@angular/platform-browser';
3 | import { Ng2OdometerModule } from 'ng2-odometer';
4 | import { AppComponent } from './app.component';
5 |
6 | @NgModule({
7 | imports: [
8 | BrowserModule,
9 | Ng2OdometerModule.forRoot()
10 | ],
11 | declarations: [AppComponent],
12 | bootstrap: [AppComponent]
13 | })
14 | export class AppModule {
15 | //
16 | }
17 |
--------------------------------------------------------------------------------
/demo/src/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "",
4 | "declaration": false,
5 | "emitDecoratorMetadata": true,
6 | "experimentalDecorators": true,
7 | "lib": [
8 | "es2016",
9 | "dom"
10 | ],
11 | "mapRoot": "./",
12 | "module": "es2015",
13 | "moduleResolution": "node",
14 | "outDir": "../dist/out-tsc",
15 | "sourceMap": true,
16 | "target": "es5",
17 | "typeRoots": [
18 | "../node_modules/@types"
19 | ]
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Jose Andres on 02.23.17
3 | */
4 |
5 | import { NgModule, ModuleWithProviders } from '@angular/core';
6 | import { CommonModule } from '@angular/common';
7 | import { Ng2OdometerComponent } from './odometer';
8 |
9 | @NgModule({
10 | imports: [CommonModule],
11 | declarations: [Ng2OdometerComponent],
12 | exports: [Ng2OdometerComponent]
13 | })
14 | export class Ng2OdometerModule {
15 | static forRoot(): ModuleWithProviders {
16 | return {
17 | ngModule: Ng2OdometerModule
18 | };
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/odometer/odometer.config.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Jose Andres on 6.15.17
3 | */
4 |
5 | import { Component } from '@angular/core';
6 | import { Observable } from 'rxjs';
7 |
8 | export interface Ng2OdometerConfigModel {
9 | animation?: string;
10 | format?: string;
11 | theme?: string;
12 | value?: number;
13 | duration?: number;
14 | auto?: boolean;
15 | }
16 |
17 | export class Ng2OdometerConfig implements Ng2OdometerConfigModel {
18 | animation?: string = 'slide';
19 | format: string = '(,ddd)';
20 | theme?: string = 'default';
21 | value?: number = 0;
22 | duration?: number = 2000;
23 | auto?: boolean = true;
24 | }
25 |
--------------------------------------------------------------------------------
/src/odometer/odometer.model.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Jose Andres on 02.23.17
3 | */
4 |
5 | export interface OdometerModel {
6 | MAX_VALUES: number;
7 | digits: Array;
8 | el: HTMLElement;
9 | format: {
10 | precision: number;
11 | radix: any;
12 | repeating: string;
13 | };
14 | inside: HTMLElement;
15 | options: {
16 | el: HTMLElement;
17 | duration: number;
18 | theme: string
19 | format: string;
20 | animation: string;
21 | };
22 | ribbons: any;
23 | transitionEndBound: boolean;
24 | value: 0;
25 |
26 | // Methods
27 | update(number: number): void;
28 | }
29 |
--------------------------------------------------------------------------------
/demo/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 |
7 | # dependencies
8 | /node_modules
9 |
10 | # IDEs and editors
11 | /.idea
12 | .project
13 | .classpath
14 | .c9/
15 | *.launch
16 | .settings/
17 | *.sublime-workspace
18 |
19 | # IDE - VSCode
20 | .vscode/*
21 | !.vscode/settings.json
22 | !.vscode/tasks.json
23 | !.vscode/launch.json
24 | !.vscode/extensions.json
25 |
26 | # misc
27 | /.sass-cache
28 | /connect.lock
29 | /coverage/*
30 | /libpeerconnection.log
31 | npm-debug.log
32 | testem.log
33 | /typings
34 |
35 | # e2e
36 | /e2e/*.js
37 | /e2e/*.map
38 |
39 | #System Files
40 | .DS_Store
41 | Thumbs.db
42 |
--------------------------------------------------------------------------------
/demo/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import { Observable, Observer } from 'rxjs';
3 |
4 | @Component({
5 | selector: 'app',
6 | styleUrls: ['app.component.css'],
7 | templateUrl: 'app.component.html'
8 | })
9 | export class AppComponent {
10 | public number: number = 3000;
11 | public observable: Observable;
12 | private observer: Observer;
13 |
14 | constructor() {
15 | this.observable = new Observable((observer: any) => this.observer = observer).share();
16 |
17 | // For auto mode
18 | setTimeout(() => this.number += this.number, 5000); // Update on 5 seconds
19 | }
20 |
21 | public trigger() {
22 | this.observer.next(true);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/demo/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // Protractor configuration file, see link for more information
2 | // https://github.com/angular/protractor/blob/master/lib/config.ts
3 |
4 | /*global jasmine */
5 | const { SpecReporter } = require('jasmine-spec-reporter');
6 |
7 | exports.config = {
8 | allScriptsTimeout: 11000,
9 | specs: [
10 | './e2e/**/*.e2e-spec.ts'
11 | ],
12 | capabilities: {
13 | 'browserName': 'chrome'
14 | },
15 | directConnect: true,
16 | baseUrl: 'http://localhost:4200/',
17 | framework: 'jasmine',
18 | jasmineNodeOpts: {
19 | showColors: true,
20 | defaultTimeoutInterval: 30000,
21 | print: function() {}
22 | },
23 | beforeLaunch: function() {
24 | require('ts-node').register({
25 | project: 'e2e'
26 | });
27 | },
28 | onPrepare() {
29 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
30 | }
31 | };
32 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Submitting Pull Requests
2 |
3 | If you're changing the structure of the repository please create an issue first.
4 |
5 | The release process is automated using [semantic-release](https://github.com/semantic-release/semantic-release), for best release result follow these simple steps:
6 |
7 | ```
8 | git add --all
9 | npm run commit
10 | git push origin master
11 | ```
12 |
13 | * Do not add/change the package.json version field.
14 | * Create unit test for any new functionality you add in your commits.
15 |
16 | ## Submitting bug reports
17 |
18 | Make sure you are on latest changes and that you ran this command `npm run clean:install` after updating your local repository. If you can, please provide more information about your environment such as browser, operating system, node version, and npm version.
19 |
20 | ## Project Structure
21 |
22 | The configuration files are devided in config/, config/advance/ and config/custom
23 | - src/core
24 | - src/providers/ This folder contains one folder per provider
25 |
--------------------------------------------------------------------------------
/demo/src/app/app.component.html:
--------------------------------------------------------------------------------
1 | Odometer for Angular2
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Jose Andres
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/demo/README.md:
--------------------------------------------------------------------------------
1 | # Demo
2 |
3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.0.0-beta.32.3.
4 |
5 | ## Development server
6 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
7 |
8 | ## Code scaffolding
9 |
10 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive/pipe/service/class/module`.
11 |
12 | ## Build
13 |
14 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.
15 |
16 | ## Running unit tests
17 |
18 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
19 |
20 | ## Running end-to-end tests
21 |
22 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
23 | Before running the tests make sure you are serving the app via `ng serve`.
24 |
25 | ## Further help
26 |
27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
28 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "moduleResolution": "node",
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "sourceMap": true,
9 | "inlineSources": true,
10 | "noEmitHelpers": false,
11 | "noImplicitAny": true,
12 | "declaration": true,
13 | "skipLibCheck": true,
14 | "stripInternal": true,
15 | "noUnusedLocals": false,
16 | "noUnusedParameters": false,
17 | "removeComments": true,
18 | "noLib": false,
19 | "pretty": true,
20 | "allowUnreachableCode": false,
21 | "allowUnusedLabels": false,
22 | "noImplicitReturns": false,
23 | "noImplicitUseStrict": false,
24 | "noFallthroughCasesInSwitch": true,
25 | "outDir": "dist",
26 | "lib": [
27 | "dom",
28 | "es6"
29 | ],
30 | "types": [
31 | "node",
32 | "karma",
33 | "jasmine",
34 | "lodash"
35 | ]
36 | },
37 | "files": [
38 | "src/index.ts"
39 | ],
40 | "exclude": [
41 | "node_modules"
42 | ],
43 | "compileOnSave": false,
44 | "angularCompilerOptions": {
45 | "skipTemplateCodegen": true
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/demo/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/long-stack-trace-zone';
4 | import 'zone.js/dist/proxy.js';
5 | import 'zone.js/dist/sync-test';
6 | import 'zone.js/dist/jasmine-patch';
7 | import 'zone.js/dist/async-test';
8 | import 'zone.js/dist/fake-async-test';
9 | import { getTestBed } from '@angular/core/testing';
10 | import {
11 | BrowserDynamicTestingModule,
12 | platformBrowserDynamicTesting
13 | } from '@angular/platform-browser-dynamic/testing';
14 |
15 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any.
16 | declare var __karma__: any;
17 | declare var require: any;
18 |
19 | // Prevent Karma from running prematurely.
20 | __karma__.loaded = function () {};
21 |
22 | // First, initialize the Angular testing environment.
23 | getTestBed().initTestEnvironment(
24 | BrowserDynamicTestingModule,
25 | platformBrowserDynamicTesting()
26 | );
27 | // Then we find all the tests.
28 | const context = require.context('./', true, /\.spec\.ts$/);
29 | // And load the modules.
30 | context.keys().map(context);
31 | // Finally, start Karma to run the tests.
32 | __karma__.start();
33 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | **Note: for support questions, please use one of these channels:**
2 |
3 | * **I'm submitting a ...**
4 | [ ] bug report
5 | [ ] feature request
6 | [ ] question about the decisions made in the repository
7 |
8 | * **Do you want to request a *feature* or report a *bug*?**
9 |
10 |
11 |
12 | * **What is the current behavior?**
13 |
14 |
15 |
16 | * **If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem** via
17 | https://plnkr.co or similar (you can use this template as a starting point: http://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5).
18 |
19 |
20 |
21 | * **What is the expected behavior?**
22 |
23 |
24 |
25 | * **What is the motivation / use case for changing the behavior?**
26 |
27 |
28 |
29 | * **Please tell us about your environment:**
30 |
31 | - Angular version: 2.1.2
32 | - Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]
33 |
34 |
35 |
36 | * **Other information** (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc)
37 |
--------------------------------------------------------------------------------
/demo/.angular-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "project": {
4 | "version": "1.0.0-beta.32.3",
5 | "name": "demo"
6 | },
7 | "apps": [
8 | {
9 | "root": "src",
10 | "outDir": "dist",
11 | "assets": [
12 | "assets",
13 | "favicon.ico"
14 | ],
15 | "index": "index.html",
16 | "main": "main.ts",
17 | "polyfills": "polyfills.ts",
18 | "test": "test.ts",
19 | "tsconfig": "tsconfig.json",
20 | "prefix": "app",
21 | "styles": [
22 | "styles.css"
23 | ],
24 | "scripts": [],
25 | "environmentSource": "environments/environment.ts",
26 | "environments": {
27 | "dev": "environments/environment.ts",
28 | "prod": "environments/environment.prod.ts"
29 | }
30 | }
31 | ],
32 | "e2e": {
33 | "protractor": {
34 | "config": "./protractor.conf.js"
35 | }
36 | },
37 | "lint": [
38 | {
39 | "files": "src/**/*.ts",
40 | "project": "src/tsconfig.json"
41 | },
42 | {
43 | "files": "e2e/**/*.ts",
44 | "project": "e2e/tsconfig.json"
45 | }
46 | ],
47 | "test": {
48 | "karma": {
49 | "config": "./karma.conf.js"
50 | }
51 | },
52 | "defaults": {
53 | "styleExt": "css",
54 | "component": {}
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/demo/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/0.13/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular/cli'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular/cli/plugins/karma')
14 | ],
15 | client:{
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | files: [
19 | { pattern: './src/test.ts', watched: false }
20 | ],
21 | preprocessors: {
22 | './src/test.ts': ['@angular/cli']
23 | },
24 | mime: {
25 | 'text/x-typescript': ['ts','tsx']
26 | },
27 | coverageIstanbulReporter: {
28 | reports: [ 'html', 'lcovonly' ],
29 | fixWebpackSourcePaths: true
30 | },
31 | angularCli: {
32 | config: './.angular-cli.json',
33 | environment: 'dev'
34 | },
35 | reporters: config.angularCli && config.angularCli.codeCoverage
36 | ? ['progress', 'coverage-istanbul']
37 | : ['progress', 'kjhtml'],
38 | port: 9876,
39 | colors: true,
40 | logLevel: config.LOG_INFO,
41 | autoWatch: true,
42 | browsers: ['Chrome'],
43 | singleRun: false
44 | });
45 | };
46 |
--------------------------------------------------------------------------------
/demo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ng2-odometer-demo",
3 | "version": "1.0.0",
4 | "description": "Odometer for Angular2",
5 | "author": "Jose Andres ",
6 | "license": "MIT",
7 | "angular-cli": {},
8 | "scripts": {
9 | "ng": "ng",
10 | "start": "ng serve",
11 | "test": "ng test",
12 | "lint": "ng lint",
13 | "e2e": "ng e2e"
14 | },
15 | "private": true,
16 | "dependencies": {
17 | "@angular/common": "^2.4.0",
18 | "@angular/compiler": "^2.4.0",
19 | "@angular/core": "^2.4.0",
20 | "@angular/forms": "^2.4.0",
21 | "@angular/http": "^2.4.0",
22 | "@angular/platform-browser": "^2.4.0",
23 | "@angular/platform-browser-dynamic": "^2.4.0",
24 | "@angular/router": "^3.4.0",
25 | "core-js": "^2.4.1",
26 | "ng2-odometer": "^1.1.1",
27 | "odometer": "^0.4.8",
28 | "rxjs": "^5.1.0",
29 | "zone.js": "^0.7.6"
30 | },
31 | "devDependencies": {
32 | "@angular/cli": "1.0.0-beta.32.3",
33 | "@angular/compiler-cli": "^2.4.0",
34 | "@types/jasmine": "2.5.38",
35 | "@types/node": "~6.0.60",
36 | "codelyzer": "~2.0.0-beta.4",
37 | "jasmine-core": "~2.5.2",
38 | "jasmine-spec-reporter": "~3.2.0",
39 | "karma": "~1.4.1",
40 | "karma-chrome-launcher": "~2.0.0",
41 | "karma-cli": "~1.0.1",
42 | "karma-jasmine": "~1.1.0",
43 | "karma-jasmine-html-reporter": "^0.2.2",
44 | "karma-coverage-istanbul-reporter": "^0.2.0",
45 | "protractor": "~5.1.0",
46 | "ts-node": "~2.0.0",
47 | "tslint": "~4.4.2",
48 | "typescript": "~2.0.0"
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/demo/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/
22 | // import 'core-js/es6/symbol';
23 | // import 'core-js/es6/object';
24 | // import 'core-js/es6/function';
25 | // import 'core-js/es6/parse-int';
26 | // import 'core-js/es6/parse-float';
27 | // import 'core-js/es6/number';
28 | // import 'core-js/es6/math';
29 | // import 'core-js/es6/string';
30 | // import 'core-js/es6/date';
31 | // import 'core-js/es6/array';
32 | // import 'core-js/es6/regexp';
33 | // import 'core-js/es6/map';
34 | // import 'core-js/es6/set';
35 |
36 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */
37 | // import 'classlist.js'; // Run `npm install --save classlist.js`.
38 |
39 | /** IE10 and IE11 requires the following to support `@angular/animation`. */
40 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
41 |
42 |
43 | /** Evergreen browsers require these. **/
44 | import 'core-js/es6/reflect';
45 | import 'core-js/es7/reflect';
46 |
47 |
48 | /** ALL Firefox browsers require the following to support `@angular/animation`. **/
49 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
50 |
51 |
52 |
53 | /***************************************************************************************************
54 | * Zone JS is required by Angular itself.
55 | */
56 | import 'zone.js/dist/zone'; // Included with Angular CLI.
57 |
58 |
59 |
60 | /***************************************************************************************************
61 | * APPLICATION IMPORTS
62 | */
63 |
64 | /**
65 | * Date, currency, decimal and percent pipes.
66 | * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10
67 | */
68 | // import 'intl'; // Run `npm install --save intl`.
69 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rulesDirectory": [
3 | "node_modules/codelyzer"
4 | ],
5 | "rules": {
6 | "class-name": true,
7 | "comment-format": [
8 | true,
9 | "check-space"
10 | ],
11 | "component-class-suffix": true,
12 | "curly": true,
13 | "directive-class-suffix": false,
14 | "directive-selector": [
15 | true,
16 | "attribute",
17 | "",
18 | "camelCase"
19 | ],
20 | "component-selector": [
21 | true,
22 | "element",
23 | "",
24 | "kebab-case"
25 | ],
26 | "eofline": true,
27 | "forin": true,
28 | "indent": [
29 | true,
30 | "spaces"
31 | ],
32 | "label-position": true,
33 | "max-line-length": [
34 | true,
35 | 140
36 | ],
37 | "member-access": false,
38 | "member-ordering": [
39 | true,
40 | "static-before-instance",
41 | "variables-before-functions"
42 | ],
43 | "no-arg": true,
44 | "no-attribute-parameter-decorator": true,
45 | "no-bitwise": true,
46 | "no-console": [
47 | true,
48 | "debug",
49 | "info",
50 | "time",
51 | "timeEnd",
52 | "trace"
53 | ],
54 | "no-construct": true,
55 | "no-debugger": true,
56 | "no-duplicate-variable": true,
57 | "no-empty": false,
58 | "no-eval": true,
59 | "no-forward-ref": true,
60 | "no-inferrable-types": true,
61 | "no-input-rename": true,
62 | "no-output-rename": true,
63 | "no-shadowed-variable": true,
64 | "no-string-literal": false,
65 | "no-switch-case-fall-through": true,
66 | "no-trailing-whitespace": true,
67 | "no-unused-expression": true,
68 | "no-use-before-declare": true,
69 | "no-var-keyword": true,
70 | "object-literal-sort-keys": false,
71 | "one-line": [false],
72 | "pipe-naming": [
73 | true,
74 | "camelCase"
75 | ],
76 | "quotemark": [
77 | true,
78 | "single"
79 | ],
80 | "radix": true,
81 | "semicolon": [
82 | true,
83 | "always"
84 | ],
85 | "triple-equals": [
86 | true,
87 | "allow-null-check"
88 | ],
89 | "typedef-whitespace": [
90 | true,
91 | {
92 | "call-signature": "nospace",
93 | "index-signature": "nospace",
94 | "parameter": "nospace",
95 | "property-declaration": "nospace",
96 | "variable-declaration": "nospace"
97 | }
98 | ],
99 | "use-host-property-decorator": true,
100 | "use-input-property-decorator": true,
101 | "use-life-cycle-interface": true,
102 | "use-output-property-decorator": true,
103 | "use-pipe-transform-interface": true,
104 | "variable-name": false,
105 | "whitespace": [
106 | true,
107 | "check-branch",
108 | "check-decl",
109 | "check-operator",
110 | "check-separator",
111 | "check-type"
112 | ]
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/demo/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rulesDirectory": [
3 | "node_modules/codelyzer"
4 | ],
5 | "rules": {
6 | "callable-types": true,
7 | "class-name": true,
8 | "comment-format": [
9 | true,
10 | "check-space"
11 | ],
12 | "curly": true,
13 | "eofline": true,
14 | "forin": true,
15 | "import-blacklist": [true, "rxjs"],
16 | "import-spacing": true,
17 | "indent": [
18 | true,
19 | "spaces"
20 | ],
21 | "interface-over-type-literal": true,
22 | "label-position": true,
23 | "max-line-length": [
24 | true,
25 | 140
26 | ],
27 | "member-access": false,
28 | "member-ordering": [
29 | true,
30 | "static-before-instance",
31 | "variables-before-functions"
32 | ],
33 | "no-arg": true,
34 | "no-bitwise": true,
35 | "no-console": [
36 | true,
37 | "debug",
38 | "info",
39 | "time",
40 | "timeEnd",
41 | "trace"
42 | ],
43 | "no-construct": true,
44 | "no-debugger": true,
45 | "no-duplicate-variable": true,
46 | "no-empty": false,
47 | "no-empty-interface": true,
48 | "no-eval": true,
49 | "no-inferrable-types": [true, "ignore-params"],
50 | "no-shadowed-variable": true,
51 | "no-string-literal": false,
52 | "no-string-throw": true,
53 | "no-switch-case-fall-through": true,
54 | "no-trailing-whitespace": true,
55 | "no-unused-expression": true,
56 | "no-use-before-declare": true,
57 | "no-var-keyword": true,
58 | "object-literal-sort-keys": false,
59 | "one-line": [
60 | true,
61 | "check-open-brace",
62 | "check-catch",
63 | "check-else",
64 | "check-whitespace"
65 | ],
66 | "prefer-const": true,
67 | "quotemark": [
68 | true,
69 | "single"
70 | ],
71 | "radix": true,
72 | "semicolon": [
73 | "always"
74 | ],
75 | "triple-equals": [
76 | true,
77 | "allow-null-check"
78 | ],
79 | "typedef-whitespace": [
80 | true,
81 | {
82 | "call-signature": "nospace",
83 | "index-signature": "nospace",
84 | "parameter": "nospace",
85 | "property-declaration": "nospace",
86 | "variable-declaration": "nospace"
87 | }
88 | ],
89 | "typeof-compare": true,
90 | "unified-signatures": true,
91 | "variable-name": false,
92 | "whitespace": [
93 | true,
94 | "check-branch",
95 | "check-decl",
96 | "check-operator",
97 | "check-separator",
98 | "check-type"
99 | ],
100 |
101 | "directive-selector": [true, "attribute", "app", "camelCase"],
102 | "component-selector": [true, "element", "app", "kebab-case"],
103 | "use-input-property-decorator": true,
104 | "use-output-property-decorator": true,
105 | "use-host-property-decorator": true,
106 | "no-input-rename": true,
107 | "no-output-rename": true,
108 | "use-life-cycle-interface": true,
109 | "use-pipe-transform-interface": true,
110 | "component-class-suffix": true,
111 | "directive-class-suffix": true,
112 | "no-access-missing-member": true,
113 | "templates-use-public": true,
114 | "invoke-injectable": true
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/.github/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, gender identity and expression, level of experience,
9 | nationality, personal appearance, race, religion, or sexual identity and
10 | orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at jonnybgod@gmail.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at [http://contributor-covenant.org/version/1/4][version]
72 |
73 | [homepage]: http://contributor-covenant.org
74 | [version]: http://contributor-covenant.org/version/1/4/
75 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ng2-odometer",
3 | "description": "Odometer for Angular2",
4 | "author": "Jose Andres ",
5 | "license": "MIT",
6 | "version": "1.1.3",
7 | "keywords": [
8 | "hubspot",
9 | "odometer",
10 | "hubspot",
11 | "angular",
12 | "angular2",
13 | "ng2-odometer"
14 | ],
15 | "main": "./dist/index",
16 | "typings": "./dist/index.d.ts",
17 | "repository": {
18 | "type": "git",
19 | "url": "https://github.com/jmandreslopez/ng2-odometer.git"
20 | },
21 | "bugs": {
22 | "url": "https://github.com/jmandreslopez/ng2-odometer/issues"
23 | },
24 | "homepage": "https://github.com/jmandreslopez/ng2-odometer#readme",
25 | "scripts": {
26 | "rimraf": "rimraf",
27 | "lint": "tslint ./*.ts ./src/{,*/}*.ts",
28 | "clean": "npm cache clean && npm run rimraf -- node_modules dist",
29 | "preclean:install": "npm run clean",
30 | "clean:install": "npm set progress=false && npm install",
31 | "commit": "git-cz",
32 | "build": "tsc -d && ngc",
33 | "semantic-release": "semantic-release pre && npm publish && semantic-release post"
34 | },
35 | "dependencies": {
36 | "odometer": "^0.4.8"
37 | },
38 | "devDependencies": {
39 | "@angular/cli": "^1.1.2",
40 | "@angular/common": "^2.4.7",
41 | "@angular/compiler": "^2.4.7",
42 | "@angular/compiler-cli": "^2.4.7",
43 | "@angular/core": "^2.4.7",
44 | "@angular/forms": "^2.4.7",
45 | "@angular/platform-browser": "^2.4.7",
46 | "@angular/platform-browser-dynamic": "^2.4.7",
47 | "@angular/platform-server": "^2.4.7",
48 | "@angular/router": "3.4.7",
49 | "@angular/tsc-wrapped": "0.5.1",
50 | "@ngtools/webpack": "1.1.4",
51 | "@types/core-js": "0.9.35",
52 | "@types/es6-shim": "^0.31.32",
53 | "@types/jasmine": "^2.5.35",
54 | "@types/karma": "0.13.33",
55 | "@types/lodash": "^4.14.52",
56 | "@types/node": "^7.0.0",
57 | "angular2-template-loader": "0.6.0",
58 | "bulma": "0.2.3",
59 | "classlist-polyfill": "1.0.3",
60 | "codecov": "1.0.1",
61 | "codelyzer": "~2.0.0-beta.4",
62 | "commitizen": "^2.8.6",
63 | "concurrently": "^3.1.0",
64 | "conventional-changelog-cli": "1.2.0",
65 | "conventional-github-releaser": "1.1.3",
66 | "core-js": "^2.4.0",
67 | "cpy": "5.0.0",
68 | "cpy-cli": "1.0.1",
69 | "css-loader": "^0.23.1",
70 | "cz-conventional-changelog": "^1.2.0",
71 | "del-cli": "0.2.1",
72 | "es6-promise": "^3.0.2",
73 | "es6-shim": "^0.35.0",
74 | "gitignore-to-glob": "0.3.0",
75 | "google-code-prettify": "1.0.5",
76 | "highlight.js": "^9.1.0",
77 | "html-loader": "^0.4.3",
78 | "jasmine": "2.5.3",
79 | "jasmine-core": "^2.4.1",
80 | "json-loader": "^0.5.4",
81 | "karma": "^1.4.0",
82 | "karma-chrome-launcher": "^2.0.0",
83 | "karma-cli": "^1.0.1",
84 | "karma-jasmine": "^1.0.2",
85 | "karma-mocha-reporter": "^2.2.0",
86 | "karma-phantomjs-launcher": "^1.0.2",
87 | "karma-webpack": "^1.8.0",
88 | "lodash": "^4.17.4",
89 | "marked": "^0.3.6",
90 | "ngm-cli": "0.4.4",
91 | "node-sass": "^3.6.0",
92 | "npm-run-all": "^4.0.1",
93 | "phantomjs-prebuilt": "^2.1.7",
94 | "pre-commit": "1.2.2",
95 | "raw-loader": "^0.5.1",
96 | "reflect-metadata": "^0.1.3",
97 | "require-dir": "0.3.1",
98 | "rimraf": "~2.5.4",
99 | "rxjs": "^5.0.3",
100 | "sass-loader": "^5.0.0",
101 | "semantic-release": "^6.3.2",
102 | "style-loader": "^0.13.1",
103 | "systemjs-builder": "0.15.34",
104 | "ts-helpers": "^1.1.1",
105 | "ts-loader": "^1.0.0",
106 | "ts-node": "2.0.0",
107 | "tslint": "4.3.1",
108 | "typescript": "^2.1.6",
109 | "webpack": "^2.2.1",
110 | "zone.js": "^0.7.6"
111 | },
112 | "engines": {
113 | "node": ">=6.2.0"
114 | },
115 | "config": {
116 | "commitizen": {
117 | "path": "node_modules/cz-conventional-changelog"
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/src/odometer/themes/minimal.theme.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Jose Andres on 02.23.17
3 | */
4 |
5 | export const MINIMAL_THEME = `
6 | .odometer.odometer-auto-theme,
7 | .odometer.odometer-theme-minimal {
8 | display: inline-block;
9 | vertical-align: middle;
10 | *vertical-align: auto;
11 | *zoom: 1;
12 | *display: inline;
13 | position: relative;
14 | }
15 | .odometer.odometer-auto-theme .odometer-digit,
16 | .odometer.odometer-theme-minimal .odometer-digit {
17 | display: inline-block;
18 | vertical-align: middle;
19 | *vertical-align: auto;
20 | *zoom: 1;
21 | *display: inline;
22 | position: relative;
23 | }
24 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-spacer,
25 | .odometer.odometer-theme-minimal .odometer-digit .odometer-digit-spacer {
26 | display: inline-block;
27 | vertical-align: middle;
28 | *vertical-align: auto;
29 | *zoom: 1;
30 | *display: inline;
31 | visibility: hidden;
32 | }
33 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-inner,
34 | .odometer.odometer-theme-minimal .odometer-digit .odometer-digit-inner {
35 | text-align: left;
36 | display: block;
37 | position: absolute;
38 | top: 0;
39 | left: 0;
40 | right: 0;
41 | bottom: 0;
42 | overflow: hidden;
43 | }
44 | .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon,
45 | .odometer.odometer-theme-minimal .odometer-digit .odometer-ribbon {
46 | display: block;
47 | }
48 | .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon-inner,
49 | .odometer.odometer-theme-minimal .odometer-digit .odometer-ribbon-inner {
50 | display: block;
51 | -webkit-backface-visibility: hidden;
52 | }
53 | .odometer.odometer-auto-theme .odometer-digit .odometer-value,
54 | .odometer.odometer-theme-minimal .odometer-digit .odometer-value {
55 | display: block;
56 | -webkit-transform: translateZ(0);
57 | }
58 | .odometer.odometer-auto-theme .odometer-digit .odometer-value.odometer-last-value,
59 | .odometer.odometer-theme-minimal .odometer-digit .odometer-value.odometer-last-value {
60 | position: absolute;
61 | }
62 | .odometer.odometer-auto-theme.odometer-animating-up .odometer-ribbon-inner,
63 | .odometer.odometer-theme-minimal.odometer-animating-up .odometer-ribbon-inner {
64 | -webkit-transition: -webkit-transform 2s;
65 | -moz-transition: -moz-transform 2s;
66 | -ms-transition: -ms-transform 2s;
67 | -o-transition: -o-transform 2s;
68 | transition: transform 2s;
69 | }
70 | .odometer.odometer-auto-theme.odometer-animating-up.odometer-animating .odometer-ribbon-inner,
71 | .odometer.odometer-theme-minimal.odometer-animating-up.odometer-animating .odometer-ribbon-inner {
72 | -webkit-transform: translateY(-100%);
73 | -moz-transform: translateY(-100%);
74 | -ms-transform: translateY(-100%);
75 | -o-transform: translateY(-100%);
76 | transform: translateY(-100%);
77 | }
78 | .odometer.odometer-auto-theme.odometer-animating-down .odometer-ribbon-inner,
79 | .odometer.odometer-theme-minimal.odometer-animating-down .odometer-ribbon-inner {
80 | -webkit-transform: translateY(-100%);
81 | -moz-transform: translateY(-100%);
82 | -ms-transform: translateY(-100%);
83 | -o-transform: translateY(-100%);
84 | transform: translateY(-100%);
85 | }
86 | .odometer.odometer-auto-theme.odometer-animating-down.odometer-animating .odometer-ribbon-inner,
87 | .odometer.odometer-theme-minimal.odometer-animating-down.odometer-animating .odometer-ribbon-inner {
88 | -webkit-transition: -webkit-transform 2s;
89 | -moz-transition: -moz-transform 2s;
90 | -ms-transition: -ms-transform 2s;
91 | -o-transition: -o-transform 2s;
92 | transition: transform 2s;
93 | -webkit-transform: translateY(0);
94 | -moz-transform: translateY(0);
95 | -ms-transform: translateY(0);
96 | -o-transform: translateY(0);
97 | transform: translateY(0);
98 | }
99 | `;
100 |
--------------------------------------------------------------------------------
/src/odometer/themes/default.theme.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Jose Andres on 02.23.17
3 | */
4 |
5 | export const DEFAULT_THEME = `
6 | .odometer.odometer-auto-theme,
7 | .odometer.odometer-theme-default {
8 | display: inline-block;
9 | vertical-align: middle;
10 | *vertical-align: auto;
11 | *zoom: 1;
12 | *display: inline;
13 | position: relative;
14 | }
15 | .odometer.odometer-auto-theme .odometer-digit,
16 | .odometer.odometer-theme-default .odometer-digit {
17 | display: inline-block;
18 | vertical-align: middle;
19 | *vertical-align: auto;
20 | *zoom: 1;
21 | *display: inline;
22 | position: relative;
23 | }
24 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-spacer,
25 | .odometer.odometer-theme-default .odometer-digit .odometer-digit-spacer {
26 | display: inline-block;
27 | vertical-align: middle;
28 | *vertical-align: auto;
29 | *zoom: 1;
30 | *display: inline;
31 | visibility: hidden;
32 | }
33 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-inner,
34 | .odometer.odometer-theme-default .odometer-digit .odometer-digit-inner {
35 | text-align: left;
36 | display: block;
37 | position: absolute;
38 | top: 0;
39 | left: 0;
40 | right: 0;
41 | bottom: 0;
42 | overflow: hidden;
43 | }
44 | .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon,
45 | .odometer.odometer-theme-default .odometer-digit .odometer-ribbon {
46 | display: block;
47 | }
48 | .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon-inner,
49 | .odometer.odometer-theme-default .odometer-digit .odometer-ribbon-inner {
50 | display: block;
51 | -webkit-backface-visibility: hidden;
52 | }
53 | .odometer.odometer-auto-theme .odometer-digit .odometer-value,
54 | .odometer.odometer-theme-default .odometer-digit .odometer-value {
55 | display: block;
56 | -webkit-transform: translateZ(0);
57 | }
58 | .odometer.odometer-auto-theme .odometer-digit .odometer-value.odometer-last-value,
59 | .odometer.odometer-theme-default .odometer-digit .odometer-value.odometer-last-value {
60 | position: absolute;
61 | }
62 | .odometer.odometer-auto-theme.odometer-animating-up .odometer-ribbon-inner,
63 | .odometer.odometer-theme-default.odometer-animating-up .odometer-ribbon-inner {
64 | -webkit-transition: -webkit-transform 2s !important;
65 | -moz-transition: -moz-transform 2s;
66 | -ms-transition: -ms-transform 2s;
67 | -o-transition: -o-transform 2s;
68 | transition: transform 2s;
69 | }
70 | .odometer.odometer-auto-theme.odometer-animating-up.odometer-animating .odometer-ribbon-inner,
71 | .odometer.odometer-theme-default.odometer-animating-up.odometer-animating .odometer-ribbon-inner {
72 | -webkit-transform: translateY(-100%);
73 | -moz-transform: translateY(-100%);
74 | -ms-transform: translateY(-100%);
75 | -o-transform: translateY(-100%);
76 | transform: translateY(-100%);
77 | }
78 | .odometer.odometer-auto-theme.odometer-animating-down .odometer-ribbon-inner,
79 | .odometer.odometer-theme-default.odometer-animating-down .odometer-ribbon-inner {
80 | -webkit-transform: translateY(-100%);
81 | -moz-transform: translateY(-100%);
82 | -ms-transform: translateY(-100%);
83 | -o-transform: translateY(-100%);
84 | transform: translateY(-100%);
85 | }
86 | .odometer.odometer-auto-theme.odometer-animating-down.odometer-animating .odometer-ribbon-inner,
87 | .odometer.odometer-theme-default.odometer-animating-down.odometer-animating .odometer-ribbon-inner {
88 | -webkit-transition: -webkit-transform 2s;
89 | -moz-transition: -moz-transform 2s;
90 | -ms-transition: -ms-transform 2s;
91 | -o-transition: -o-transform 2s;
92 | transition: transform 2s;
93 | -webkit-transform: translateY(0);
94 | -moz-transform: translateY(0);
95 | -ms-transform: translateY(0);
96 | -o-transform: translateY(0);
97 | transform: translateY(0);
98 | }
99 | .odometer.odometer-auto-theme,
100 | .odometer.odometer-theme-default {
101 | font-family: "Helvetica Neue", sans-serif;
102 | line-height: 1.1em;
103 | }
104 | .odometer.odometer-auto-theme .odometer-value,
105 | .odometer.odometer-theme-default .odometer-value {
106 | text-align: center;
107 | }
108 | `;
109 |
--------------------------------------------------------------------------------
/src/odometer/themes/plaza.theme.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Jose Andres on 02.23.17
3 | */
4 |
5 | export const PLAZA_THEME = `
6 | .odometer.odometer-auto-theme,
7 | .odometer.odometer-theme-plaza {
8 | display: inline-block;
9 | vertical-align: middle;
10 | *vertical-align: auto;
11 | *zoom: 1;
12 | *display: inline;
13 | position: relative;
14 | }
15 | .odometer.odometer-auto-theme .odometer-digit,
16 | .odometer.odometer-theme-plaza .odometer-digit {
17 | display: inline-block;
18 | vertical-align: middle;
19 | *vertical-align: auto;
20 | *zoom: 1;
21 | *display: inline;
22 | position: relative;
23 | }
24 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-spacer,
25 | .odometer.odometer-theme-plaza .odometer-digit .odometer-digit-spacer {
26 | display: inline-block;
27 | vertical-align: middle;
28 | *vertical-align: auto;
29 | *zoom: 1;
30 | *display: inline;
31 | visibility: hidden;
32 | }
33 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-inner,
34 | .odometer.odometer-theme-plaza .odometer-digit .odometer-digit-inner {
35 | text-align: left;
36 | display: block;
37 | position: absolute;
38 | top: 0;
39 | left: 0;
40 | right: 0;
41 | bottom: 0;
42 | overflow: hidden;
43 | }
44 | .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon,
45 | .odometer.odometer-theme-plaza .odometer-digit .odometer-ribbon {
46 | display: block;
47 | }
48 | .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon-inner,
49 | .odometer.odometer-theme-plaza .odometer-digit .odometer-ribbon-inner {
50 | display: block;
51 | -webkit-backface-visibility: hidden;
52 | }
53 | .odometer.odometer-auto-theme .odometer-digit .odometer-value,
54 | .odometer.odometer-theme-plaza .odometer-digit .odometer-value {
55 | display: block;
56 | -webkit-transform: translateZ(0);
57 | }
58 | .odometer.odometer-auto-theme .odometer-digit .odometer-value.odometer-last-value,
59 | .odometer.odometer-theme-plaza .odometer-digit .odometer-value.odometer-last-value {
60 | position: absolute;
61 | }
62 | .odometer.odometer-auto-theme.odometer-animating-up .odometer-ribbon-inner,
63 | .odometer.odometer-theme-plaza.odometer-animating-up .odometer-ribbon-inner {
64 | -webkit-transition: -webkit-transform 2s;
65 | -moz-transition: -moz-transform 2s;
66 | -ms-transition: -ms-transform 2s;
67 | -o-transition: -o-transform 2s;
68 | transition: transform 2s;
69 | }
70 | .odometer.odometer-auto-theme.odometer-animating-up.odometer-animating .odometer-ribbon-inner,
71 | .odometer.odometer-theme-plaza.odometer-animating-up.odometer-animating .odometer-ribbon-inner {
72 | -webkit-transform: translateY(-100%);
73 | -moz-transform: translateY(-100%);
74 | -ms-transform: translateY(-100%);
75 | -o-transform: translateY(-100%);
76 | transform: translateY(-100%);
77 | }
78 | .odometer.odometer-auto-theme.odometer-animating-down .odometer-ribbon-inner,
79 | .odometer.odometer-theme-plaza.odometer-animating-down .odometer-ribbon-inner {
80 | -webkit-transform: translateY(-100%);
81 | -moz-transform: translateY(-100%);
82 | -ms-transform: translateY(-100%);
83 | -o-transform: translateY(-100%);
84 | transform: translateY(-100%);
85 | }
86 | .odometer.odometer-auto-theme.odometer-animating-down.odometer-animating .odometer-ribbon-inner,
87 | .odometer.odometer-theme-plaza.odometer-animating-down.odometer-animating .odometer-ribbon-inner {
88 | -webkit-transition: -webkit-transform 2s;
89 | -moz-transition: -moz-transform 2s;
90 | -ms-transition: -ms-transform 2s;
91 | -o-transition: -o-transform 2s;
92 | transition: transform 2s;
93 | -webkit-transform: translateY(0);
94 | -moz-transform: translateY(0);
95 | -ms-transform: translateY(0);
96 | -o-transform: translateY(0);
97 | transform: translateY(0);
98 | }
99 | .odometer.odometer-auto-theme,
100 | .odometer.odometer-theme-plaza {
101 | -moz-border-radius: 0.15em;
102 | -webkit-border-radius: 0.15em;
103 | border-radius: 0.15em;
104 | background-color: #f0f8ff;
105 | font-family: "Helvetica Neue", sans-serif;
106 | font-weight: 100;
107 | padding: 0 0.12em;
108 | line-height: 1.2em;
109 | font-size: 1.2em;
110 | background-size: 16px 16px;
111 | }
112 | .odometer.odometer-auto-theme .odometer-digit,
113 | .odometer.odometer-theme-plaza .odometer-digit {
114 | -moz-border-radius: 0.1em;
115 | -webkit-border-radius: 0.1em;
116 | border-radius: 0.1em;
117 | padding: 0 0.03em;
118 | color: #648baf;
119 | }
120 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-inner,
121 | .odometer.odometer-theme-plaza .odometer-digit .odometer-digit-inner {
122 | left: 0.03em;
123 | }
124 | `;
125 |
--------------------------------------------------------------------------------
/src/odometer/themes/digital.theme.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Jose Andres on 02.23.17
3 | */
4 |
5 | export const DIGITAL_THEME = `
6 | @import url("//fonts.googleapis.com/css?family=Wallpoet");
7 | .odometer.odometer-auto-theme,
8 | .odometer.odometer-theme-digital {
9 | display: inline-block;
10 | vertical-align: middle;
11 | *vertical-align: auto;
12 | *zoom: 1;
13 | *display: inline;
14 | position: relative;
15 | }
16 | .odometer.odometer-auto-theme .odometer-digit,
17 | .odometer.odometer-theme-digital .odometer-digit {
18 | display: inline-block;
19 | vertical-align: middle;
20 | *vertical-align: auto;
21 | *zoom: 1;
22 | *display: inline;
23 | position: relative;
24 | }
25 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-spacer,
26 | .odometer.odometer-theme-digital .odometer-digit .odometer-digit-spacer {
27 | display: inline-block;
28 | vertical-align: middle;
29 | *vertical-align: auto;
30 | *zoom: 1;
31 | *display: inline;
32 | visibility: hidden;
33 | }
34 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-inner,
35 | .odometer.odometer-theme-digital .odometer-digit .odometer-digit-inner {
36 | text-align: left;
37 | display: block;
38 | position: absolute;
39 | top: 0;
40 | left: 0;
41 | right: 0;
42 | bottom: 0;
43 | overflow: hidden;
44 | }
45 | .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon,
46 | .odometer.odometer-theme-digital .odometer-digit .odometer-ribbon {
47 | display: block;
48 | }
49 | .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon-inner,
50 | .odometer.odometer-theme-digital .odometer-digit .odometer-ribbon-inner {
51 | display: block;
52 | -webkit-backface-visibility: hidden;
53 | }
54 | .odometer.odometer-auto-theme .odometer-digit .odometer-value,
55 | .odometer.odometer-theme-digital .odometer-digit .odometer-value {
56 | display: block;
57 | -webkit-transform: translateZ(0);
58 | }
59 | .odometer.odometer-auto-theme .odometer-digit .odometer-value.odometer-last-value,
60 | .odometer.odometer-theme-digital .odometer-digit .odometer-value.odometer-last-value {
61 | position: absolute;
62 | }
63 | .odometer.odometer-auto-theme.odometer-animating-up .odometer-ribbon-inner,
64 | .odometer.odometer-theme-digital.odometer-animating-up .odometer-ribbon-inner {
65 | -webkit-transition: -webkit-transform 2s;
66 | -moz-transition: -moz-transform 2s;
67 | -ms-transition: -ms-transform 2s;
68 | -o-transition: -o-transform 2s;
69 | transition: transform 2s;
70 | }
71 | .odometer.odometer-auto-theme.odometer-animating-up.odometer-animating .odometer-ribbon-inner,
72 | .odometer.odometer-theme-digital.odometer-animating-up.odometer-animating .odometer-ribbon-inner {
73 | -webkit-transform: translateY(-100%);
74 | -moz-transform: translateY(-100%);
75 | -ms-transform: translateY(-100%);
76 | -o-transform: translateY(-100%);
77 | transform: translateY(-100%);
78 | }
79 | .odometer.odometer-auto-theme.odometer-animating-down .odometer-ribbon-inner,
80 | .odometer.odometer-theme-digital.odometer-animating-down .odometer-ribbon-inner {
81 | -webkit-transform: translateY(-100%);
82 | -moz-transform: translateY(-100%);
83 | -ms-transform: translateY(-100%);
84 | -o-transform: translateY(-100%);
85 | transform: translateY(-100%);
86 | }
87 | .odometer.odometer-auto-theme.odometer-animating-down.odometer-animating .odometer-ribbon-inner,
88 | .odometer.odometer-theme-digital.odometer-animating-down.odometer-animating .odometer-ribbon-inner {
89 | -webkit-transition: -webkit-transform 2s;
90 | -moz-transition: -moz-transform 2s;
91 | -ms-transition: -ms-transform 2s;
92 | -o-transition: -o-transform 2s;
93 | transition: transform 2s;
94 | -webkit-transform: translateY(0);
95 | -moz-transform: translateY(0);
96 | -ms-transform: translateY(0);
97 | -o-transform: translateY(0);
98 | transform: translateY(0);
99 | }
100 | .odometer.odometer-auto-theme,
101 | .odometer.odometer-theme-digital {
102 | background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHJhZGlhbEdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY3g9IjUwJSIgY3k9IjUwJSIgcj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzhiZjVhNSIgc3RvcC1vcGFjaXR5PSIwLjQiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiLz48L3JhZGlhbEdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA=');
103 | background-size: 100%;
104 | background-image: -moz-radial-gradient(rgba(139, 245, 165, 0.4), #000000);
105 | background-image: -webkit-radial-gradient(rgba(139, 245, 165, 0.4), #000000);
106 | background-image: radial-gradient(rgba(139, 245, 165, 0.4), #000000);
107 | background-color: #000;
108 | font-family: "Wallpoet", monospace;
109 | padding: 0 0.2em;
110 | line-height: 1.1em;
111 | color: #8bf5a5;
112 | }
113 | .odometer.odometer-auto-theme .odometer-digit + .odometer-digit,
114 | .odometer.odometer-theme-digital .odometer-digit + .odometer-digit {
115 | margin-left: 0.1em;
116 | }
117 | `;
118 |
--------------------------------------------------------------------------------
/src/odometer/odometer.component.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | /**
4 | * Created by Jose Andres on 6.15.17
5 | */
6 |
7 | import * as _ from 'lodash';
8 | import { Component, ViewEncapsulation, Input, OnInit, OnDestroy, OnChanges, AfterViewInit, ViewChild, ElementRef } from '@angular/core';
9 | import { Observable } from 'rxjs/Observable';
10 | import { Subscription } from 'rxjs/Subscription';
11 | import { OdometerModel } from './odometer.model';
12 | import { Ng2OdometerConfig, Ng2OdometerConfigModel } from './odometer.config';
13 | import {
14 | CAR_THEME,
15 | DEFAULT_THEME,
16 | DIGITAL_THEME,
17 | MINIMAL_THEME,
18 | PLAZA_THEME,
19 | SLOT_MACHINE_THEME,
20 | TRAIN_STATION_THEME,
21 | } from './themes';
22 |
23 | // HubSpot's Oodometer
24 | // https://github.com/HubSpot/odometer
25 | const Odometer = require('odometer');
26 |
27 | @Component({
28 | selector: 'ng2-odometer',
29 | encapsulation: ViewEncapsulation.None,
30 | styles: [
31 | CAR_THEME,
32 | DEFAULT_THEME,
33 | DIGITAL_THEME,
34 | MINIMAL_THEME,
35 | PLAZA_THEME,
36 | SLOT_MACHINE_THEME,
37 | TRAIN_STATION_THEME,
38 | `
39 | .odometer,
40 | .odometer-inside,
41 | .odometer-digit,
42 | .odometer-digit-spacer,
43 | .odometer-digit-inner,
44 | .odometer-ribbon,
45 | .odometer-ribbon-inner,
46 | .odometer-value,
47 | .odometer-formatting-mark {
48 | color: inherit;
49 | font-size: inherit;
50 | font-family: inherit;
51 | }
52 | `,
53 | ],
54 | template: ``
55 | })
56 | export class Ng2OdometerComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit {
57 | private subscription: Subscription;
58 | private odometer: OdometerModel;
59 | @ViewChild('container', { read: ElementRef }) container: ElementRef;
60 | @Input() number: number; // Required
61 | @Input() config: Ng2OdometerConfigModel = {};
62 | @Input() observable: Observable = undefined;
63 |
64 | // Individual configuration attributes
65 | @Input() animation: string = undefined;
66 | @Input() format: string = undefined;
67 | @Input() theme: string = undefined;
68 | @Input() value: number = undefined;
69 | @Input() duration: number = undefined;
70 | @Input() auto: boolean = undefined;
71 |
72 | // Available themes
73 | private themes: Array = [
74 | 'car',
75 | 'default',
76 | 'digital',
77 | 'minimal',
78 | 'plaza',
79 | 'slot-machine',
80 | 'train-station'
81 | ];
82 |
83 | // Start Odometer
84 | private initOdometer() {
85 | if (!_.isUndefined(this.container)
86 | && typeof Odometer !== 'undefined') {
87 |
88 | this.odometer = new Odometer({
89 | el: this.container.nativeElement,
90 | animation: this.config.animation,
91 | value: this.config.value,
92 | duration: this.config.duration,
93 | format: this.config.format,
94 | theme: this.config.theme,
95 | });
96 |
97 | if (!_.isUndefined(this.number) && this.config.auto) {
98 | this.odometer.update(this.number);
99 | }
100 | }
101 | }
102 |
103 | private initConfig() {
104 | this.config = _.defaults(this.config, new Ng2OdometerConfig());
105 |
106 | // Animation
107 | if (!_.isUndefined(this.animation)) {
108 | this.config.animation = this.animation;
109 | }
110 |
111 | // Format
112 | if (!_.isUndefined(this.format)) {
113 | this.config.format = this.format;
114 | }
115 |
116 | // Theme
117 | if (!_.isUndefined(this.theme)) {
118 | this.config.theme = !_.includes(this.themes, this.theme) ? 'default' : this.theme;
119 | }
120 |
121 | // Value
122 | if (!_.isUndefined(this.value)) {
123 | this.config.value = this.value;
124 | }
125 |
126 | // Duration
127 | if (!_.isUndefined(this.duration)) {
128 | this.config.duration = this.duration;
129 | }
130 |
131 | // Auto
132 | if (!_.isUndefined(this.auto)) {
133 | this.config.auto = this.auto;
134 | }
135 |
136 | // Validate theme. If not part of the
137 | // available themes array, use the default
138 | if (!_.includes(this.themes, this.config.theme)) {
139 | this.config.theme = 'default';
140 | }
141 | }
142 |
143 | // ***************************************
144 | // LIFECYCLES
145 | // ***************************************
146 |
147 | public ngOnInit() {
148 |
149 | // Bind Observable
150 | if (!_.isUndefined(this.observable) && !this.config.auto) {
151 | this.subscription = this.observable.subscribe((trigger: boolean) => {
152 | if (!_.isUndefined(trigger) && trigger) {
153 | this.odometer.update(this.number);
154 | }
155 | });
156 | }
157 |
158 | // Apply defaults and
159 | // individual configurations
160 | this.initConfig();
161 | }
162 |
163 | public ngOnDestroy() {
164 | if (!_.isUndefined(this.subscription)) {
165 | this.subscription.unsubscribe();
166 | }
167 | }
168 |
169 | public ngOnChanges() {
170 | if (!_.isUndefined(this.number) && !_.isUndefined(this.odometer) && this.config.auto) {
171 | this.odometer.update(this.number);
172 | }
173 | }
174 |
175 | public ngAfterViewInit() {
176 | this.initOdometer();
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ng2-odometer [](https://www.npmjs.com/package/ng2-odometer) [](http://opensource.org/licenses/MIT)
2 |
3 | Odometer for Angular2 that wraps HubSpot's Odometer [http://github.hubspot.com/odometer/docs/welcome/](http://github.hubspot.com/odometer/docs/welcome/)
4 |
5 | ## Quick Start
6 |
7 | ```
8 | npm install ng2-odometer --save
9 | ```
10 |
11 | ## Table of contents
12 |
13 | - [Setup](#setup)
14 | - [Usage](#usage)
15 | - [Configuration](#configuration)
16 | - [Demo](#demo)
17 |
18 | ## Setup
19 |
20 | First you need to install the npm module:
21 | ```sh
22 | npm install ng2-odometer --save
23 | ```
24 |
25 | Then add the `Ng2OdometerModule` to the imports array of your application module.
26 |
27 | ```typescript
28 | import { NgModule } from '@angular/core';
29 | import { BrowserModule } from '@angular/platform-browser';
30 | import { Ng2OdometerModule } from 'ng2-odometer'; // <-- import the module
31 | import { AppComponent} from './app.component';
32 |
33 | @NgModule({
34 | imports: [
35 | BrowserModule,
36 | Ng2OdometerModule.forRoot() // <-- include it in your app module
37 | ],
38 | declarations: [AppComponent],
39 | bootstrap: [AppComponent]
40 | })
41 | export class AppModule {
42 | //
43 | }
44 | ```
45 |
46 | ## Usage
47 |
48 | Use the `` component to create an odometer. The `number` is required attribute.
49 | The `number` represents the limit at which the odometer will travel. The `config` an object with the configuration properties, this is NOT required.
50 |
51 | ```js
52 | @Component({
53 | selector: 'main-element',
54 | template: `
55 | ...
56 |
57 |
58 | ...
59 | `
60 | })
61 | export class MainElementComponent {
62 | public number: number = 1000;
63 | }
64 | ```
65 |
66 | When on manual mode (`[config]="{ auto: false }"`), you can update the `number` attribute and that will trigger an odometer update right away. The `observable` is an Observable which will be used as a trigger for the odometer when on manual mode.
67 |
68 | ```js
69 | @Component({
70 | selector: 'main-element',
71 | template: `
72 | ...
73 |
74 |
75 | ...
76 | `
77 | })
78 | export class MainElementComponent {
79 | public number: number = 1000;
80 | public observable: Observable;
81 | private observer: Observer;
82 |
83 | constructor() {
84 | this.observable = new Observable((observer: any) => this.observer = observer).share();
85 |
86 | // Trigger odometer after 2s
87 | setTimeout(() => this.observer.next(true), 2000);
88 | }
89 | }
90 | ```
91 |
92 | ## Configuration
93 |
94 | The component accepts either a `[config]="{ ... }"` attribute with an object with all the configurable attribues or independent attributes for each configuration.
95 |
96 | | Option | Type | Default | Description |
97 | | --------------| --------- | ----------- |-------------- |
98 | | `animation` | string | 'slide' | Animation effect type.
Options: 'slide', 'count'
99 | | `format` | string | '(,ddd)' | Format to apply on the numbers.
Format - Example:
(,ddd) - 12,345,678
(,ddd).dd - 12,345,678.09
(.ddd),dd - 12.345.678,09
( ddd),dd - 12 345 678,09
d - 12345678
100 | | `theme` | string | 'default' | The desired theme.
Options: 'default', 'minima', 'digital', 'car', 'plaza', 'slot-machine', 'train-station'
101 | | `value` | number | 0 | Initial value of the odometer
102 | | `auto` | boolean | true | Setup auto or manual mode for the odometer
103 |
104 | ```js
105 | @Component({
106 | selector: 'main-element',
107 | template: `
108 | ...
109 |
113 |
114 |
115 |
119 |
120 |
121 |
122 |
130 |
131 |
132 | ...
133 | `
134 | })
135 | export class MainElementComponent {
136 | public config = {
137 | animation: 'count',
138 | format: 'd',
139 | theme: 'car',
140 | value: 50,
141 | auto: true,
142 | }
143 |
144 | ...
145 | }
146 | ```
147 |
148 | If you add both, the `[config]` and any independent configuration, the independent config will overwrite the `[config]` object.
149 |
150 | ## Demo
151 |
152 | The [demo](demo) subfolder contains a project created with angular-cli that has been adapted to showcase the functionality of ng2-odometer.
153 | To execute the code follow this steps:
154 |
155 | ```
156 | // Go the the demo folder
157 | cd demo
158 |
159 | // Install dependencies
160 | npm install
161 |
162 | // Run the server
163 | ng serve
164 | ```
165 |
166 | Then go to [http://localhost:4200](http://localhost:4200/) to check the demo running.
167 |
168 | ## TODO:
169 |
170 | * Update to Angular4
171 | * Add tests to the library and demo
172 | * Add new themes
173 | * Create a Directive also
174 |
175 | ## License
176 |
177 | [MIT](LICENSE)
178 |
--------------------------------------------------------------------------------
/src/odometer/themes/train-station.theme.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Jose Andres on 02.23.17
3 | */
4 |
5 | export const TRAIN_STATION_THEME = `
6 | @import url("//fonts.googleapis.com/css?family=Economica");
7 | .odometer.odometer-auto-theme,
8 | .odometer.odometer-theme-train-station {
9 | display: inline-block;
10 | vertical-align: middle;
11 | *vertical-align: auto;
12 | *zoom: 1;
13 | *display: inline;
14 | position: relative;
15 | }
16 | .odometer.odometer-auto-theme .odometer-digit,
17 | .odometer.odometer-theme-train-station .odometer-digit {
18 | display: inline-block;
19 | vertical-align: middle;
20 | *vertical-align: auto;
21 | *zoom: 1;
22 | *display: inline;
23 | position: relative;
24 | }
25 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-spacer,
26 | .odometer.odometer-theme-train-station .odometer-digit .odometer-digit-spacer {
27 | display: inline-block;
28 | vertical-align: middle;
29 | *vertical-align: auto;
30 | *zoom: 1;
31 | *display: inline;
32 | visibility: hidden;
33 | }
34 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-inner,
35 | .odometer.odometer-theme-train-station .odometer-digit .odometer-digit-inner {
36 | text-align: left;
37 | display: block;
38 | position: absolute;
39 | top: 0;
40 | left: 0;
41 | right: 0;
42 | bottom: 0;
43 | overflow: hidden;
44 | }
45 | .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon,
46 | .odometer.odometer-theme-train-station .odometer-digit .odometer-ribbon {
47 | display: block;
48 | }
49 | .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon-inner,
50 | .odometer.odometer-theme-train-station .odometer-digit .odometer-ribbon-inner {
51 | display: block;
52 | -webkit-backface-visibility: hidden;
53 | }
54 | .odometer.odometer-auto-theme .odometer-digit .odometer-value,
55 | .odometer.odometer-theme-train-station .odometer-digit .odometer-value {
56 | display: block;
57 | -webkit-transform: translateZ(0);
58 | }
59 | .odometer.odometer-auto-theme .odometer-digit .odometer-value.odometer-last-value,
60 | .odometer.odometer-theme-train-station .odometer-digit .odometer-value.odometer-last-value {
61 | position: absolute;
62 | }
63 | .odometer.odometer-auto-theme.odometer-animating-up .odometer-ribbon-inner,
64 | .odometer.odometer-theme-train-station.odometer-animating-up .odometer-ribbon-inner {
65 | -webkit-transition: -webkit-transform 2s;
66 | -moz-transition: -moz-transform 2s;
67 | -ms-transition: -ms-transform 2s;
68 | -o-transition: -o-transform 2s;
69 | transition: transform 2s;
70 | }
71 | .odometer.odometer-auto-theme.odometer-animating-up.odometer-animating .odometer-ribbon-inner,
72 | .odometer.odometer-theme-train-station.odometer-animating-up.odometer-animating .odometer-ribbon-inner {
73 | -webkit-transform: translateY(-100%);
74 | -moz-transform: translateY(-100%);
75 | -ms-transform: translateY(-100%);
76 | -o-transform: translateY(-100%);
77 | transform: translateY(-100%);
78 | }
79 | .odometer.odometer-auto-theme.odometer-animating-down .odometer-ribbon-inner,
80 | .odometer.odometer-theme-train-station.odometer-animating-down .odometer-ribbon-inner {
81 | -webkit-transform: translateY(-100%);
82 | -moz-transform: translateY(-100%);
83 | -ms-transform: translateY(-100%);
84 | -o-transform: translateY(-100%);
85 | transform: translateY(-100%);
86 | }
87 | .odometer.odometer-auto-theme.odometer-animating-down.odometer-animating .odometer-ribbon-inner,
88 | .odometer.odometer-theme-train-station.odometer-animating-down.odometer-animating .odometer-ribbon-inner {
89 | -webkit-transition: -webkit-transform 2s;
90 | -moz-transition: -moz-transform 2s;
91 | -ms-transition: -ms-transform 2s;
92 | -o-transition: -o-transform 2s;
93 | transition: transform 2s;
94 | -webkit-transform: translateY(0);
95 | -moz-transform: translateY(0);
96 | -ms-transform: translateY(0);
97 | -o-transform: translateY(0);
98 | transform: translateY(0);
99 | }
100 | .odometer.odometer-auto-theme,
101 | .odometer.odometer-theme-train-station {
102 | font-family: "Economica", sans-serif;
103 | }
104 | .odometer.odometer-auto-theme .odometer-digit,
105 | .odometer.odometer-theme-train-station .odometer-digit {
106 | display: inline-block;
107 | vertical-align: middle;
108 | *vertical-align: auto;
109 | *zoom: 1;
110 | *display: inline;
111 | -moz-border-radius: 0.1em;
112 | -webkit-border-radius: 0.1em;
113 | border-radius: 0.1em;
114 | background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzExMTExMSIvPjxzdG9wIG9mZnNldD0iMzUlIiBzdG9wLWNvbG9yPSIjMTExMTExIi8+PHN0b3Agb2Zmc2V0PSI1NSUiIHN0b3AtY29sb3I9IiMzMzMzMzMiLz48c3RvcCBvZmZzZXQ9IjU1JSIgc3RvcC1jb2xvcj0iIzExMTExMSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzExMTExMSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
115 | background-size: 100%;
116 | background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #111111), color-stop(35%, #111111), color-stop(55%, #333333), color-stop(55%, #111111), color-stop(100%, #111111));
117 | background-image: -moz-linear-gradient(top, #111111 0%, #111111 35%, #333333 55%, #111111 55%, #111111 100%);
118 | background-image: -webkit-linear-gradient(top, #111111 0%, #111111 35%, #333333 55%, #111111 55%, #111111 100%);
119 | background-image: linear-gradient(to bottom, #111111 0%, #111111 35%, #333333 55%, #111111 55%, #111111 100%);
120 | background-color: #222;
121 | padding: 0 0.15em;
122 | color: #fff;
123 | }
124 | .odometer.odometer-auto-theme .odometer-digit + .odometer-digit,
125 | .odometer.odometer-theme-train-station .odometer-digit + .odometer-digit {
126 | margin-left: 0.1em;
127 | }
128 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-inner,
129 | .odometer.odometer-theme-train-station .odometer-digit .odometer-digit-inner {
130 | left: 0.15em;
131 | }
132 | `;
133 |
--------------------------------------------------------------------------------
/src/odometer/themes/car.theme.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Jose Andres on 02.23.17
3 | */
4 |
5 | export const CAR_THEME = `
6 | @import url("//fonts.googleapis.com/css?family=Arimo");
7 | .odometer.odometer-auto-theme,
8 | .odometer.odometer-theme-car {
9 | display: inline-block;
10 | vertical-align: middle;
11 | *vertical-align: auto;
12 | *zoom: 1;
13 | *display: inline;
14 | position: relative;
15 | }
16 | .odometer.odometer-auto-theme .odometer-digit,
17 | .odometer.odometer-theme-car .odometer-digit {
18 | display: inline-block;
19 | vertical-align: middle;
20 | *vertical-align: auto;
21 | *zoom: 1;
22 | *display: inline;
23 | position: relative;
24 | }
25 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-spacer,
26 | .odometer.odometer-theme-car .odometer-digit .odometer-digit-spacer {
27 | display: inline-block;
28 | vertical-align: middle;
29 | *vertical-align: auto;
30 | *zoom: 1;
31 | *display: inline;
32 | visibility: hidden;
33 | }
34 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-inner,
35 | .odometer.odometer-theme-car .odometer-digit .odometer-digit-inner {
36 | text-align: left;
37 | display: block;
38 | position: absolute;
39 | top: 0;
40 | left: 0;
41 | right: 0;
42 | bottom: 0;
43 | overflow: hidden;
44 | }
45 | .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon,
46 | .odometer.odometer-theme-car .odometer-digit .odometer-ribbon {
47 | display: block;
48 | }
49 | .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon-inner,
50 | .odometer.odometer-theme-car .odometer-digit .odometer-ribbon-inner {
51 | display: block;
52 | -webkit-backface-visibility: hidden;
53 | }
54 | .odometer.odometer-auto-theme .odometer-digit .odometer-value,
55 | .odometer.odometer-theme-car .odometer-digit .odometer-value {
56 | display: block;
57 | -webkit-transform: translateZ(0);
58 | }
59 | .odometer.odometer-auto-theme .odometer-digit .odometer-value.odometer-last-value,
60 | .odometer.odometer-theme-car .odometer-digit .odometer-value.odometer-last-value {
61 | position: absolute;
62 | }
63 | .odometer.odometer-auto-theme.odometer-animating-up .odometer-ribbon-inner,
64 | .odometer.odometer-theme-car.odometer-animating-up .odometer-ribbon-inner {
65 | -webkit-transition: -webkit-transform 2s;
66 | -moz-transition: -moz-transform 2s;
67 | -ms-transition: -ms-transform 2s;
68 | -o-transition: -o-transform 2s;
69 | transition: transform 2s;
70 | }
71 | .odometer.odometer-auto-theme.odometer-animating-up.odometer-animating .odometer-ribbon-inner,
72 | .odometer.odometer-theme-car.odometer-animating-up.odometer-animating .odometer-ribbon-inner {
73 | -webkit-transform: translateY(-100%);
74 | -moz-transform: translateY(-100%);
75 | -ms-transform: translateY(-100%);
76 | -o-transform: translateY(-100%);
77 | transform: translateY(-100%);
78 | }
79 | .odometer.odometer-auto-theme.odometer-animating-down .odometer-ribbon-inner,
80 | .odometer.odometer-theme-car.odometer-animating-down .odometer-ribbon-inner {
81 | -webkit-transform: translateY(-100%);
82 | -moz-transform: translateY(-100%);
83 | -ms-transform: translateY(-100%);
84 | -o-transform: translateY(-100%);
85 | transform: translateY(-100%);
86 | }
87 | .odometer.odometer-auto-theme.odometer-animating-down.odometer-animating .odometer-ribbon-inner,
88 | .odometer.odometer-theme-car.odometer-animating-down.odometer-animating .odometer-ribbon-inner {
89 | -webkit-transition: -webkit-transform 2s;
90 | -moz-transition: -moz-transform 2s;
91 | -ms-transition: -ms-transform 2s;
92 | -o-transition: -o-transform 2s;
93 | transition: transform 2s;
94 | -webkit-transform: translateY(0);
95 | -moz-transform: translateY(0);
96 | -ms-transform: translateY(0);
97 | -o-transform: translateY(0);
98 | transform: translateY(0);
99 | }
100 | .odometer.odometer-auto-theme,
101 | .odometer.odometer-theme-car {
102 | -moz-border-radius: 0.34em;
103 | -webkit-border-radius: 0.34em;
104 | border-radius: 0.34em;
105 | font-family: "Arimo", monospace;
106 | padding: 0.15em;
107 | background: #000;
108 | color: #eee0d3;
109 | }
110 | .odometer.odometer-auto-theme .odometer-digit,
111 | .odometer.odometer-theme-car .odometer-digit {
112 | -moz-box-shadow: inset 0 0 0.3em rgba(0, 0, 0, 0.8);
113 | -webkit-box-shadow: inset 0 0 0.3em rgba(0, 0, 0, 0.8);
114 | box-shadow: inset 0 0 0.3em rgba(0, 0, 0, 0.8);
115 | background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzMzMzMzMyIvPjxzdG9wIG9mZnNldD0iNDAlIiBzdG9wLWNvbG9yPSIjMzMzMzMzIi8+PHN0b3Agb2Zmc2V0PSI2MCUiIHN0b3AtY29sb3I9IiMxMDEwMTAiLz48c3RvcCBvZmZzZXQ9IjgwJSIgc3RvcC1jb2xvcj0iIzMzMzMzMyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzMzMzMzMyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
116 | background-size: 100%;
117 | background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #333333), color-stop(40%, #333333), color-stop(60%, #101010), color-stop(80%, #333333), color-stop(100%, #333333));
118 | background-image: -moz-linear-gradient(top, #333333 0%, #333333 40%, #101010 60%, #333333 80%, #333333 100%);
119 | background-image: -webkit-linear-gradient(top, #333333 0%, #333333 40%, #101010 60%, #333333 80%, #333333 100%);
120 | background-image: linear-gradient(to bottom, #333333 0%, #333333 40%, #101010 60%, #333333 80%, #333333 100%);
121 | padding: 0 0.15em;
122 | }
123 | .odometer.odometer-auto-theme .odometer-digit:first-child,
124 | .odometer.odometer-theme-car .odometer-digit:first-child {
125 | -moz-border-radius: 0.2em 0 0 0.2em;
126 | -webkit-border-radius: 0.2em;
127 | border-radius: 0.2em 0 0 0.2em;
128 | }
129 | .odometer.odometer-auto-theme .odometer-digit:last-child,
130 | .odometer.odometer-theme-car .odometer-digit:last-child {
131 | -moz-border-radius: 0 0.2em 0.2em 0;
132 | -webkit-border-radius: 0;
133 | border-radius: 0 0.2em 0.2em 0;
134 | background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2VlZTBkMyIvPjxzdG9wIG9mZnNldD0iNDAlIiBzdG9wLWNvbG9yPSIjZWVlMGQzIi8+PHN0b3Agb2Zmc2V0PSI2MCUiIHN0b3AtY29sb3I9IiNiYmFhOWEiLz48c3RvcCBvZmZzZXQ9IjgwJSIgc3RvcC1jb2xvcj0iI2VlZTBkMyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2VlZTBkMyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
135 | background-size: 100%;
136 | background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #eee0d3), color-stop(40%, #eee0d3), color-stop(60%, #bbaa9a), color-stop(80%, #eee0d3), color-stop(100%, #eee0d3));
137 | background-image: -moz-linear-gradient(top, #eee0d3 0%, #eee0d3 40%, #bbaa9a 60%, #eee0d3 80%, #eee0d3 100%);
138 | background-image: -webkit-linear-gradient(top, #eee0d3 0%, #eee0d3 40%, #bbaa9a 60%, #eee0d3 80%, #eee0d3 100%);
139 | background-image: linear-gradient(to bottom, #eee0d3 0%, #eee0d3 40%, #bbaa9a 60%, #eee0d3 80%, #eee0d3 100%);
140 | background-color: #eee0d3;
141 | color: #000;
142 | }
143 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-inner,
144 | .odometer.odometer-theme-car .odometer-digit .odometer-digit-inner {
145 | left: 0.15em;
146 | }
147 | .odometer.odometer-auto-theme.odometer-animating-up .odometer-ribbon-inner,
148 | .odometer.odometer-auto-theme.odometer-animating-down.odometer-animating .odometer-ribbon-inner,
149 | .odometer.odometer-theme-car.odometer-animating-up .odometer-ribbon-inner,
150 | .odometer.odometer-theme-car.odometer-animating-down.odometer-animating .odometer-ribbon-inner {
151 | -webkit-transition-timing-function: linear;
152 | -moz-transition-timing-function: linear;
153 | -ms-transition-timing-function: linear;
154 | -o-transition-timing-function: linear;
155 | transition-timing-function: linear;
156 | }
157 | `;
158 |
--------------------------------------------------------------------------------
/src/odometer/themes/slot-machine.theme.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Jose Andres on 02.23.17
3 | */
4 |
5 | export const SLOT_MACHINE_THEME = `
6 | @import url("//fonts.googleapis.com/css?family=Rye");
7 | .odometer.odometer-auto-theme,
8 | .odometer.odometer-theme-slot-machine {
9 | display: inline-block;
10 | vertical-align: middle;
11 | *vertical-align: auto;
12 | *zoom: 1;
13 | *display: inline;
14 | position: relative;
15 | }
16 | .odometer.odometer-auto-theme .odometer-digit,
17 | .odometer.odometer-theme-slot-machine .odometer-digit {
18 | display: inline-block;
19 | vertical-align: middle;
20 | *vertical-align: auto;
21 | *zoom: 1;
22 | *display: inline;
23 | position: relative;
24 | }
25 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-spacer,
26 | .odometer.odometer-theme-slot-machine .odometer-digit .odometer-digit-spacer {
27 | display: inline-block;
28 | vertical-align: middle;
29 | *vertical-align: auto;
30 | *zoom: 1;
31 | *display: inline;
32 | visibility: hidden;
33 | }
34 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-inner,
35 | .odometer.odometer-theme-slot-machine .odometer-digit .odometer-digit-inner {
36 | text-align: left;
37 | display: block;
38 | position: absolute;
39 | top: 0;
40 | left: 0;
41 | right: 0;
42 | bottom: 0;
43 | overflow: hidden;
44 | }
45 | .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon,
46 | .odometer.odometer-theme-slot-machine .odometer-digit .odometer-ribbon {
47 | display: block;
48 | }
49 | .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon-inner,
50 | .odometer.odometer-theme-slot-machine .odometer-digit .odometer-ribbon-inner {
51 | display: block;
52 | -webkit-backface-visibility: hidden;
53 | }
54 | .odometer.odometer-auto-theme .odometer-digit .odometer-value,
55 | .odometer.odometer-theme-slot-machine .odometer-digit .odometer-value {
56 | display: block;
57 | -webkit-transform: translateZ(0);
58 | }
59 | .odometer.odometer-auto-theme .odometer-digit .odometer-value.odometer-last-value,
60 | .odometer.odometer-theme-slot-machine .odometer-digit .odometer-value.odometer-last-value {
61 | position: absolute;
62 | }
63 | .odometer.odometer-auto-theme.odometer-animating-up .odometer-ribbon-inner,
64 | .odometer.odometer-theme-slot-machine.odometer-animating-up .odometer-ribbon-inner {
65 | -webkit-transition: -webkit-transform 2s;
66 | -moz-transition: -moz-transform 2s;
67 | -ms-transition: -ms-transform 2s;
68 | -o-transition: -o-transform 2s;
69 | transition: transform 2s;
70 | }
71 | .odometer.odometer-auto-theme.odometer-animating-up.odometer-animating .odometer-ribbon-inner,
72 | .odometer.odometer-theme-slot-machine.odometer-animating-up.odometer-animating .odometer-ribbon-inner {
73 | -webkit-transform: translateY(-100%);
74 | -moz-transform: translateY(-100%);
75 | -ms-transform: translateY(-100%);
76 | -o-transform: translateY(-100%);
77 | transform: translateY(-100%);
78 | }
79 | .odometer.odometer-auto-theme.odometer-animating-down .odometer-ribbon-inner,
80 | .odometer.odometer-theme-slot-machine.odometer-animating-down .odometer-ribbon-inner {
81 | -webkit-transform: translateY(-100%);
82 | -moz-transform: translateY(-100%);
83 | -ms-transform: translateY(-100%);
84 | -o-transform: translateY(-100%);
85 | transform: translateY(-100%);
86 | }
87 | .odometer.odometer-auto-theme.odometer-animating-down.odometer-animating .odometer-ribbon-inner,
88 | .odometer.odometer-theme-slot-machine.odometer-animating-down.odometer-animating .odometer-ribbon-inner {
89 | -webkit-transition: -webkit-transform 2s;
90 | -moz-transition: -moz-transform 2s;
91 | -ms-transition: -ms-transform 2s;
92 | -o-transition: -o-transform 2s;
93 | transition: transform 2s;
94 | -webkit-transform: translateY(0);
95 | -moz-transform: translateY(0);
96 | -ms-transform: translateY(0);
97 | -o-transform: translateY(0);
98 | transform: translateY(0);
99 | }
100 | .odometer.odometer-auto-theme,
101 | .odometer.odometer-theme-slot-machine {
102 | -moz-border-radius: 0.34em;
103 | -webkit-border-radius: 0.34em;
104 | border-radius: 0.34em;
105 | background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZmZmYwMCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2ZmYTUwMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
106 | background-size: 100%;
107 | background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffff00), color-stop(100%, #ffa500));
108 | background-image: -moz-linear-gradient(#ffff00, #ffa500);
109 | background-image: -webkit-linear-gradient(#ffff00, #ffa500);
110 | background-image: linear-gradient(#ffff00, #ffa500);
111 | background-color: #fc0;
112 | font-family: "Rye", monospace;
113 | padding: 0.15em;
114 | color: #f80000;
115 | line-height: 1.35em;
116 | border: 0.03em solid #000;
117 | -webkit-text-stroke: 0.05em #000;
118 | }
119 | .odometer.odometer-auto-theme .odometer-digit,
120 | .odometer.odometer-theme-slot-machine .odometer-digit {
121 | -moz-box-shadow: inset 0 0 0.1em rgba(0, 0, 0, 0.5), 0 0 0 0.03em #fff, 0 0 0 0.05em rgba(0, 0, 0, 0.2);
122 | -webkit-box-shadow: inset 0 0 0.1em rgba(0, 0, 0, 0.5), 0 0 0 0.03em #fff, 0 0 0 0.05em rgba(0, 0, 0, 0.2);
123 | box-shadow: inset 0 0 0.1em rgba(0, 0, 0, 0.5), 0 0 0 0.03em #fff, 0 0 0 0.05em rgba(0, 0, 0, 0.2);
124 | -moz-border-radius: 0.2em;
125 | -webkit-border-radius: 0.2em;
126 | border-radius: 0.2em;
127 | background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2NjY2NjYyIvPjxzdG9wIG9mZnNldD0iMjAlIiBzdG9wLWNvbG9yPSIjZmZmZmZmIi8+PHN0b3Agb2Zmc2V0PSI4MCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNjY2NjY2MiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA=');
128 | background-size: 100%;
129 | background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #cccccc), color-stop(20%, #ffffff), color-stop(80%, #ffffff), color-stop(100%, #cccccc));
130 | background-image: -moz-linear-gradient(top, #cccccc 0%, #ffffff 20%, #ffffff 80%, #cccccc 100%);
131 | background-image: -webkit-linear-gradient(top, #cccccc 0%, #ffffff 20%, #ffffff 80%, #cccccc 100%);
132 | background-image: linear-gradient(to bottom, #cccccc 0%, #ffffff 20%, #ffffff 80%, #cccccc 100%);
133 | border: 0.03em solid #444;
134 | padding: 0.1em 0.15em 0;
135 | }
136 | .odometer.odometer-auto-theme .odometer-digit:first-child,
137 | .odometer.odometer-theme-slot-machine .odometer-digit:first-child {
138 | -moz-box-shadow: inset 0.05em 0 0.1em rgba(0, 0, 0, 0.5), 0 0 0 0.03em #fff, 0 0 0 0.05em rgba(0, 0, 0, 0.2);
139 | -webkit-box-shadow: inset 0.05em 0 0.1em rgba(0, 0, 0, 0.5), 0 0 0 0.03em #fff, 0 0 0 0.05em rgba(0, 0, 0, 0.2);
140 | box-shadow: inset 0.05em 0 0.1em rgba(0, 0, 0, 0.5), 0 0 0 0.03em #fff, 0 0 0 0.05em rgba(0, 0, 0, 0.2);
141 | }
142 | .odometer.odometer-auto-theme .odometer-digit:last-child,
143 | .odometer.odometer-theme-slot-machine .odometer-digit:last-child {
144 | -moz-box-shadow: inset -0.05em 0 0.1em rgba(0, 0, 0, 0.5), 0 0 0 0.03em #fff, 0 0 0 0.05em rgba(0, 0, 0, 0.2);
145 | -webkit-box-shadow: inset -0.05em 0 0.1em rgba(0, 0, 0, 0.5), 0 0 0 0.03em #fff, 0 0 0 0.05em rgba(0, 0, 0, 0.2);
146 | box-shadow: inset -0.05em 0 0.1em rgba(0, 0, 0, 0.5), 0 0 0 0.03em #fff, 0 0 0 0.05em rgba(0, 0, 0, 0.2);
147 | }
148 | .odometer.odometer-auto-theme .odometer-digit + .odometer-digit,
149 | .odometer.odometer-theme-slot-machine .odometer-digit + .odometer-digit {
150 | margin-left: 0.15em;
151 | }
152 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-inner,
153 | .odometer.odometer-theme-slot-machine .odometer-digit .odometer-digit-inner {
154 | padding-top: 0.08em;
155 | }
156 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-inner,
157 | .odometer.odometer-auto-theme .odometer-digit .odometer-value.odometer-last-value,
158 | .odometer.odometer-theme-slot-machine .odometer-digit .odometer-digit-inner,
159 | .odometer.odometer-theme-slot-machine .odometer-digit .odometer-value.odometer-last-value {
160 | left: 0;
161 | right: 0;
162 | text-align: center;
163 | }
164 | `;
165 |
--------------------------------------------------------------------------------