├── dist
├── CNAME
├── assets
│ ├── favicon.ico
│ └── img
│ │ ├── fav.png
│ │ ├── ads300.gif
│ │ ├── ads300.png
│ │ ├── loading.gif
│ │ └── loading (1).gif
├── components
│ └── common
│ │ ├── footer
│ │ └── footer.tpl.html
│ │ ├── header
│ │ └── header.tpl.html
│ │ └── keyboard
│ │ └── keyboard.tpl.html
├── views
│ ├── home
│ │ └── home.tpl.html
│ ├── editor
│ │ └── editor.tpl.html
│ └── practice
│ │ ├── practice.tpl.html
│ │ └── practise.tpl.html
├── auth
│ ├── login
│ │ └── login.tpl.html
│ └── user-register
│ │ └── user-register.tpl.html
├── 404.html
├── index.html
├── app.css
└── app.min.js
├── client
├── CNAME
├── components
│ ├── common
│ │ ├── header
│ │ │ ├── header.css
│ │ │ ├── header.js
│ │ │ └── header.tpl.html
│ │ ├── footer
│ │ │ ├── footer.css
│ │ │ ├── footer.ctrl.js
│ │ │ └── footer.tpl.html
│ │ └── keyboard
│ │ │ ├── keyboard.component.js
│ │ │ ├── keyboard.tpl.html
│ │ │ └── keyboard.css
│ └── common.module.js
├── assets
│ ├── favicon.ico
│ └── img
│ │ ├── fav.png
│ │ ├── ads300.gif
│ │ ├── ads300.png
│ │ ├── loading.gif
│ │ └── loading (1).gif
├── app.css
├── services
│ ├── capitalisefirst.service.js
│ ├── limitobj.filter.js
│ ├── datafetch.service.js
│ ├── socket.service.js
│ ├── filter.service.js
│ ├── authentication.service.js
│ └── keyboardlayout.service.js
├── views
│ ├── home
│ │ ├── home.tpl.html
│ │ └── home.ctrl.js
│ ├── practice
│ │ ├── practise.css
│ │ ├── practice.tpl.html
│ │ └── practise.ctrl.js
│ └── editor
│ │ ├── editor.ctrl.js
│ │ ├── editor.tpl.html
│ │ └── editor.css
├── auth
│ ├── user-register
│ │ ├── user-register.ctrl.js
│ │ └── user-register.tpl.html
│ └── login
│ │ ├── login.tpl.html
│ │ └── login.controller.js
├── app.js
└── index.html
├── .bowerrc
├── server
├── config.json
├── app
│ ├── routes.js
│ ├── api.controller.js
│ └── app.controller.js
└── server.js
├── .gitignore
├── gulpfiles
├── build.js
├── prodtpl.js
├── uglifycss.js
├── github.js
├── uglify.js
├── app.js
├── watch.js
├── inject.js
├── server.js
└── prod.js
├── e2e-tests
├── protractor.conf.js
└── scenarios.js
├── .travis.yml
├── .jshintrc
├── gulpfile.js
├── karma.conf.js
├── bower.json
├── package.json
├── README.md
└── data
└── type-content
└── strings.json
/dist/CNAME:
--------------------------------------------------------------------------------
1 | typali.mjt.com.np
--------------------------------------------------------------------------------
/client/CNAME:
--------------------------------------------------------------------------------
1 | typali.mjt.com.np
--------------------------------------------------------------------------------
/client/components/common/header/header.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "./bower_components"
3 | }
--------------------------------------------------------------------------------
/client/components/common.module.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('typali.common',[]);
--------------------------------------------------------------------------------
/client/components/common/footer/footer.css:
--------------------------------------------------------------------------------
1 | .footer li a {
2 | margin: 10px;
3 | }
--------------------------------------------------------------------------------
/dist/assets/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emp3ror/typali/HEAD/dist/assets/favicon.ico
--------------------------------------------------------------------------------
/dist/assets/img/fav.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emp3ror/typali/HEAD/dist/assets/img/fav.png
--------------------------------------------------------------------------------
/client/assets/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emp3ror/typali/HEAD/client/assets/favicon.ico
--------------------------------------------------------------------------------
/client/assets/img/fav.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emp3ror/typali/HEAD/client/assets/img/fav.png
--------------------------------------------------------------------------------
/dist/assets/img/ads300.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emp3ror/typali/HEAD/dist/assets/img/ads300.gif
--------------------------------------------------------------------------------
/dist/assets/img/ads300.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emp3ror/typali/HEAD/dist/assets/img/ads300.png
--------------------------------------------------------------------------------
/client/assets/img/ads300.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emp3ror/typali/HEAD/client/assets/img/ads300.gif
--------------------------------------------------------------------------------
/client/assets/img/ads300.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emp3ror/typali/HEAD/client/assets/img/ads300.png
--------------------------------------------------------------------------------
/client/assets/img/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emp3ror/typali/HEAD/client/assets/img/loading.gif
--------------------------------------------------------------------------------
/dist/assets/img/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emp3ror/typali/HEAD/dist/assets/img/loading.gif
--------------------------------------------------------------------------------
/dist/assets/img/loading (1).gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emp3ror/typali/HEAD/dist/assets/img/loading (1).gif
--------------------------------------------------------------------------------
/client/assets/img/loading (1).gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emp3ror/typali/HEAD/client/assets/img/loading (1).gif
--------------------------------------------------------------------------------
/server/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "localApiUri": "http://localhost:8080/api",
3 | "serverApiUri" : ""
4 | }
5 |
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | logs/*
2 | !.gitkeep
3 | node_modules/
4 | bower_components/
5 | public/
6 | tmp
7 | .DS_Store
8 | .idea
9 | .tags
10 | .tags_sorted_by_file
11 | client/configFile.js
12 | *~
13 | \#*\#
--------------------------------------------------------------------------------
/client/components/common/footer/footer.ctrl.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | angular.module('typali')
3 | .controller('FooterCtrl', FooterCtrl);
4 | FooterCtrl.$inject = ['$scope'];
5 |
6 | function FooterCtrl ($scope) {
7 | var vm = this;
8 | }
--------------------------------------------------------------------------------
/gulpfiles/build.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp'),
2 | watch = require('gulp-watch');
3 |
4 | var source = './client';
5 | gulp.task('build',function () {
6 | return gulp.src(source+'/**/*.*', { base: source+'/' })
7 | .pipe(gulp.dest('public'));
8 | });
--------------------------------------------------------------------------------
/gulpfiles/prodtpl.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 |
3 | var print = require('gulp-print');
4 |
5 |
6 |
7 | gulp.task('prodtpl', function () {
8 | var target = gulp.src('./client/**/*.html');
9 |
10 | return target
11 | .pipe(gulp.dest('./dist'));
12 | });
13 |
--------------------------------------------------------------------------------
/client/components/common/header/header.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | angular.module('typali')
3 | .controller('HeaderCtrl', HeaderCtrl)
4 |
5 | HeaderCtrl.$inject = ['$scope','$rootScope'];
6 |
7 | function HeaderCtrl ($scope,$rootScope) {
8 | var vm = this;
9 |
10 |
11 |
12 |
13 |
14 | }
--------------------------------------------------------------------------------
/client/app.css:
--------------------------------------------------------------------------------
1 | html,body {
2 | background: #fff;
3 | font-family: ProximaNova,-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
4 | font-size: 16px;
5 | color: #231f20;
6 | }
7 | /* app css stylesheet */
8 |
9 | .mainView {
10 | min-height: 300px;
11 | margin-bottom: 20px;
12 | }
--------------------------------------------------------------------------------
/client/services/capitalisefirst.service.js:
--------------------------------------------------------------------------------
1 | angular.module('typali').
2 | filter('capitalize', function() {
3 | return function(input, all) {
4 | var reg = (all) ? /([^\W_]+[^\s-]*) */g : /([^\W_]+[^\s-]*)/;
5 | return (!!input) ? input.replace(reg, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}) : '';
6 | }
7 | });
--------------------------------------------------------------------------------
/gulpfiles/uglifycss.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var uglifycss = require('gulp-uglifycss');
3 | var concat = require('gulp-concat');
4 |
5 | gulp.task('uglifycss', function () {
6 | gulp.src('./client/**/*.css')
7 | .pipe(uglifycss({
8 | "maxLineLen": 0,
9 | "uglyComments": true
10 | }))
11 | .pipe(concat('app.css'))
12 | .pipe(gulp.dest('./dist/'));
13 | });
14 |
--------------------------------------------------------------------------------
/e2e-tests/protractor.conf.js:
--------------------------------------------------------------------------------
1 | //jshint strict: false
2 | exports.config = {
3 |
4 | allScriptsTimeout: 11000,
5 |
6 | specs: [
7 | '*.js'
8 | ],
9 |
10 | capabilities: {
11 | 'browserName': 'chrome'
12 | },
13 |
14 | baseUrl: 'http://localhost:8000/',
15 |
16 | framework: 'jasmine',
17 |
18 | jasmineNodeOpts: {
19 | defaultTimeoutInterval: 30000
20 | }
21 |
22 | };
23 |
--------------------------------------------------------------------------------
/dist/components/common/footer/footer.tpl.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/client/components/common/footer/footer.tpl.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/client/views/home/home.tpl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 | Home is making, keep checking
Practice
11 |
12 |
--------------------------------------------------------------------------------
/dist/views/home/home.tpl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 | Home is making, keep checking
Practice
11 |
12 |
--------------------------------------------------------------------------------
/gulpfiles/github.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var rename = require("gulp-rename");
3 |
4 | gulp.task('github-cname', function () {
5 | var target = gulp.src('./client/CNAME');
6 |
7 | return target
8 | .pipe(gulp.dest('./dist'));
9 | });
10 |
11 |
12 | gulp.task('github',['prod','github-cname'],function () {
13 | var target = gulp.src('./dist/index.html');
14 | return target
15 | .pipe(rename("404.html"))
16 | .pipe(gulp.dest('./dist'))
17 | })
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - '4.4'
4 |
5 | before_script:
6 | - export DISPLAY=:99.0
7 | - sh -e /etc/init.d/xvfb start
8 | - npm start > /dev/null &
9 | - npm run update-webdriver
10 | - sleep 1 # give server time to start
11 |
12 | script:
13 | - node_modules/.bin/karma start karma.conf.js --no-auto-watch --single-run --reporters=dots --browsers=Firefox
14 | - node_modules/.bin/protractor e2e-tests/protractor.conf.js --browser=firefox
15 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "strict": "global",
3 | "globals": {
4 | // Angular
5 | "angular": false,
6 |
7 | // Angular mocks
8 | "module": false,
9 | "inject": false,
10 |
11 | // Jasmine
12 | "jasmine": false,
13 | "describe": false,
14 | "beforeEach": false,
15 | "afterEach": false,
16 | "it": false,
17 | "expect": false,
18 |
19 | // Protractor
20 | "browser": false,
21 | "element": false,
22 | "by": false
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/server/app/routes.js:
--------------------------------------------------------------------------------
1 | // load the todo model
2 | // var Todo = require('./models/todo');
3 | // var socketio = require('./socketio.js');
4 | var request = require('request');
5 |
6 | // expose the routes to our app with module.exports
7 | module.exports = function(app) {
8 |
9 | app.use('/api',require('./api.controller'));
10 |
11 | app.use("/",require("./app.controller"));
12 |
13 | // api ---------------------------------------------------------------------
14 |
15 | };
16 |
--------------------------------------------------------------------------------
/gulpfiles/uglify.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var uglify = require('gulp-uglify');
3 | var bytediff = require('gulp-bytediff');
4 | var rename = require('gulp-rename');
5 | var plumber = require('gulp-plumber')
6 |
7 | gulp.task('uglify', ['app'], function() {
8 | return gulp.src('dist/app.js')
9 | .pipe(plumber())
10 | .pipe(bytediff.start())
11 | .pipe(uglify({mangle: true}))
12 | .pipe(bytediff.stop())
13 | .pipe(rename('app.min.js'))
14 | .pipe(plumber.stop())
15 | .pipe(gulp.dest('dist/'));
16 | });
17 |
--------------------------------------------------------------------------------
/gulpfiles/app.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var concat = require('gulp-concat');
3 | var ngAnnotate = require('gulp-ng-annotate');
4 | var plumber = require('gulp-plumber');
5 | var angularFilesort = require('gulp-angular-filesort');
6 | var print = require('gulp-print');
7 |
8 | gulp.task('app', function() {
9 | return gulp.src(['./client/**/*.js', '!./client/**/*test.js'], {
10 | relative: true})
11 | .pipe(angularFilesort())
12 | .pipe(print())
13 | .pipe(plumber())
14 | .pipe(concat('app.js', {newLine: ';'}))
15 | .pipe(ngAnnotate({add: true}))
16 | .pipe(plumber.stop())
17 | .pipe(gulp.dest('dist/'));
18 | });
19 |
--------------------------------------------------------------------------------
/server/app/api.controller.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 | var request = require('request');
4 |
5 | var config = require('../config.json');
6 |
7 | var textCollection = require("../../data/type-content/strings.json");
8 |
9 | var length = textCollection.length;
10 |
11 | router.get('/getstring/:id', function (req,res) {
12 |
13 |
14 | var id = parseInt(req.params.id);
15 |
16 | console.log(req.params.id,id,length);
17 |
18 | if (id >=length) {
19 | id = 0;
20 | }
21 |
22 |
23 | var data = textCollection[id];
24 |
25 | res.json({data : data});
26 | });
27 |
28 | module.exports = router;
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | /* jshint node: true */
2 |
3 | 'use strict';
4 |
5 | var gulp = require('gulp');
6 | var wrench = require('wrench');
7 |
8 | /*
9 | concatenate all *.js / *.coffee files in the 'gulp' folder
10 | */
11 | wrench.readdirSyncRecursive('./gulpfiles').filter(function(file) {
12 | return (/\.(js|coffee)$/i).test(file);
13 | }).map(function(file) {
14 | require('./gulpfiles/' + file);
15 | });
16 |
17 | /*
18 | executed as default task, when no task is specified
19 | */
20 | // gulp.task('default', ['html', 'lib', 'css', 'fonts', 'images', 'index', 'ts', 'tsTest', 'tsE2E']);
21 | /*gulp.task('default', ['clean'], function () {
22 | gulp.start('build');
23 | });*/
--------------------------------------------------------------------------------
/client/services/limitobj.filter.js:
--------------------------------------------------------------------------------
1 | var app=angular.module('typali');
2 | app.filter('limitobj', [function(){
3 | return function(obj, limit){
4 | if (typeof obj != 'object') {
5 | return [];
6 | }
7 | var keys = Object.keys(obj);
8 | if(keys.length < 1 || typeof keys == 'undefined'){
9 | return [];
10 | }
11 |
12 | var ret = new Object,
13 | count = 0;
14 | angular.forEach(keys, function(key, arrayIndex){
15 | if(count >= limit){
16 | return false;
17 | }
18 | ret[key] = obj[key];
19 | count++;
20 | });
21 | return ret;
22 | };
23 | }]);
--------------------------------------------------------------------------------
/client/services/datafetch.service.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | (function () {
3 |
4 | angular
5 | .module('typali')
6 | .service('datafetchService', DatafetchService);
7 |
8 | DatafetchService.$inject = ['$http'];
9 |
10 | function DatafetchService ($http) {
11 | var service = this;
12 |
13 | var url = "https://typali.herokuapp.com/api/";
14 | // var url = "http://localhost:8080/api/";
15 |
16 | /*get string*/
17 | service.getString = function (params) {
18 | var response = $http({
19 | cache: true,
20 | method: 'GET',
21 | url: url+"getstring/"+params
22 | });
23 |
24 | console.log("url : ",url+"getstring/"+params);
25 |
26 | return response;
27 | };
28 |
29 |
30 |
31 | }
32 |
33 | })();
34 |
--------------------------------------------------------------------------------
/client/auth/user-register/user-register.ctrl.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | angular
4 | .module('typali')
5 | .config(['$stateProvider', function($stateProvider) {
6 | $stateProvider
7 | .state('app.register', {
8 | url:'/register',
9 | views: {
10 | 'container@' : {
11 | templateUrl: 'auth/user-register/user-register.tpl.html',
12 | controller: 'UserRegisterCtrl',
13 | controllerAs : 'vm'
14 | }
15 | }
16 |
17 | });
18 | }])
19 | .controller('UserRegisterCtrl', userRegisterCtrl);
20 |
21 | userRegisterCtrl.$inject = ['$location', 'authentication'];
22 | function userRegisterCtrl($location, authentication) {
23 | var vm = this;
24 |
25 | }
26 |
27 | })();
--------------------------------------------------------------------------------
/gulpfiles/watch.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp'),
2 | watch = require('gulp-watch');
3 |
4 | var modRewrite = require('connect-modrewrite');
5 |
6 |
7 | var browserSync = require("browser-sync").create();
8 |
9 |
10 | gulp.task('watch-folder', function() {
11 | browserSync.init({
12 | server: {
13 | baseDir: ["./public","./client"],
14 | routes: {
15 | "/bower_components": "bower_components"
16 | },
17 | middleware: [
18 | modRewrite([
19 | '!\\.\\w+$ /index.html [L]'
20 | ])
21 | ]
22 | }
23 | });
24 | gulp.watch('./client/**/*', ['inject']).on('change', browserSync.reload);;
25 | });
26 |
27 |
--------------------------------------------------------------------------------
/client/auth/login/login.tpl.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dist/auth/login/login.tpl.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/client/views/home/home.ctrl.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('typali')
4 |
5 | .config(['$stateProvider', function($stateProvider) {
6 | $stateProvider
7 | .state('app.home', {
8 | url:'/',
9 | views : {
10 | 'container@': {
11 | templateUrl: 'views/home/home.tpl.html',
12 | controller: 'HomeCtrl',
13 | controllerAs : 'vm'
14 | }
15 | }
16 | })
17 |
18 | }])
19 |
20 | .controller('HomeCtrl', HomeCtrl);
21 | HomeCtrl.$inject = ['$scope','$rootScope'];
22 | function HomeCtrl ($scope,$rootScope) {
23 | var vm = this;
24 |
25 | $rootScope.lang = "unicode";
26 | vm.lang = $rootScope.lang;
27 |
28 | vm.update = function() {
29 | console.log("lang",vm.lang);
30 | $rootScope.lang=vm.lang;
31 | $rootScope.$broadcast("lang",vm.lang);
32 | }
33 | };
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | //jshint strict: false
2 | module.exports = function(config) {
3 | config.set({
4 |
5 | basePath: './app',
6 |
7 | files: [
8 | 'bower_components/angular/angular.js',
9 | 'bower_components/angular-route/angular-route.js',
10 | 'bower_components/angular-mocks/angular-mocks.js',
11 | 'components/**/*.js',
12 | 'view*/**/*.js'
13 | ],
14 |
15 | autoWatch: true,
16 |
17 | frameworks: ['jasmine'],
18 |
19 | browsers: ['Chrome'],
20 |
21 | plugins: [
22 | 'karma-chrome-launcher',
23 | 'karma-firefox-launcher',
24 | 'karma-jasmine',
25 | 'karma-junit-reporter'
26 | ],
27 |
28 | junitReporter: {
29 | outputFile: 'test_out/unit.xml',
30 | suite: 'unit'
31 | }
32 |
33 | });
34 | };
35 |
--------------------------------------------------------------------------------
/server/app/app.controller.js:
--------------------------------------------------------------------------------
1 | var express = require("express");
2 | var router = express.Router();
3 |
4 |
5 | router.use('/', function (req, res, next) {
6 |
7 | /*if (req.path !== '/login' && !req.session.token) {
8 | return res.redirect('/login');
9 | }
10 | */
11 |
12 |
13 | next();
14 | });
15 |
16 | /*static defined*/
17 | // res.sendfile('./public/index.html');
18 |
19 | // router.use("/", express.static('./public/')); //public folder run by gulp
20 |
21 | // router.use("/", express.static('./client/')); //client folder also taken as static
22 |
23 | // router.use("/img/", express.static('./client/assets/img/'));
24 |
25 | // router.use('*', express.static('./public/index.html'))
26 | /*router.get('*', function(req, res) {
27 | res.sendfile('./public/index.html');
28 | });
29 | */
30 | module.exports = router;
--------------------------------------------------------------------------------
/client/services/socket.service.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | angular.module('typali')
3 |
4 | //Here LoopBackAuth service must be provided as argument for authenticating the user
5 | .factory('socket', function ($rootScope) {
6 | var socket = io.connect();
7 | return {
8 | on: function (eventName, callback) {
9 | socket.on(eventName, function () {
10 | var args = arguments;
11 | $rootScope.$apply(function () {
12 | callback.apply(socket, args);
13 | });
14 | });
15 | },
16 | emit: function (eventName, data, callback) {
17 | socket.emit(eventName, data, function () {
18 | var args = arguments;
19 | $rootScope.$apply(function () {
20 | if (callback) {
21 | callback.apply(socket, args);
22 | }
23 | });
24 | })
25 | }
26 | };
27 | });
28 |
--------------------------------------------------------------------------------
/dist/components/common/header/header.tpl.html:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/client/components/common/header/header.tpl.html:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/client/services/filter.service.js:
--------------------------------------------------------------------------------
1 | var app=angular.module('typali');
2 | app.filter('filterByProperty',['$filter', function ($filter) {
3 | /* array is first argument, each addiitonal argument is prefixed by a ":" in filter markup*/
4 | return function (dataArray, searchTerm, propertyName) {
5 | console.log("reached here", searchTerm, propertyName);
6 | if (!dataArray) return;
7 | /* when term is cleared, return full array*/
8 | if (!searchTerm) {
9 | return dataArray
10 | } else if (propertyName === "$") {
11 | return $filter('filter')(dataArray, searchTerm)
12 | }
13 | else {
14 | /* otherwise filter the array */
15 | console.log(searchTerm);
16 | var term = searchTerm.toString().toLowerCase();
17 | return dataArray.filter(function (item) {
18 | return item[propertyName].toString().toLowerCase().indexOf(term) > -1;
19 | });
20 | }
21 | }
22 | }]);
--------------------------------------------------------------------------------
/client/auth/login/login.controller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | angular
4 | .module('typali')
5 | .config(['$stateProvider', function($stateProvider) {
6 | $stateProvider
7 | .state('app.login', {
8 | url:'/login',
9 | views: {
10 | 'container@' : {
11 | templateUrl: 'auth/login/login.tpl.html',
12 | controller: 'LoginCtrl',
13 | controllerAs : 'vm'
14 | }
15 | }
16 |
17 | });
18 | }])
19 | .controller('LoginCtrl', loginCtrl);
20 |
21 | loginCtrl.$inject = ['$location', 'authentication'];
22 | function loginCtrl($location, authentication) {
23 | var vm = this;
24 |
25 | vm.credentials = {
26 | email : "yo@hotmail.com",
27 | password : ""
28 | };
29 |
30 | vm.onSubmit = function () {
31 | authentication
32 | .login(vm.credentials)
33 | .error(function(err){
34 | console.log(err);
35 | })
36 | .then(function(){
37 | $location.path('profile');
38 | });
39 | };
40 |
41 | }
42 |
43 | })();
--------------------------------------------------------------------------------
/e2e-tests/scenarios.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /* https://github.com/angular/protractor/blob/master/docs/toc.md */
4 |
5 | describe('my app', function() {
6 |
7 |
8 | it('should automatically redirect to /view1 when location hash/fragment is empty', function() {
9 | browser.get('index.html');
10 | expect(browser.getLocationAbsUrl()).toMatch("/view1");
11 | });
12 |
13 |
14 | describe('view1', function() {
15 |
16 | beforeEach(function() {
17 | browser.get('index.html#!/view1');
18 | });
19 |
20 |
21 | it('should render view1 when user navigates to /view1', function() {
22 | expect(element.all(by.css('[ng-view] p')).first().getText()).
23 | toMatch(/partial for view 1/);
24 | });
25 |
26 | });
27 |
28 |
29 | describe('view2', function() {
30 |
31 | beforeEach(function() {
32 | browser.get('index.html#!/view2');
33 | });
34 |
35 |
36 | it('should render view2 when user navigates to /view2', function() {
37 | expect(element.all(by.css('[ng-view] p')).first().getText()).
38 | toMatch(/partial for view 2/);
39 | });
40 |
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/gulpfiles/inject.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp'),
2 | wiredep = require('wiredep').stream,
3 | inject = require('gulp-inject'),
4 | angularFilesort = require('gulp-angular-filesort'),
5 | watch = require('gulp-watch');
6 | var print = require('gulp-print');
7 |
8 |
9 |
10 | gulp.task('inject', function () {
11 | var target = gulp.src('./client/index.html');
12 |
13 | var sources = gulp.src(['./client/**/*.js', '!./client/**/*test.js' ],{
14 |
15 | relative: false})
16 | .pipe(angularFilesort())
17 | .pipe(print());
18 |
19 | var injectStyles = gulp.src(['./client/**/*.css'],
20 | { read: false,
21 | relative: false })
22 | .pipe(print());
23 |
24 | var options = {
25 | directory: './bower_components/',
26 | ignorePath: '../',
27 | devDependencies: true,
28 | relative: false
29 | };
30 |
31 | return target
32 | .pipe(wiredep(options))
33 | .pipe(inject(sources,
34 | {ignorePath:"client",
35 | addRootSlash : false,}
36 | ))
37 | .pipe(inject(injectStyles,
38 | {ignorePath:"client",
39 | addRootSlash : false,}
40 | ))
41 | .pipe(gulp.dest('./public'));
42 | });
43 |
--------------------------------------------------------------------------------
/gulpfiles/server.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp'),
2 | spawn = require('child_process').spawn,
3 | node;
4 |
5 |
6 | /**
7 | * $ gulp server
8 | * description: launch the server. If there's a server already running, kill it.
9 | */
10 | gulp.task('server', function() {
11 | if (node) node.kill()
12 | node = spawn('node', ['./server/server.js'], {stdio: 'inherit'})
13 | node.on('close', function (code) {
14 | if (code === 8) {
15 | gulp.log('Error detected, waiting for changes...');
16 | }
17 | });
18 | })
19 |
20 | /**
21 | * $ gulp
22 | * description: start the development environment
23 | */
24 | gulp.task('launch-server',['inject','server','watch-folder'], function() {
25 | /*gulp.run('server');
26 | gulp.run('inject');
27 | */
28 | // gulp.watch(['./server/server.js', './server/app/**/*.js'], function() {
29 | // gulp.run('server')
30 | // });
31 | gulp.watch(['./server/server.js', './server/app/**/*.js','./server/jsons/**/*.json'],['server']);
32 |
33 | })
34 |
35 | // clean up if an error goes unhandled.
36 | process.on('exit', function() {
37 | if (node) node.kill()
38 | })
39 |
40 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "typali",
3 | "description": "typali nepali typing tutor",
4 | "version": "0.0.",
5 | "homepage": "typali.com",
6 | "private": true,
7 | "dependencies": {
8 | "angular": "~1.5.0",
9 | "angular-loader": "~1.5.0",
10 | "bootstrap": "^3.3.4",
11 | "jquery": "^3.1.0",
12 | "font-awesome": "^4.6.3",
13 | "angular-sanitize": "~1.5.0",
14 | "angular-ui-router": "^0.3.2",
15 | "angular-loading-bar": "^0.9.0",
16 | "angular-aria": "~1.5.0",
17 | "angular-animate": "~1.5.0",
18 | "angular-messages": "~1.5.0"
19 | },
20 | "overrides": {
21 | "jquery": {
22 | "main": []
23 | },
24 | "angular": {
25 | "main": []
26 | },
27 | "angular-loader": {
28 | "main": []
29 | },
30 | "angular-sanitize": {
31 | "main": []
32 | },
33 | "angular-ui-router": {
34 | "main": []
35 | },
36 | "angular-aria": {
37 | "main": []
38 | },
39 | "angular-animate": {
40 | "main": []
41 | },
42 | "angular-messages": {
43 | "main": []
44 | },
45 | "bootstrap": {
46 | "main": []
47 | },
48 | "angular-bootstrap": {
49 | "main": []
50 | },
51 | "angular-loading-bar": {
52 | "main": []
53 | },
54 | "font-awesome": {
55 | "main": []
56 | },
57 | "highcharts": {
58 | "main": []
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "typali",
3 | "private": true,
4 | "version": "0.0.1",
5 | "description": "Nepali typing all",
6 | "dependencies": {
7 | "body-parser": "^1.15.2",
8 | "ejs": "^2.5.5",
9 | "express": "^4.10.2",
10 | "express-session": "^1.14.2",
11 | "gulp-rename": "^1.2.2",
12 | "morgan": "^1.7.0",
13 | "nodemon": "^1.11.0",
14 | "request": "^2.74.0",
15 | "wagner-core": "^0.2.0"
16 | },
17 | "devDependencies": {
18 | "bower": "^1.7.7",
19 | "browser-sync": "^2.18.5",
20 | "connect-modrewrite": "^0.10.1",
21 | "gulp": "^3.9.1",
22 | "gulp-angular-filesort": "^1.1.1",
23 | "gulp-bytediff": "^1.0.0",
24 | "gulp-concat": "^2.6.1",
25 | "gulp-inject": "^4.1.0",
26 | "gulp-ng-annotate": "^2.0.0",
27 | "gulp-ng-config": "^1.4.0",
28 | "gulp-plumber": "^1.1.0",
29 | "gulp-print": "^2.0.1",
30 | "gulp-remove-files": "^0.0.3",
31 | "gulp-rename": "^1.2.2",
32 | "gulp-uglify": "^2.1.2",
33 | "gulp-uglifycss": "^1.0.8",
34 | "gulp-watch": "^4.3.9",
35 | "http-server": "^0.9.0",
36 | "jasmine-core": "^2.4.1",
37 | "karma": "^0.13.22",
38 | "karma-chrome-launcher": "^0.2.3",
39 | "karma-firefox-launcher": "^0.1.7",
40 | "karma-jasmine": "^0.3.8",
41 | "karma-junit-reporter": "^0.4.1",
42 | "protractor": "^3.2.2",
43 | "wiredep": "^4.0.0",
44 | "wrench": "^1.5.9"
45 | },
46 | "scripts": {
47 | "prestart": "npm install",
48 | "start": "node server/server.js"
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/client/views/practice/practise.css:
--------------------------------------------------------------------------------
1 |
2 | .showArea {
3 | min-height: 50px;
4 | color: #727070;
5 | font-size: 0.8em;
6 | }
7 |
8 | .writeArea {
9 | border: 1px solid #c9c9c9;
10 | padding: 5px 10px;
11 | background: #fff;
12 | margin: 20px 0;
13 | }
14 |
15 | .active {
16 | border: 1px solid #66ceff;
17 | box-shadow: 0px 0px 2px #66ceff;
18 | }
19 |
20 | .writeArea .word {
21 | display: inline-block;
22 | font-size: 18px;
23 | }
24 |
25 | .writeArea input {
26 | border: none;
27 | font-size: 18px;
28 | outline: none;
29 | color: #fff;
30 | }
31 |
32 | .writeArea input:focus {
33 | outline: none;
34 | }
35 |
36 | @keyframes blink {
37 | 50% {
38 | opacity: 0.0;
39 | }
40 | }
41 | @-webkit-keyframes blink {
42 | 50% {
43 | opacity: 0.0;
44 | }
45 | }
46 | .blink {
47 | display: inline-block;
48 | font-size: 14px;
49 | color : 878383;
50 | animation: blink 1s step-start 0s infinite;
51 | -webkit-animation: blink 1s step-start 0s infinite;
52 | }
53 |
54 | .writeArea.alert-danger {
55 | background: #F2DEDE;
56 | }
57 |
58 | .writeArea.alert-danger input {
59 | background: #F2DEDE;
60 | color: #F2DEDE;
61 | }
62 |
63 | .highlightWord span {
64 | /*background: #000;*/
65 | font-weight: bold;
66 | border-bottom: 1px solid #000;
67 | }
68 |
69 | .practice .msgHolder {
70 | position: absolute;
71 | width: 100%;
72 | height: 100%;
73 | top: 0;
74 | left: 0;
75 | background: rgba(0,0,0,0.7);
76 | }
77 |
78 | .practice .messegebox {
79 | position: absolute;
80 | background: #fff;
81 | top: 100px;
82 | left: 30%;
83 | width: 400px;
84 | transform: translateX(-150px);
85 | padding: 10px;
86 | border: 1px solid #c9c9c9;
87 | box-shadow: 0 0 5px #f8f8f8;
88 | border-radius: 5px;
89 | }
--------------------------------------------------------------------------------
/client/views/editor/editor.ctrl.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('typali')
4 |
5 | .config(['$stateProvider', function($stateProvider) {
6 | $stateProvider
7 | .state('app.editor', {
8 | url:'/editor',
9 | views : {
10 | 'container@': {
11 | templateUrl: 'views/editor/editor.tpl.html',
12 | controller: 'editorCtrl',
13 | controllerAs : 'vm'
14 | }
15 | }
16 | })
17 |
18 | }])
19 |
20 | .controller('editorCtrl', EditorCtrl);
21 | EditorCtrl.$inject = ['$scope'];
22 | function EditorCtrl ($scope) {
23 | var vm = this;
24 |
25 | var colorPalette = ['000000', 'FF9966', '6699FF', '99FF66', 'CC0000', '00CC00', '0000CC', '333333', '0066FF', 'FFFFFF'];
26 | var forePalette = $('.fore-palette');
27 | var backPalette = $('.back-palette');
28 |
29 | for (var i = 0; i < colorPalette.length; i++) {
30 | forePalette.append('');
31 | backPalette.append('');
32 | }
33 |
34 | $('.toolbar a').click(function(e) {
35 | var command = $(this).data('command');
36 | if (command == 'h1' || command == 'h2' || command == 'p') {
37 | document.execCommand('formatBlock', false, command);
38 | }
39 | if (command == 'forecolor' || command == 'backcolor') {
40 | document.execCommand($(this).data('command'), false, $(this).data('value'));
41 | }
42 | if (command == 'createlink' || command == 'insertimage') {
43 | url = prompt('Enter the link here: ', 'http:\/\/');
44 | document.execCommand($(this).data('command'), false, url);
45 | } else document.execCommand($(this).data('command'), false, null);
46 | });
47 |
48 | };
--------------------------------------------------------------------------------
/client/app.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // Declare app level module which depends on views, and components
4 |
5 | function run($rootScope, $location, authentication,$window) {
6 | $rootScope.$on('$routeChangeStart', function(event, nextRoute, currentRoute) {
7 | /*if (!authentication.isLoggedIn()) {
8 | $location.path('/login');
9 | }*/
10 | });
11 |
12 |
13 | $rootScope.facebookAppId = '[]'; // set your facebook app id here
14 | // initialise google analytics
15 | /* $window.ga('create', '', 'auto');
16 |
17 | // track pageview on state change
18 | $rootScope.$on('$stateChangeSuccess', function (event) {
19 | $window.ga('send', 'pageview', $location.path());
20 | });*/
21 |
22 | }
23 |
24 |
25 | var app = angular.module('typali', [
26 | 'ui.router',
27 | 'ngSanitize',
28 | 'angular-loading-bar'
29 | ])
30 |
31 | .config(['$locationProvider', '$stateProvider', '$urlRouterProvider', function($locationProvider, $stateProvider, $urlRouterProvider) {
32 | $locationProvider.hashPrefix('!');
33 |
34 | $urlRouterProvider.otherwise('/404');
35 |
36 | $stateProvider
37 | .state('app',{
38 | url : '',
39 | views : {
40 | 'header@' : {
41 | controller : 'HeaderCtrl',
42 | templateUrl : 'components/common/header/header.tpl.html',
43 | controllerAs : "vm"
44 | },
45 | 'footer@' : {
46 | controller : 'FooterCtrl',
47 | templateUrl : 'components/common/footer/footer.tpl.html',
48 | controllerAs : "vm"
49 | }
50 | }
51 | })
52 |
53 | .state('app.404',{
54 | url : '/404',
55 | views : {
56 | 'header@' : {
57 | templateUrl : 'components/common/header/header.tpl.html'
58 | }
59 | }
60 | });
61 |
62 | $locationProvider.html5Mode(true);
63 |
64 |
65 |
66 | }])
67 | .run(['$rootScope', '$location', 'authentication', '$window', run]);
--------------------------------------------------------------------------------
/client/services/authentication.service.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | angular
4 | .module('typali')
5 | .service('authentication', authentication);
6 |
7 | authentication.$inject = ['$http', '$window'];
8 | function authentication ($http, $window) {
9 |
10 | var saveToken = function (token) {
11 | $window.localStorage['typali-token'] = token;
12 | };
13 |
14 | var getToken = function () {
15 | return $window.localStorage['typali-token'];
16 | };
17 |
18 | var isLoggedIn = function() {
19 | var token = getToken();
20 | var payload;
21 |
22 | if(token){
23 | payload = token.split('.')[1];
24 | payload = $window.atob(payload);
25 | payload = JSON.parse(payload);
26 |
27 | return payload.exp > Date.now() / 1000;
28 | } else {
29 | return false;
30 | }
31 | };
32 |
33 | var currentUser = function() {
34 | if(isLoggedIn()){
35 | var token = getToken();
36 | var payload = token.split('.')[1];
37 | payload = $window.atob(payload);
38 | payload = JSON.parse(payload);
39 | return {
40 | email : payload.email,
41 | name : payload.name
42 | };
43 | }
44 | };
45 |
46 | var register = function(user) {
47 | return $http.post('/api/register', user).success(function(data){
48 | saveToken(data.token);
49 | });
50 | };
51 |
52 | var login = function(user) {
53 | return $http.post('/api/login', user)
54 | .success(function(data) {
55 | console.log(data.token);
56 | saveToken(data.token);
57 | });
58 | };
59 |
60 | var logout = function() {
61 | $window.localStorage.removeItem('typali-token');
62 | };
63 |
64 | return {
65 | currentUser : currentUser,
66 | saveToken : saveToken,
67 | getToken : getToken,
68 | isLoggedIn : isLoggedIn,
69 | register : register,
70 | login : login,
71 | logout : logout
72 | };
73 | }
74 |
75 |
76 | })();
77 |
--------------------------------------------------------------------------------
/server/server.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | app = express();
3 | var http = require('http').Server(app);
4 | var morgan = require('morgan');
5 | var bodyParser = require('body-parser');
6 | // var session = require('express-session');
7 |
8 | // var io = require('socket.io')(http);
9 | var request = require('request');
10 |
11 | var config = require('./config.json');
12 |
13 | var port = process.env.PORT || 8080;
14 |
15 | console.log("from serverjs");
16 | app.use(morgan('dev'));
17 |
18 |
19 |
20 |
21 | // app.set('view engine', 'ejs');
22 | // app.set('views', __dirname + '/views');
23 |
24 | // app.use('/bower_components', express.static('./bower_components'));
25 |
26 | app.use(bodyParser.urlencoded({ extended: true, parameterLimit: 5000 })); // parse application/x-www-form-urlencoded
27 | app.use(bodyParser.json()); // parse application/json
28 | app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
29 |
30 | // app.use(session({ secret: "mjt", resave: false, saveUninitialized: true }));
31 |
32 | app.use(function(req, res, next) {
33 | // req.io = io;
34 | res.header("Access-Control-Allow-Origin", "*");
35 | res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
36 | next();
37 | });
38 |
39 |
40 | require('./app/routes.js')(app);
41 |
42 |
43 |
44 | // app.listen(port);
45 | // console.log("App listening on port " + port);
46 |
47 |
48 | http.listen(port,function(){
49 | console.log('listening on *:'+port);
50 | });
51 | /*
52 | io.on('connection', function (socket) {
53 | console.log('client connect');
54 | // socket.on('echo', function (data) {
55 | var url = config.localApiUri+"/marketlive"
56 | request.get({url : url},function (error, response, html) {
57 | if (!error) {
58 | var resArray = JSON.parse(html);
59 | console.log("from io first connection");
60 | console.log(resArray);
61 | io.emit('update', resArray.data);
62 | }
63 | }
64 | )
65 |
66 | // })
67 |
68 | });*/
69 |
70 | // io.emit('update', {msg : 'i reached everywhere'});
71 | // });
--------------------------------------------------------------------------------
/client/auth/user-register/user-register.tpl.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dist/auth/user-register/user-register.tpl.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dist/views/editor/editor.tpl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
36 |
37 |
A WYSIWYG Editor.
38 |
Try making some changes here. Add your own text or maybe an image.
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/client/views/editor/editor.tpl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
36 |
37 |
A WYSIWYG Editor.
38 |
Try making some changes here. Add your own text or maybe an image.
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/client/components/common/keyboard/keyboard.component.js:
--------------------------------------------------------------------------------
1 | angular.module('typali')
2 | .component('keyboard2', {
3 | templateUrl: 'components/common/keyboard/keyboard.tpl.html',
4 | controller: keyboardCtrl,
5 | bindings: {
6 | keyboard: '<',
7 | word: '<',
8 | letter: '<',
9 | shift: '<'
10 | }
11 | });
12 |
13 |
14 | keyboardCtrl.$inject = ['$document', '$scope']
15 | function keyboardCtrl($document, $scope) {
16 | var ctrl = this;
17 |
18 | var keyboard = ctrl.keyboard;
19 |
20 | var cls;
21 |
22 | console.log("letter = ", ctrl.letter);
23 |
24 | // highlightLetter(ctrl.letter)
25 |
26 | var allKeys = [],
27 | engData_all,
28 | codeData_all,
29 | npData_all,
30 | npShiftData_all;
31 |
32 | // function makeKeyboard() {
33 | for (var key in keyboard) {
34 | for (var i = 0; i < keyboard[key].length; i++) {
35 | allKeys.push(keyboard[key][i])
36 | };
37 | }
38 |
39 |
40 |
41 |
42 | engData_all = allKeys.map(function (item) { return item.en; });
43 | codeData_all = allKeys.map(function (item) { return item.code; });
44 | npData_all = allKeys.map(function (item) { return item.np; });
45 | npShiftData_all = allKeys.map(function (item) { return item.npShift; });
46 | // }
47 |
48 | this.$onInit = function () {
49 | console.log("changing");
50 | // makeKeyboard();
51 | highlightLetter(ctrl.letter);
52 | }
53 |
54 | console.log("in components", ctrl.word, ctrl.letter);
55 | this.$onChanges = function (changes) {
56 | // console.log("changed in components",changes.word,changes.letter.currentValue);
57 | console.log("changes", changes);
58 | if (typeof changes.letter != 'undefined') {
59 | highlightLetter(changes.letter.currentValue);
60 | } /* else {
61 | console.log("here");
62 | // makeKeyboard();
63 | highlightLetter(changes.letter);
64 | } */
65 | }
66 |
67 |
68 | function highlightLetter(letter) {
69 | console.log("letter again = ", ctrl.letter);
70 | $(".highlightLetter").removeClass("highlightLetter");
71 | if (letter == " ") {
72 | cls = "spacebar";
73 | // return;
74 | } else {
75 |
76 | if (npData_all.indexOf(letter) > -1) {
77 | cls = "c" + codeData_all[npData_all.indexOf(letter)];
78 | console.log(npData_all,npData_all.indexOf(letter));
79 |
80 | } else {
81 | cls = "c" + codeData_all[npShiftData_all.indexOf(letter)];
82 | $(".shiftKey").addClass("highlightLetter");
83 | }
84 | }
85 |
86 | console.log("letter again = ", ctrl.letter, cls);
87 | $document.find("." + cls).addClass("highlightLetter");
88 | }
89 |
90 | // highlightLetter(ctrl.letter)
91 | }
--------------------------------------------------------------------------------
/client/views/practice/practice.tpl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

5 |
6 |
7 |
8 |
9 | {{value}}
10 |
11 |
12 |
13 |
14 |
15 | {{vm.sentence}}
16 |
17 |
18 |
19 |
20 |
21 | {{vm.word}}
22 |
23 |
|
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | Time : {{vm.time}}
45 |
46 |
47 | Speed : {{vm.speed}} WPM
48 |
49 |
50 | {{vm.timeTaken}} millisecond
51 |
52 |
53 |
54 |
55 |
56 |
57 |
Congratulation! You completed
58 |
59 | This text is brought from {{vm.art.title}} by {{vm.art.author}}
60 |
61 |
62 | full content is
Here
63 |
64 |
65 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/dist/views/practice/practice.tpl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

5 |
6 |
7 |
8 |
9 | {{value}}
10 |
11 |
12 |
13 |
14 |
15 | {{vm.sentence}}
16 |
17 |
18 |
19 |
20 |
21 | {{vm.word}}
22 |
23 |
|
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | Time : {{vm.time}}
45 |
46 |
47 | Speed : {{vm.speed}} WPM
48 |
49 |
50 | {{vm.timeTaken}} millisecond
51 |
52 |
53 |
54 |
55 |
56 |
57 |
Congratulation! You completed
58 |
59 | This text is brought from {{vm.art.title}} by {{vm.art.author}}
60 |
61 |
62 | full content is
Here
63 |
64 |
65 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/dist/views/practice/practise.tpl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

5 |
6 |
7 |
8 |
9 | {{value}}
10 |
11 |
12 |
13 |
14 |
15 | {{vm.sentence}}
16 |
17 |
18 |
19 |
20 |
21 | {{vm.word}}
22 |
23 |
|
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | Time : {{vm.time}}
45 |
46 |
47 | Speed : {{vm.speed}} WPM
48 |
49 |
50 | {{vm.timeTaken}} millisecond
51 |
52 |
53 |
54 |
55 |
56 |
57 |
Congratulation! You completed
58 |
59 | This text is brought from {{vm.art.title}} by {{vm.art.author}}
60 |
61 |
62 | full content is
Here
63 |
64 |
65 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/client/views/editor/editor.css:
--------------------------------------------------------------------------------
1 |
2 |
3 | .editor a {
4 | cursor: pointer;
5 | }
6 |
7 | .editor #editor {
8 | box-shadow: 0 0 2px #CCC;
9 | min-height: 150px;
10 | overflow: auto;
11 | padding: 1em;
12 | margin-top: 20px;
13 | resize: vertical;
14 | outline: none;
15 | }
16 |
17 | .editor .toolbar {
18 | text-align: center;
19 | }
20 |
21 | .editor .toolbar a,
22 | .editor .fore-wrapper,
23 | .editor .back-wrapper {
24 | border: 1px solid #AAA;
25 | background: #FFF;
26 | font-family: 'Candal';
27 | border-radius: 1px;
28 | color: black;
29 | padding: 5px;
30 | width: 1.5em;
31 | margin: -2px;
32 | margin-top: 10px;
33 | display: inline-block;
34 | text-decoration: none;
35 | box-shadow: 0px 1px 0px #CCC;
36 | }
37 |
38 | .editor .toolbar a:hover,
39 | .editor .fore-wrapper:hover,
40 | .editor .back-wrapper:hover {
41 | background: #f2f2f2;
42 | border-color: #8c8c8c;
43 | }
44 |
45 | .editor a[data-command='redo'],
46 | .editor a[data-command='strikeThrough'],
47 | .editor a[data-command='justifyFull'],
48 | .editor a[data-command='insertOrderedList'],
49 | .editor a[data-command='outdent'],
50 | .editor a[data-command='p'],
51 | .editor a[data-command='superscript'] {
52 | margin-right: 5px;
53 | border-radius: 0 3px 3px 0;
54 | }
55 |
56 | .editor a[data-command='undo'],
57 | .editor .fore-wrapper,
58 | .editor a[data-command='justifyLeft'],
59 | .editor a[data-command='insertUnorderedList'],
60 | .editor a[data-command='indent'],
61 | .editor a[data-command='h1'],
62 | .editor a[data-command='subscript'] {
63 | border-radius: 3px 0 0 3px;
64 | }
65 |
66 | .editor a.palette-item {
67 | height: 1em;
68 | border-radius: 3px;
69 | margin: 2px;
70 | width: 1em;
71 | border: 1px solid #CCC;
72 | }
73 |
74 | .editor a.palette-item:hover {
75 | border: 1px solid #CCC;
76 | box-shadow: 0 0 3px #333;
77 | }
78 |
79 | .editor .fore-palette,
80 | .editor .back-palette {
81 | display: none;
82 | }
83 |
84 | .editor .fore-wrapper,
85 | .editor .back-wrapper {
86 | display: inline-block;
87 | cursor: pointer;
88 | }
89 |
90 | .editor .fore-wrapper:hover .fore-palette,
91 | .editor .back-wrapper:hover .back-palette {
92 | display: block;
93 | float: left;
94 | position: absolute;
95 | padding: 3px;
96 | width: 160px;
97 | background: #FFF;
98 | border: 1px solid #DDD;
99 | box-shadow: 0 0 5px #CCC;
100 | height: 70px;
101 | }
102 |
103 | .editor .fore-palette a,
104 | .editor .back-palette a {
105 | background: #FFF;
106 | margin-bottom: 2px;
107 | }
108 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Typali: Nepali typing tutor
2 | Type+Nepali = typali :D
3 |
4 | # why typali (not typesala)
5 | typesala.com typeshala.com domains where too high ;)
6 |
7 |
8 | # Demo
9 | [Demo](https://emp3ror.github.io/typali/).
10 |
11 | ## sample text
12 | * this string is used from
13 | * कथा : दोषी चश्मा
14 |
15 | # Gross speed
16 | WPM (word per minute)
17 |
18 | Taking a [sample text](https://emp3ror.github.io/typesala/speed/sample-text1.md) seems average letters per word on a paragraph (including space) is 6
19 |
20 | So, our formula for gross speed is :
21 |
22 | Gross WPM = (All typed Entries/6)/Time
23 |
24 |
25 | # TODO
26 | * calculate speed
27 | * Ending Message
28 | * Nepali paragraphs Array
29 | * Landing page : (choose easy to hard paragraphs)
30 |
31 |
32 | ## How to use in local
33 |
34 | ### if NVM
35 | ```bash
36 | $ source /usr/share/nvm/init-nvm.sh
37 | $ nvm use v10.18.0
38 | ```
39 |
40 |
41 | ### Setup
42 |
43 | Install node, npm according to you OS
44 | on ARCH
45 | ```bash
46 | $ sudo pacman -S nodejs
47 | ```
48 |
49 | ### Install bower,gulp:
50 |
51 | ```bash
52 | $ npm install -g gulp
53 | $ npm install -g bower
54 | $ npm install
55 | $ bower install
56 | ```
57 |
58 | and run gulp script like this:
59 |
60 | ```bash
61 | $ gulp launch-server
62 | ```
63 |
64 | for production
65 |
66 | ```bash
67 | $ gulp prod
68 | ```
69 |
70 | # /dist
71 | dist folder is created when
72 | ```bash
73 | $ gulp prod
74 | ```
75 |
76 | ### for gh-pages
77 | rename index.html to 404.html (hack for github redirect)
78 | ```
79 | $ git subtree push --prefix dist origin gh-pages
80 | or force push
81 | $ git push origin `git subtree split --prefix dist master`:gh-pages --force
82 | ```
83 |
84 |
85 | ## License
86 |
87 | * [Apache Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html)
88 |
89 | ## Acknowledgements
90 |
91 | My sincere respect to all the open source community, all those people who manages their time to help on finding solution to needy, blog their experiences and write tutorials.
92 |
93 | ## Contributing
94 |
95 | Please fork this repository and contribute back using
96 | [pull requests](https://github.com/emp3ror/typesala/pulls).
97 |
98 | Any contributions, large or small, major features, bug fixes, additional
99 | language translations, unit/integration tests are welcomed and appreciated
100 | but will be thoroughly reviewed and discussed.
101 |
102 |
103 | ## Reference for speed calculation
104 | https://www.speedtypingonline.com/typing-equations
105 |
--------------------------------------------------------------------------------
/gulpfiles/prod.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp'),
2 | wiredep = require('wiredep').stream,
3 | inject = require('gulp-inject'),
4 | angularFilesort = require('gulp-angular-filesort'),
5 | watch = require('gulp-watch');
6 | var print = require('gulp-print');
7 | var removeFiles = require('gulp-remove-files');
8 |
9 |
10 | gulp.task('prod', ['uglify', 'uglifycss','move-assets','prodtpl'], function () {
11 |
12 | // remove app.js
13 | gulp.src('./dist/app.js')
14 | .pipe(removeFiles());
15 |
16 | // inject app.min.js and app.css
17 | var target = gulp.src('./client/index.html');
18 |
19 | var sources = gulp.src(['./dist/app.min.js'],{
20 | relative: true})
21 | .pipe(angularFilesort())
22 | .pipe(print());
23 |
24 | var injectStyles = gulp.src(['./dist/app.css'],
25 | { read: false,
26 | relative: true })
27 | .pipe(print());
28 |
29 | var options = {
30 | directory: './bower_components/',
31 | ignorePath: '../',
32 | devDependencies: true,
33 | relative: false
34 | };
35 |
36 | return target
37 | .pipe(wiredep(options))
38 | .pipe(inject(sources,
39 | {ignorePath:"dist",
40 | addRootSlash : false,}
41 | ))
42 | .pipe(inject(injectStyles,
43 | {ignorePath:"dist",
44 | addRootSlash : false,}
45 | ))
46 | .pipe(gulp.dest('./dist'));
47 | });
48 |
49 | gulp.task('move-assets',function () {
50 | //temporary solutions to mkdir for existing directory problem
51 | gulp.src('./dist/*')
52 | .pipe(removeFiles());
53 |
54 | gulp.src(['./client/assets/**/*'])
55 | .pipe(gulp.dest('./dist/assets/'));
56 | })
57 |
58 |
59 | gulp.task('test-minify', ['uglify', 'uglifycss'], function () {
60 |
61 |
62 | // inject app.min.js and app.css
63 | var target = gulp.src('./client/index.html');
64 |
65 | var sources = gulp.src(['./dist/app.js'],{
66 | relative: true})
67 | .pipe(angularFilesort())
68 | .pipe(print());
69 |
70 | var injectStyles = gulp.src(['./dist/app.css'],
71 | { read: false,
72 | relative: true })
73 | .pipe(print());
74 |
75 | var options = {
76 | directory: './bower_components/',
77 | ignorePath: '../',
78 | devDependencies: true,
79 | relative: false
80 | };
81 |
82 | return target
83 | .pipe(wiredep(options))
84 | .pipe(inject(sources,
85 | {ignorePath:"dist",
86 | addRootSlash : false,}
87 | ))
88 | .pipe(inject(injectStyles,
89 | {ignorePath:"dist",
90 | addRootSlash : false,}
91 | ))
92 | .pipe(gulp.dest('./dist'));
93 | });
94 |
95 |
--------------------------------------------------------------------------------
/data/type-content/strings.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "text" : "सानो छ खेत सानो छ बारी सानै छ जहान, नगरी काम पुग्दैन खान साझ र बिहान, बिहानपख झुल्किनछ घाम देउराली पाखामा, आसरे गीत घन्किनछ अनि सुरिलो भाकामा",
4 | "title" : "किसानको रहर",
5 | "author" : "लक्ष्मी प्रसाद देवकोटा ",
6 | "desc" : "",
7 | "url_readmore" : "",
8 | "img_url" : ""
9 | },
10 | {
11 | "text" : "मेरो गाउँ ज्यामिरे, जमुनीको छोरो म, काले भन्छन् मलाई, तर मान्छे गोरो म। सबै पढ्न गएछन्, जान्ने सुन्ने भएछन्, म त अझै गोठमा, छैन हाँसो ओठमा। किन किन मन यो, दुखे दुखे जस्तो छ,",
12 | "title" : "जमुनीको छोरो",
13 | "author" : "रामबाबु सुवेदी,स्वर्णिम स्कूलका विद्यार्थीहरू,रामेश श्रेष्ठ",
14 | "desc" : "",
15 | "url_readmore" : "",
16 | "img_url" : ""
17 | },
18 | {
19 | "text" : "हुँदैन बिहान मिर्मिरेमा तारा झरेर नगए, बन्दैन मुलुक दुई-चार सपूत मरेर नगए",
20 | "title" : "शहीदहरुको सम्झनामा",
21 | "author" : "भुपी शेरचन",
22 | "desc" : "",
23 | "url_readmore" : "",
24 | "img_url" : ""
25 | },
26 | {
27 | "text" : "भर जन्म घासँ तिर मन दिई धन कमायो, नाम् केही रहोस् पछी भनि कुवा खनायो, घाँशी दरिद्र घरको तर बुद्दी कस्तो, म भानुभक्त धनी भैकन आज एस्तो",
28 | "title" : "घासी",
29 | "author" : "आदिकवि भानुभक्त",
30 | "desc" : "",
31 | "url_readmore" : "",
32 | "img_url" : ""
33 | },
34 | {
35 | "text" : "लेकका हामी केटाकेटी, कुहिरो भित्र इस्कुल छ, चौरीलाई चराउँदै दिन बित्छ, पढ्नु र लेख्नु मुस्किल छ, हिउँमा कोरेको अक्षर त, एकछिनमा बिलाई जाइजान्छ, दिनभरि हेर्नु छ गाईबस्तु, नहेरे भालुले खाइजान्छ",
36 | "title" : "लेकका हामी केटाकटी",
37 | "author" : "",
38 | "desc" : "",
39 | "url_readmore" : "",
40 | "img_url" : ""
41 | },
42 | {
43 | "text" : "केशवराजको चश्मा दोषी थियो। अलिक टाढाको मानिस तिनी चिन्न सक्तैनथे। किताब पढ्दा तिनको आँखालाई निकै बल पर्थ्यो। चश्माको पावर तिनका आँखाका लागि कम भएछ। धेरै दिनदेखि अर्को चश्मा लिनें विचारमा थिए, तर अझै अनुकूल परेको थिएन।",
44 | "title" : "दोषी चस्मा",
45 | "author" : "विश्वेश्वर प्रसाद कोइरा",
46 | "desc" : "",
47 | "url_readmore" : "",
48 | "img_url" : ""
49 | },
50 | {
51 | "text" : "भोलिवादको श्रीगणेश कुन बेला, कसको पालादेखि कसले सुरु गर्यो, त्यो किट्न सकिन्न, तर हेरिल्याउँदा नेपाली समाजमा भानुभक्तभन्दा अघिदेखि नै यसले खुट्टो घुमाएको बुझिन्छ।",
52 | "title" : "जय भोलि !",
53 | "author" : "भैरव अर्याल",
54 | "desc" : "",
55 | "url_readmore" : "",
56 | "img_url" : ""
57 | },
58 | {
59 | "text" : "हिजोसम्म रोईरोई बाँचिरहेका थिए। आज तिनै हाँसीहाँसी मर्न तयार छन्। हिजोसम्म जसको बोलीमा केही थिएन; मनको प्रतिध्वनिसम्म थिएन, मानिसले बोलेजस्तै थिएन; केवल शब्द थियो, अर्थ थिएन; आज तिनैको बोलीमा प्राण छ, व्यथा, उन्माद, आह्वान छ, आकर्षण छ, आज तिनैको मौनता पनि बोल्छ।",
60 | "title" : "Pariwartan",
61 | "author" : "Gopal Prasad Rimal",
62 | "desc" : "",
63 | "url_readmore" : "",
64 | "img_url" : ""
65 | },
66 | {
67 | "text" : "नटिप्नु हेर कोपिला, नचुँड्नु पाप लाग्दछ, नच्यात्नु फुल नानी हो, दया र धर्म भाग्दछ",
68 | "title" : "पाप लाग्छ",
69 | "author" : "लक्ष्मीप्रसाद देवकोटा",
70 | "desc" : "",
71 | "url_readmore" : "",
72 | "img_url" : ""
73 | }
74 |
75 | ]
76 |
--------------------------------------------------------------------------------
/client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | नेपाली typing
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
68 |
69 |
70 |
71 |
72 |
73 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |

85 |
86 |
87 |
88 |
89 |
90 |
93 |
94 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/dist/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | नेपाली typing
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
68 |
69 |
70 |
71 |
72 |
73 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |

85 |
86 |
87 |
88 |
89 |
90 |
93 |
94 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | नेपाली typing
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
68 |
69 |
70 |
71 |
72 |
73 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |

85 |
86 |
87 |
88 |
89 |
90 |
93 |
94 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/client/components/common/keyboard/keyboard.tpl.html:
--------------------------------------------------------------------------------
1 |
2 |
18 |
27 |
38 |
58 |
80 |
97 |
98 |
--------------------------------------------------------------------------------
/dist/components/common/keyboard/keyboard.tpl.html:
--------------------------------------------------------------------------------
1 |
2 |
18 |
27 |
38 |
58 |
80 |
97 |
98 |
--------------------------------------------------------------------------------
/dist/app.css:
--------------------------------------------------------------------------------
1 | html,body{background:#fff;font-family:ProximaNova,-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:16px;color:#231f20}.mainView{min-height:300px;margin-bottom:20px}
2 | .editor a{cursor:pointer}.editor #editor{box-shadow:0 0 2px #CCC;min-height:150px;overflow:auto;padding:1em;margin-top:20px;resize:vertical;outline:0}.editor .toolbar{text-align:center}.editor .toolbar a,.editor .fore-wrapper,.editor .back-wrapper{border:1px solid #AAA;background:#FFF;font-family:'Candal';border-radius:1px;color:black;padding:5px;width:1.5em;margin:-2px;margin-top:10px;display:inline-block;text-decoration:none;box-shadow:0 1px 0 #CCC}.editor .toolbar a:hover,.editor .fore-wrapper:hover,.editor .back-wrapper:hover{background:#f2f2f2;border-color:#8c8c8c}.editor a[data-command='redo'],.editor a[data-command='strikeThrough'],.editor a[data-command='justifyFull'],.editor a[data-command='insertOrderedList'],.editor a[data-command='outdent'],.editor a[data-command='p'],.editor a[data-command='superscript']{margin-right:5px;border-radius:0 3px 3px 0}.editor a[data-command='undo'],.editor .fore-wrapper,.editor a[data-command='justifyLeft'],.editor a[data-command='insertUnorderedList'],.editor a[data-command='indent'],.editor a[data-command='h1'],.editor a[data-command='subscript']{border-radius:3px 0 0 3px}.editor a.palette-item{height:1em;border-radius:3px;margin:2px;width:1em;border:1px solid #CCC}.editor a.palette-item:hover{border:1px solid #CCC;box-shadow:0 0 3px #333}.editor .fore-palette,.editor .back-palette{display:none}.editor .fore-wrapper,.editor .back-wrapper{display:inline-block;cursor:pointer}.editor .fore-wrapper:hover .fore-palette,.editor .back-wrapper:hover .back-palette{display:block;float:left;position:absolute;padding:3px;width:160px;background:#FFF;border:1px solid #DDD;box-shadow:0 0 5px #CCC;height:70px}.editor .fore-palette a,.editor .back-palette a{background:#FFF;margin-bottom:2px}
3 | .showArea{min-height:50px;color:#727070;font-size:.8em}.writeArea{border:1px solid #c9c9c9;padding:5px 10px;background:#fff;margin:20px 0}.active{border:1px solid #66ceff;box-shadow:0 0 2px #66ceff}.writeArea .word{display:inline-block;font-size:18px}.writeArea input{border:0;font-size:18px;outline:0;color:#fff}.writeArea input:focus{outline:0}@keyframes blink{50%{opacity:.0}}@-webkit-keyframes blink{50%{opacity:.0}}.blink{display:inline-block;font-size:14px;color:878383;animation:blink 1s step-start 0s infinite;-webkit-animation:blink 1s step-start 0s infinite}.writeArea.alert-danger{background:#f2dede}.writeArea.alert-danger input{background:#f2dede;color:#f2dede}.highlightWord span{font-weight:bold;border-bottom:1px solid #000}.practice .msgHolder{position:absolute;width:100%;height:100%;top:0;left:0;background:rgba(0,0,0,0.7)}.practice .messegebox{position:absolute;background:#fff;top:100px;left:30%;width:400px;transform:translateX(-150px);padding:10px;border:1px solid #c9c9c9;box-shadow:0 0 5px #f8f8f8;border-radius:5px}
4 | .footer li a{margin:10px}
5 |
6 | .highlight.key{background:#daf1fe !important}.highlightLetter.key{background:#6cedc4 !important}#keyboard{margin-left:-15px;left:0;width:784px;background:#f3f3f3}ul{list-style-type:none;width:784px;margin:0 auto}li{float:left}.key{display:block;color:#aaa;font:bold 9pt arial;text-decoration:none;text-align:center;width:44px;height:41px;margin:5px;background:#eff0f2;-moz-border-radius:4px;border-radius:4px;border-top:1px solid #f5f5f5;-webkit-box-shadow:inset 0 0 25px #e8e8e8,0 1px 0 #c3c3c3,0 2px 0 #c9c9c9,0 2px 3px #333;-moz-box-shadow:inset 0 0 25px #e8e8e8,0 1px 0 #c3c3c3,0 2px 0 #c9c9c9,0 2px 3px #333;box-shadow:inset 0 0 25px #e8e8e8,0 1px 0 #c3c3c3,0 2px 0 #c9c9c9,0 2px 3px #333;text-shadow:0 1px 0 #f5f5f5}.key:active,.keydown{color:#888;background:#ebeced;margin:7px 5px 3px;-webkit-box-shadow:inset 0 0 25px #ddd,0 0 3px #333;-moz-box-shadow:inset 0 0 25px #ddd,0 0 3px #333;box-shadow:inset 0 0 25px #ddd,0 0 3px #333;border-top:1px solid #eee}.fn span{display:block;margin:14px 5px 0 0;text-align:right;font:bold 6pt arial;text-transform:uppercase}#esc{margin:6px 15px 0 0;font-size:7.5pt;text-transform:lowercase}#numbers li a span{display:block}#numbers li a b{margin:3px 0 3px;display:block}#numbers li .alt b{display:block;margin:0 0 3px}#numbers li #backspace span{text-align:right;margin:23px 10px 0 0;font-size:7.5pt;text-transform:lowercase}#qwerty li a,#asdfg li a,#zxcvb li a{display:block;position:relative;color:#4b4949}#qwerty li a span,#asdfg li a span,#zxcvb li a span{display:block;text-transform:uppercase}#qwerty li a span.en,#asdfg li a span.en,#zxcvb li a span.en{position:absolute;display:inline-block;color:#b86c0d;top:25px;left:5px}#qwerty li a span.en-shift,#asdfg li a span.en-shift,#zxcvb li a span.en-shift{position:absolute;display:inline-block;color:#b86c0d;top:5px;left:5px}#qwerty li a span.np,#asdfg li a span.np,#zxcvb li a span.np{position:absolute;display:inline-block;color:#000;top:20px;left:25px}#qwerty li #tab span{text-align:left;margin:23px 0 0 10px;font-size:7.5pt;text-transform:lowercase}#qwerty li .alt b{display:block;margin:3px 0 0}#qwerty li .alt span{margin:2px 0 0}#asdfg li .alt span{margin:0;text-transform:lowercase}#asdfg li .alt b{display:block;margin:3px 0 0}#asdfg li #caps b{display:block;background:#999;width:4px;height:4px;border-radius:10px;margin:9px 0 0 10px;-webkit-box-shadow:inset 0 1px 0 #666;-moz-box-shadow:inset 0 1px 0 #666;box-shadow:inset 0 1px 0 #666}#asdfg li #caps span{text-align:left;margin:10px 0 0 10px;font-size:7.5pt}#asdfg li #enter span{text-align:right;margin:23px 10px 0 0;font-size:7.5pt}#zxcvb li .shiftleft span{text-align:left;margin:23px 0 0 10px;font-size:7.5pt;text-transform:lowercase}#zxcvb li .shiftright span{text-align:right;margin:23px 10px 0 0;font-size:7.5pt;text-transform:lowercase}#zxcvb li .alt b{display:block;margin:4px 0 0}#zxcvb li .alt span{margin:0}#bottomrow li #fn span,#bottomrow li #Ctrl span,#bottomrow li #mjtleft span,#bottomrow li #AltKeyleft span{display:block;text-align:left;margin:31px 0 0 8px;font-size:7.5pt;text-transform:lowercase}#bottomrow li #CtrlKeyright span,#bottomrow li #AltKeyright span{display:block;text-align:right;margin:31px 8px 0 0;font-size:7.5pt;text-transform:lowercase}#bottomrow ol li #left span,#bottomrow ol li #right span,#bottomrow ol li #up span,#bottomrow ol li #down span{display:block;margin:9px 0 0}.fn{height:26px;width:46px}#backspace{width:72px}#tab{width:72px}#caps{width:85px}#enter{width:85px}.shiftleft,.shiftright{width:112px}#fn,#Ctrl,.mjt,#CtrlKeyright,.AltKey,#spacebar{height:49px}.ctrl{width:75px}.mjt{width:46px}.AltKey{width:67px}#spacebar{width:226px}#left img,#up img,#down img,#right img{border:0}ul ol{list-style-type:none}#down{height:23px}#up,#left,#right{height:24px}#left,#right{margin:30px 5px 5px}#left:active,#right:active{margin:32px 5px 3px}#up{margin:5px 5px 1px;border-bottom-right-radius:0;border-bottom-left-radius:0}#up:active{margin:8px 5px -2px}#down{margin:0 5px 5px;border-top-left-radius:0;border-top-right-radius:0}#down:active{margin:3px 5px 4px}#main{width:700px;padding:20px 50px;margin:0 auto 50px;background:#fff;border-radius:5px;-webkit-box-shadow:0 1px 2px #aaa}h1{color:#888;text-align:center;font:bold 25pt/25pt arial;margin:30px 0 60px}h2{color:#666;font:13pt/0 arial}p{color:#999;font:9pt/17pt arial;margin:0 0 50px}small{font:italic 8pt/12pt arial;color:#aaa;padding:0 130px 0 0;display:block}cite{display:block;padding:0 0 30px;margin:0 auto;text-align:center;color:#999;font:italic bold 8pt arial}ul,ol{padding:0;margin:0}.cf:before,.cf:after{content:"";display:table}.cf:after{clear:both}.cf{zoom:1}
--------------------------------------------------------------------------------
/client/components/common/keyboard/keyboard.css:
--------------------------------------------------------------------------------
1 | .highlight {
2 |
3 | }
4 |
5 | .highlight.key {
6 | background: #daf1fe !important;
7 | }
8 |
9 | .highlightLetter.key {
10 | background: #6cedc4 !important;
11 | }
12 |
13 | /*
14 | First Keyboad layout design forked from
15 | http://cssdeck.com/labs/apple-keyboard-via-css3
16 | redefined by mjt
17 | */
18 | #keyboard {
19 | /*margin: 15px auto 0;*/
20 | margin-left: -15px;
21 | left: 0;
22 | width: 784px;
23 | /*padding: 10px 0 0 10px;*/
24 | background: #f3f3f3;
25 | /*left: 50%;*/
26 | /*transform:translateX(250px);*/
27 | /*display: none;*/
28 | }
29 |
30 | ul {list-style-type: none; width: 784px; margin: 0 auto;}
31 | li {float: left;}
32 |
33 |
34 | .key{
35 | display: block;
36 | color: #aaa;
37 | font: bold 9pt arial;
38 | text-decoration: none;
39 | text-align: center;
40 | width: 44px;
41 | height: 41px;
42 | margin: 5px;
43 | background: #eff0f2;
44 | -moz-border-radius: 4px;
45 | border-radius: 4px;
46 | border-top: 1px solid #f5f5f5;
47 | -webkit-box-shadow:
48 | inset 0 0 25px #e8e8e8,
49 | 0 1px 0 #c3c3c3,
50 | 0 2px 0 #c9c9c9,
51 | 0 2px 3px #333;
52 | -moz-box-shadow:
53 | inset 0 0 25px #e8e8e8,
54 | 0 1px 0 #c3c3c3,
55 | 0 2px 0 #c9c9c9,
56 | 0 2px 3px #333;
57 | box-shadow:
58 | inset 0 0 25px #e8e8e8,
59 | 0 1px 0 #c3c3c3,
60 | 0 2px 0 #c9c9c9,
61 | 0 2px 3px #333;
62 | text-shadow: 0px 1px 0px #f5f5f5;}
63 |
64 | .key:active, .keydown {
65 | color: #888;
66 | background: #ebeced;
67 | margin: 7px 5px 3px;
68 | -webkit-box-shadow:
69 | inset 0 0 25px #ddd,
70 | 0 0 3px #333;
71 | -moz-box-shadow:
72 | inset 0 0 25px #ddd,
73 | 0 0 3px #333;
74 | box-shadow:
75 | inset 0 0 25px #ddd,
76 | 0 0 3px #333;
77 | border-top: 1px solid #eee;}
78 |
79 | .fn span {
80 | display: block;
81 | margin: 14px 5px 0 0;
82 | text-align: right;
83 | font: bold 6pt arial;
84 | text-transform: uppercase;}
85 | #esc {
86 | margin: 6px 15px 0 0;
87 | font-size: 7.5pt;
88 | text-transform: lowercase;}
89 |
90 |
91 | #numbers li a span {
92 | display: block;}
93 |
94 | #numbers li a b {
95 | margin: 3px 0 3px;
96 | display: block;}
97 |
98 | #numbers li .alt b {display: block;margin: 0 0 3px;}
99 |
100 | #numbers li #backspace span {
101 | text-align: right;
102 | margin: 23px 10px 0 0;
103 | font-size: 7.5pt;
104 | text-transform: lowercase;}
105 |
106 | #qwerty li a,
107 | #asdfg li a,
108 | #zxcvb li a {
109 | display: block;
110 | position: relative;
111 | color: #4b4949;
112 | }
113 |
114 | #qwerty li a span,
115 | #asdfg li a span,
116 | #zxcvb li a span {
117 | display: block;
118 | /*margin: 13px 0 0;*/
119 | text-transform: uppercase;}
120 |
121 | #qwerty li a span.en,
122 | #asdfg li a span.en,
123 | #zxcvb li a span.en {
124 | position: absolute;
125 | display: inline-block;
126 | color: #b86c0d;
127 | top: 25px ;
128 | left: 5px;
129 | }
130 |
131 | #qwerty li a span.en-shift,
132 | #asdfg li a span.en-shift,
133 | #zxcvb li a span.en-shift {
134 | position: absolute;
135 | display: inline-block;
136 | color: #b86c0d;
137 | top: 5px ;
138 | left: 5px;
139 | }
140 |
141 | #qwerty li a span.np,
142 | #asdfg li a span.np,
143 | #zxcvb li a span.np {
144 | position: absolute;
145 | display: inline-block;
146 | color: #000;
147 | top: 20px ;
148 | left: 25px;
149 | /*font-weight: bold;*/
150 | }
151 |
152 | #qwerty li #tab span {
153 | text-align: left;
154 | margin: 23px 0 0 10px;
155 | font-size: 7.5pt;
156 | text-transform: lowercase;}
157 |
158 | #qwerty li .alt b {display: block; margin: 3px 0 0;}
159 | #qwerty li .alt span {margin: 2px 0 0;}
160 |
161 |
162 | #asdfg li .alt span {margin: 0; text-transform: lowercase;}
163 | #asdfg li .alt b {display: block; margin: 3px 0 0;}
164 | #asdfg li #caps b {
165 | display: block;
166 | background: #999;
167 | width: 4px;
168 | height: 4px;
169 | border-radius: 10px;
170 | margin: 9px 0 0 10px;
171 | -webkit-box-shadow: inset 0 1px 0 #666;
172 | -moz-box-shadow:inset 0 1px 0 #666;
173 | box-shadow:inset 0 1px 0 #666;}
174 | #asdfg li #caps span {
175 | text-align: left;
176 | margin: 10px 0 0 10px;
177 | font-size: 7.5pt;}
178 | #asdfg li #enter span {
179 | text-align: right;
180 | margin: 23px 10px 0 0;
181 | font-size: 7.5pt;}
182 |
183 |
184 | #zxcvb li .shiftleft span {
185 | text-align: left;
186 | margin: 23px 0 0 10px;
187 | font-size: 7.5pt;
188 | text-transform: lowercase;}
189 | #zxcvb li .shiftright span {
190 | text-align: right;
191 | margin: 23px 10px 0 0;
192 | font-size: 7.5pt;
193 | text-transform: lowercase;}
194 | #zxcvb li .alt b {display: block;margin: 4px 0 0;}
195 | #zxcvb li .alt span {margin: 0;}
196 |
197 |
198 | #bottomrow li #fn span,
199 | #bottomrow li #Ctrl span,
200 | #bottomrow li #mjtleft span,
201 | #bottomrow li #AltKeyleft span {
202 | display: block;
203 | text-align: left;
204 | margin: 31px 0 0 8px;
205 | font-size: 7.5pt;
206 | text-transform: lowercase;
207 | }
208 |
209 | #bottomrow li #CtrlKeyright span,
210 | #bottomrow li #AltKeyright span {
211 | display: block;
212 | text-align: right;
213 | margin: 31px 8px 0 0;
214 | font-size: 7.5pt;
215 | text-transform: lowercase;}
216 |
217 | #bottomrow ol li #left span,
218 | #bottomrow ol li #right span,
219 | #bottomrow ol li #up span,
220 | #bottomrow ol li #down span {
221 | display: block;
222 | margin: 9px 0 0;}
223 |
224 | .fn {height: 26px; width: 46px;}
225 | #backspace {width: 72px;}
226 | #tab {width: 72px;}
227 | #caps {width: 85px;}
228 | #enter {width: 85px;}
229 | .shiftleft, .shiftright {width: 112px;}
230 | #fn, #Ctrl, .mjt, #CtrlKeyright, .AltKey, #spacebar {height: 49px;}
231 |
232 | .ctrl {width: 75px;}
233 | .mjt {width: 46px;}
234 | .AltKey {width: 67px;}
235 | #spacebar {width: 226px;}
236 |
237 | #left img, #up img, #down img, #right img {border: none;}
238 | ul ol {list-style-type: none;}
239 | #down {height: 23px;}
240 | #up, #left, #right {height: 24px;}
241 | #left, #right {margin: 30px 5px 5px;}
242 | #left:active, #right:active {margin: 32px 5px 3px;}
243 | #up {margin: 5px 5px 1px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px;}
244 | #up:active {margin: 8px 5px -2px;}
245 | #down {margin: 0 5px 5px; border-top-left-radius: 0px; border-top-right-radius: 0px;}
246 | #down:Active {margin: 3px 5px 4px;}
247 | #main {
248 | width: 700px;
249 | padding: 20px 50px;
250 | margin: 0 auto 50px;
251 | background: #fff;
252 | border-radius: 5px;
253 | -webkit-box-shadow: 0 1px 2px #aaa;}
254 |
255 | h1 {
256 | color: #888;
257 | text-align: center;
258 | font: bold 25pt/25pt arial;
259 | margin: 30px 0 60px;}
260 |
261 | h2 {
262 | color: #666;
263 | font: 13pt/0pt arial;}
264 |
265 | p {
266 | color: #999;
267 | font: 9pt/17pt arial;
268 | margin: 0 0 50px;}
269 |
270 | small {
271 | font: italic 8pt/12pt arial;
272 | color: #aaa;
273 | padding: 0 130px 0 0;
274 | display: block;}
275 |
276 | cite {
277 | display: block;
278 | padding: 0 0 30px;
279 | margin: 0 auto;
280 | text-align: center;
281 | color: #999;
282 | font: italic bold 8pt arial;}
283 |
284 | ul, ol {padding: 0px; margin: 0;}
285 |
286 | /* Micro Clearfix by Nicolas Gallagher - http://nicolasgallagher.com/micro-clearfix-hack */
287 | /* For modern browsers */
288 | .cf:before, .cf:after {content:""; display:table;}
289 | .cf:after {clear:both;}
290 |
291 | /* For IE 6/7 (trigger hasLayout) */
292 | .cf {zoom:1;}
--------------------------------------------------------------------------------
/client/views/practice/practise.ctrl.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('typali')
4 |
5 | .config(['$stateProvider', function ($stateProvider) {
6 | $stateProvider
7 | .state('app.practice', {
8 | url: '/practice',
9 | views: {
10 | 'container@': {
11 | templateUrl: 'views/practice/practice.tpl.html',
12 | controller: 'practiceCtrl',
13 | controllerAs: "vm"
14 | }
15 | }
16 | })
17 | .state('app.practice.param', {
18 | url: '/:param',
19 | views: {
20 | 'container@': {
21 | templateUrl: 'views/practice/practice.tpl.html',
22 | controller: 'practiceCtrl',
23 | controllerAs: "vm"
24 | }
25 | }
26 | });
27 |
28 | }])
29 |
30 | .controller('practiceCtrl', PracticeCtrl);
31 |
32 | PracticeCtrl.$inject = ['$rootScope', '$scope', '$stateParams', '$document', "keyboardlayout", '$interval', 'datafetchService'];
33 | function PracticeCtrl($rootScope, $scope, $stateParams, $document, keyboardlayout, $interval, datafetchService) {
34 | var vm = this;
35 |
36 | var param = $stateParams.param;
37 |
38 | /*param*/
39 |
40 | if (typeof param == 'undefined' || param == '') {
41 | param = Math.floor((Math.random() * 10));
42 | }
43 |
44 | // console.log("param = ", param);
45 |
46 | vm.isloading = true;
47 |
48 | var isFirstLetter = true;
49 |
50 | var arrString,
51 | lenString,
52 | count = 0,
53 | countLetter = 0,
54 | grossCount = 0,
55 | isLetterCorrect = false;
56 |
57 | var initTime = 0;
58 |
59 | vm.time = 0;
60 | var timeRunner;
61 |
62 | var word = '';
63 | var sentence = '';
64 |
65 |
66 | var typedisable = false;
67 |
68 | vm.sentence = "";
69 |
70 | vm.word = "Type here";
71 |
72 | vm.alert = false;
73 |
74 | var str = "सानो छ खेत";
75 | var textAll = {};
76 |
77 |
78 | /*promise to get string*/
79 | var promise = datafetchService.getString(param);
80 | promise.then(function (response) {
81 |
82 | var contents = response.data;
83 | // console.log(contents);
84 | textAll = contents.data;
85 | str = contents.data.text;
86 | // str = str;
87 | afterStringIsArrived();
88 | messagebox();
89 | })
90 | .catch(function (error) {
91 | console.log(error);
92 | })
93 |
94 |
95 | /* keyboard settlement*/
96 | var allKeys,
97 | engData_all,
98 | codeData_all,
99 | npData_all,
100 | npShiftData_all;
101 |
102 | var keyboard = (typeof $rootScope.lang!=='undefined') ? keyboardlayout[$rootScope.lang] : keyboardlayout.unicode ;
103 | console.log(keyboard);
104 |
105 | function keyboard__() {
106 | vm.keyboard = keyboard;
107 |
108 | allKeys = []
109 | for (var key in keyboard) {
110 | for (var i = 0; i < keyboard[key].length; i++) {
111 | allKeys.push(keyboard[key][i])
112 | };
113 | }
114 |
115 | engData_all = allKeys.map(function (item) { return item.en; });
116 | codeData_all = allKeys.map(function (item) { return item.code; });
117 | npData_all = allKeys.map(function (item) { return item.np; });
118 | npShiftData_all = allKeys.map(function (item) { return item.npShift; });
119 | }
120 |
121 | keyboard__();
122 |
123 | $rootScope.$on("lang",function(event,data){
124 | // console.log("yo");
125 | keyboard = keyboardlayout[$rootScope.lang];
126 | keyboard__();
127 | // afterStringIsArrived();
128 | })
129 |
130 | /* key board settlement ends*/
131 |
132 | function afterStringIsArrived() {
133 |
134 |
135 | arrString = str.split(" ");
136 | lenString = arrString.length;
137 |
138 | count = 0;
139 |
140 | countLetter = 0;
141 |
142 | grossCount = 0;
143 |
144 | isLetterCorrect = false;
145 |
146 | vm.highlight = arrString[count];
147 | vm.highlightSingle = "";
148 |
149 | vm.text = arrString;
150 |
151 | setTimeout(function () {
152 | highlightWord();
153 | }, 1000);
154 |
155 | vm.isloading = false;
156 |
157 | }
158 |
159 |
160 |
161 |
162 |
163 | $('.writeArea').on('click', function () {
164 | $document.find(".writeArea input").focus();
165 | })
166 |
167 | $document.find(".writeArea input").on('keydown', function (event) {
168 | console.log("keypress");
169 | if (typedisable) {
170 | return;
171 | }
172 |
173 | if (isFirstLetter) {
174 | isFirstLetter = false;
175 | initialiseTime();
176 | }
177 |
178 | var code = event.which || event.charCode;
179 | // console.log(code,character,event.shiftKey);
180 | var newChar = '';
181 |
182 | var shift = event.shiftKey;
183 |
184 | if (code == 8 || code == 46) {
185 | console.log("backspace");
186 | if (isLetterCorrect && countLetter > 0) {
187 | countLetter = countLetter - 1;
188 | console.log("backspace", countLetter);
189 | // highlightSingleKey();
190 | };
191 | word = word.substring(0, word.length - 1);
192 | vm.word = word;
193 | $scope.$apply();
194 | validateQuick();
195 |
196 | } else if (code == 32) {
197 | console.log("space has been pressed 1");
198 | validateWord();
199 | } else {
200 | code += "";
201 | var character = '';
202 | console.log("code = ", code, codeData_all.indexOf(code));
203 | if (codeData_all.indexOf(code) > -1) {
204 | if (shift) {
205 | character = allKeys[codeData_all.indexOf(code)].npShift;
206 | } else {
207 | character = allKeys[codeData_all.indexOf(code)].np;
208 | }
209 |
210 | console.log(character);
211 |
212 | word = word + character;
213 |
214 | vm.inputChar = ''
215 | vm.word = word;
216 |
217 | $scope.$apply();
218 | // $scope.$digest()
219 | validateQuick();
220 | }
221 |
222 |
223 | }
224 |
225 |
226 | })
227 |
228 |
229 | function validateQuick() {
230 | var len = word.length;
231 | var compareStr = arrString[count].substring(0, len);
232 |
233 | console.log(word, compareStr);
234 |
235 | if (word != compareStr) {
236 | vm.alert = true;
237 | } else {
238 | vm.alert = false;
239 | if (isLetterCorrect) {
240 | countLetter++;
241 | }
242 | countLetter = len;
243 | isLetterCorrect = true;
244 | highlightSingleKey();
245 | //
246 | }
247 | $scope.$apply();
248 | }
249 |
250 |
251 | function validateWord() {
252 | console.log("space has been pressed");
253 | if (word === arrString[count]) {
254 | countLetter = 0;
255 | sentence += word + " ";
256 | word = '';
257 | vm.sentence = sentence;
258 | vm.word = word;
259 | count++;
260 |
261 | grossCount = grossCount + countLetter + 1;
262 |
263 | countLetter = 0;
264 | $scope.$apply();
265 | if (count >= vm.text.length) {
266 | typedisable = true;
267 | timeRunner
268 | $interval.cancel(timeRunner);
269 | stop = undefined;
270 | vm.msgbox = true;
271 | console.log("string complete", vm.msgbox);
272 | $scope.$apply();
273 | } else {
274 | highlightKeys();
275 |
276 | highlightWord();
277 | }
278 |
279 | calulateWPM();
280 | };
281 | }
282 |
283 |
284 | function highlightKeys() {
285 | vm.highlight = arrString[count];
286 | highlightSingleKey();
287 | }
288 |
289 | function highlightSingleKey() {
290 |
291 | var letterToHighlight = arrString[count].charAt(countLetter);
292 |
293 | if (letterToHighlight == '') {
294 | vm.highlightSingle = ' '
295 | return;
296 | };
297 |
298 | vm.highlightSingle = letterToHighlight;
299 | }
300 |
301 | vm.highlightSingleFn = function () {
302 | if (typedisable) return;
303 | highlightSingleKey();
304 | }
305 |
306 | function highlightWord() {
307 | var countWordHere = count + 1;
308 | $document.find(".text span").removeClass("highlightWord");
309 | $document.find(".text > span:nth-child(" + countWordHere + ")").addClass("highlightWord");
310 | }
311 |
312 |
313 |
314 |
315 |
316 | function initialiseTime() {
317 | var d = new Date();
318 | initTime = d.getTime();
319 |
320 |
321 |
322 | timeRunner = $interval(function () {
323 | vm.time += 1;
324 | }, 1000);
325 |
326 | }
327 |
328 | function calulateWPM() {
329 | var d = new Date();
330 | var hereTime = d.getTime();
331 |
332 | var timeTaken = hereTime - initTime;
333 | vm.timeTaken = timeTaken;
334 | var wpm = 1000 * 60 * (grossCount / 6) / timeTaken;
335 | vm.speed = Math.round(wpm);
336 | }
337 |
338 | function messagebox() {
339 | vm.art = {
340 | title: textAll.title,
341 | author: textAll.author
342 | }
343 |
344 | console.log("textAll", textAll);
345 |
346 | }
347 |
348 |
349 | };
--------------------------------------------------------------------------------
/dist/app.min.js:
--------------------------------------------------------------------------------
1 | "use strict";function run(n,e,t,o){n.$on("$routeChangeStart",function(n,e,t){}),n.facebookAppId="[]"}function keyboardCtrl(n,e){function t(e){console.log("letter again = ",i.letter),$(".highlightLetter").removeClass("highlightLetter")," "==e?o="spacebar":a.indexOf(e)>-1?(o="c"+c[a.indexOf(e)],console.log(a,a.indexOf(e))):(o="c"+c[l.indexOf(e)],$(".shiftKey").addClass("highlightLetter")),console.log("letter again = ",i.letter,o),n.find("."+o).addClass("highlightLetter")}var o,i=this,r=i.keyboard;console.log("letter = ",i.letter);var c,a,l,p=[];for(var f in r)for(var d=0;d=S.text.length?(O=!0,r.cancel(A),stop=void 0,S.msgbox=!0,console.log("string complete",S.msgbox),e.$apply()):(d(),u()),g())}function d(){S.highlight=y[k],h()}function h(){var n=y[k].charAt(w);if(""==n)return void(S.highlightSingle=" ");S.highlightSingle=n}function u(){var n=k+1;o.find(".text span").removeClass("highlightWord"),o.find(".text > span:nth-child("+n+")").addClass("highlightWord")}function s(){var n=new Date;j=n.getTime(),A=r(function(){S.time+=1},1e3)}function g(){var n=new Date,e=n.getTime(),t=e-j;S.timeTaken=t;var o=x/6*6e4/t;S.speed=Math.round(o)}function m(){S.art={title:L.title,author:L.author},console.log("textAll",L)}var S=this,v=t.param;void 0!==v&&""!=v||(v=Math.floor(10*Math.random())),S.isloading=!0;var y,C,b=!0,k=0,w=0,x=0,F=!1,j=0;S.time=0;var A,P="",U="",O=!1;S.sentence="",S.word="Type here",S.alert=!1;var H="सानो छ खेत",L={};c.getString(v).then(function(n){var e=n.data;L=e.data,H=e.data.text,l(),m()}).catch(function(n){console.log(n)});var T,z,E,q,I,M=void 0!==n.lang?i[n.lang]:i.unicode;console.log(M),a(),n.$on("lang",function(e,t){M=i[n.lang],a()}),$(".writeArea").on("click",function(){o.find(".writeArea input").focus()}),o.find(".writeArea input").on("keydown",function(n){if(console.log("keypress"),!O){b&&(b=!1,s());var t=n.which||n.charCode,o=n.shiftKey;if(8==t||46==t)console.log("backspace"),F&&w>0&&(w-=1,console.log("backspace",w)),P=P.substring(0,P.length-1),S.word=P,e.$apply(),p();else if(32==t)console.log("space has been pressed 1"),f();else{t+="";var i="";console.log("code = ",t,E.indexOf(t)),E.indexOf(t)>-1&&(i=o?T[E.indexOf(t)].npShift:T[E.indexOf(t)].np,console.log(i),P+=i,S.inputChar="",S.word=P,e.$apply(),p())}}}),S.highlightSingleFn=function(){O||h()}}function EditorCtrl(n){for(var e=["000000","FF9966","6699FF","99FF66","CC0000","00CC00","0000CC","333333","0066FF","FFFFFF"],t=$(".fore-palette"),o=$(".back-palette"),i=0;i'),o.append('');$(".toolbar a").click(function(n){var e=$(this).data("command");"h1"!=e&&"h2"!=e&&"p"!=e||document.execCommand("formatBlock",!1,e),"forecolor"!=e&&"backcolor"!=e||document.execCommand($(this).data("command"),!1,$(this).data("value")),"createlink"==e||"insertimage"==e?(url=prompt("Enter the link here: ","http://"),document.execCommand($(this).data("command"),!1,url)):document.execCommand($(this).data("command"),!1,null)})}function HomeCtrl(n,e){var t=this;e.lang="unicode",t.lang=e.lang,t.update=function(){console.log("lang",t.lang),e.lang=t.lang,e.$broadcast("lang",t.lang)}}var app=angular.module("typali",["ui.router","ngSanitize","angular-loading-bar"]).config(["$locationProvider","$stateProvider","$urlRouterProvider",function(n,e,t){n.hashPrefix("!"),t.otherwise("/404"),e.state("app",{url:"",views:{"header@":{controller:"HeaderCtrl",templateUrl:"components/common/header/header.tpl.html",controllerAs:"vm"},"footer@":{controller:"FooterCtrl",templateUrl:"components/common/footer/footer.tpl.html",controllerAs:"vm"}}}).state("app.404",{url:"/404",views:{"header@":{templateUrl:"components/common/header/header.tpl.html"}}}),n.html5Mode(!0)}]).run(["$rootScope","$location","authentication","$window",run]);angular.module("typali").component("keyboard2",{templateUrl:"components/common/keyboard/keyboard.tpl.html",controller:keyboardCtrl,bindings:{keyboard:"<",word:"<",letter:"<",shift:"<"}}),keyboardCtrl.$inject=["$document","$scope"],angular.module("typali").controller("HeaderCtrl",HeaderCtrl),HeaderCtrl.$inject=["$scope","$rootScope"],angular.module("typali").controller("FooterCtrl",FooterCtrl),FooterCtrl.$inject=["$scope"],angular.module("typali").config(["$stateProvider",function(n){n.state("app.practice",{url:"/practice",views:{"container@":{templateUrl:"views/practice/practice.tpl.html",controller:"practiceCtrl",controllerAs:"vm"}}}).state("app.practice.param",{url:"/:param",views:{"container@":{templateUrl:"views/practice/practice.tpl.html",controller:"practiceCtrl",controllerAs:"vm"}}})}]).controller("practiceCtrl",PracticeCtrl),PracticeCtrl.$inject=["$rootScope","$scope","$stateParams","$document","keyboardlayout","$interval","datafetchService"],angular.module("typali").config(["$stateProvider",function(n){n.state("app.editor",{url:"/editor",views:{"container@":{templateUrl:"views/editor/editor.tpl.html",controller:"editorCtrl",controllerAs:"vm"}}})}]).controller("editorCtrl",EditorCtrl),EditorCtrl.$inject=["$scope"],angular.module("typali").config(["$stateProvider",function(n){n.state("app.home",{url:"/",views:{"container@":{templateUrl:"views/home/home.tpl.html",controller:"HomeCtrl",controllerAs:"vm"}}})}]).controller("HomeCtrl",HomeCtrl),HomeCtrl.$inject=["$scope","$rootScope"],function(){function n(n,e){}angular.module("typali").config(["$stateProvider",function(n){n.state("app.register",{url:"/register",views:{"container@":{templateUrl:"auth/user-register/user-register.tpl.html",controller:"UserRegisterCtrl",controllerAs:"vm"}}})}]).controller("UserRegisterCtrl",n),n.$inject=["$location","authentication"]}(),function(){function n(n,e){var t=this;t.credentials={email:"yo@hotmail.com",password:""},t.onSubmit=function(){e.login(t.credentials).error(function(n){console.log(n)}).then(function(){n.path("profile")})}}angular.module("typali").config(["$stateProvider",function(n){n.state("app.login",{url:"/login",views:{"container@":{templateUrl:"auth/login/login.tpl.html",controller:"LoginCtrl",controllerAs:"vm"}}})}]).controller("LoginCtrl",n),n.$inject=["$location","authentication"]}(),angular.module("typali").factory("socket",["$rootScope",function(n){var e=io.connect();return{on:function(t,o){e.on(t,function(){var t=arguments;n.$apply(function(){o.apply(e,t)})})},emit:function(t,o,i){e.emit(t,o,function(){var t=arguments;n.$apply(function(){i&&i.apply(e,t)})})}}}]);var app=angular.module("typali");app.filter("limitobj",[function(){return function(n,e){if("object"!=typeof n)return[];var t=Object.keys(n);if(t.length<1||void 0===t)return[];var o=new Object,i=0;return angular.forEach(t,function(t,r){if(i>=e)return!1;o[t]=n[t],i++}),o}}]),angular.module("typali").factory("keyboardlayout",["$rootScope",function(n){var e={};return e.unicode={qwerty:[{code:"81",en:"q",npShift:"ठ",np:"ट"},{code:"87",en:"w",npShift:"औ",np:"ौ"},{code:"69",en:"e",npShift:"ै",np:"े"},{code:"82",en:"r",npShift:"ृ",np:"र"},{code:"84",en:"t",npShift:"थ",np:"त"},{code:"89",en:"y",npShift:"ञ",np:"य"},{code:"85",en:"u",npShift:"ू",np:"ु"},{code:"73",en:"i",npShift:"ी",np:"ि"},{code:"79",en:"o",npShift:"ओ",np:"ो"},{code:"80",en:"p",npShift:"फ",np:"प"},{code:"219",en:"[",npShift:"ई",np:"इ"},{code:"221",en:"]",npShift:"ऐ",np:"ए"},{code:"220",en:"\\",npShift:"ः",np:"ॐ"}],asdfg:[{code:"65",en:"a",npShift:"आ",np:"ा"},{code:"83",en:"s",npShift:"श",np:"स"},{code:"68",en:"d",npShift:"ध",np:"द"},{code:"70",en:"f",npShift:"ऊ",np:"उ"},{code:"71",en:"g",npShift:"घ",np:"ग"},{code:"72",en:"h",npShift:"अ",np:"ह"},{code:"74",en:"j",npShift:"झ",np:"ज"},{code:"75",en:"k",npShift:"ख",np:"क"},{code:"76",en:"l",npShift:"॥",np:"ल"},{code:"186",en:"l",npShift:":",np:";"},{code:"222",en:"l",npShift:'"',np:"'"}],zxcvb:[{code:"90",en:"z",npShift:"ऋ",np:"ष"},{code:"88",en:"x",npShift:"ढ",np:"ड"},{code:"67",en:"c",npShift:"च",np:"छ"},{code:"86",en:"v",npShift:"ँ",np:"व"},{code:"66",en:"b",npShift:"भ",np:"ब"},{code:"78",en:"n",npShift:"ण",np:"न"},{code:"77",en:"m",npShift:"ं",np:"म"},{code:"188",en:",",npShift:"ङ",np:","},{code:"190",en:".",npShift:">",np:"।"},{code:"191",en:"/",npShift:"?",np:"्"}],1234:[{code:"192",en:"`",enShift:"~",npShift:"~",np:"`"},{code:"49",en:"1",npShift:"!",np:"१"},{code:"50",en:"2",npShift:"@",np:"२"},{code:"51",en:"3",npShift:"#",np:"३"},{code:"52",en:"4",npShift:"रु",np:"४"},{code:"53",en:"5",npShift:"%",np:"५"},{code:"54",en:"6",npShift:"^",np:"६"},{code:"55",en:"7",npShift:"&",np:"७"},{code:"56",en:"8",npShift:"*",np:"८"},{code:"59",en:"9",npShift:"(",np:"९"},{code:"48",en:"0",npShift:")",np:"०"},{code:"189",en:"-",npShift:"_",np:"-"},{code:"187",en:"=",npShift:"+",np:"="}]},e.unicodeTraditional={qwerty:[{code:"81",en:"q",npShift:"त्त",np:"त्र"},{code:"87",en:"w",npShift:"ड्ढ",np:"ध"},{code:"69",en:"e",npShift:"ऐ",np:"भ"},{code:"82",en:"r",npShift:"द्ब",np:"च"},{code:"84",en:"t",npShift:"ट्ट",np:"त"},{code:"89",en:"y",npShift:"ठ्ठ",np:"थ"},{code:"85",en:"u",npShift:"ऊ",np:"ग"},{code:"73",en:"i",npShift:"क्ष",np:"ष"},{code:"79",en:"o",npShift:"इ",np:"य"},{code:"80",en:"p",npShift:"ए",np:"उ"},{code:"219",en:"[",npShift:"ृ",np:"र्"},{code:"221",en:"]",npShift:"ै",np:"े"},{code:"220",en:"\\",npShift:"ं",np:"्"}],asdfg:[{code:"65",en:"a",npShift:"आ",np:"ब"},{code:"83",en:"s",npShift:"ङ्क",np:"क"},{code:"68",en:"d",npShift:"ङ्ग",np:"म"},{code:"70",en:"f",npShift:"ँ",np:"ा"},{code:"71",en:"g",npShift:"द्द",np:"न"},{code:"72",en:"h",npShift:"झ",np:"ज"},{code:"74",en:"j",npShift:"ो",np:"व"},{code:"75",en:"k",npShift:"फ",np:"प"},{code:"76",en:"l",npShift:"ी",np:"ि"},{code:"186",en:";",npShift:"ट्ठ",np:"स"},{code:"222",en:"'",npShift:"ू",np:"ु"}],zxcvb:[{code:"90",en:"z",npShift:"क्क",np:"श"},{code:"88",en:"x",npShift:"ह्य",np:"ह"},{code:"67",en:"c",npShift:"ऋ",np:"अ"},{code:"86",en:"v",npShift:"ॐ",np:"ख"},{code:"66",en:"b",npShift:"ौ",np:"द"},{code:"78",en:"n",npShift:"द्य",np:"ल"},{code:"77",en:"m",npShift:"ड्ड",np:"ः"},{code:"188",en:",",npShift:"ङ",np:"ऽ"},{code:"190",en:".",npShift:"श्र",np:"।"},{code:"191",en:"/",npShift:"रु",np:"र"}],1234:[{code:"192",en:"`",enShift:"~",npShift:"॥",np:"ञ`"},{code:"49",en:"1",enShift:"!",npShift:"ज्ञ",np:"१"},{code:"50",en:"2",enShift:"@",npShift:"ई",np:"२"},{code:"51",en:"3",enShift:"#",npShift:"घ",np:"३"},{code:"52",en:"4",enShift:"$",npShift:"द्ध",np:"४"},{code:"53",en:"5",enShift:"%",npShift:"छ",np:"५"},{code:"54",en:"6",enShift:"^",npShift:"ट",np:"६"},{code:"55",en:"7",enShift:"&",npShift:"ठ",np:"७"},{code:"56",en:"8",enShift:"*",npShift:"ड",np:"८"},{code:"59",en:"9",enShift:"(",npShift:"ढ",np:"९"},{code:"48",en:"0",enShift:")",npShift:"ण",np:"०"},{code:"189",en:"-",enShift:"_",npShift:"ओ",np:"औ"},{code:"187",en:"=",enShift:"+",npShift:"",np:""}]},e}]);var app=angular.module("typali");app.filter("filterByProperty",["$filter",function(n){return function(e,t,o){if(console.log("reached here",t,o),e){if(t){if("$"===o)return n("filter")(e,t);console.log(t);var i=t.toString().toLowerCase();return e.filter(function(n){return n[o].toString().toLowerCase().indexOf(i)>-1})}return e}}}]),function(){function n(n){var e=this,t="https://typali.herokuapp.com/api/";e.getString=function(e){var o=n({cache:!0,method:"GET",url:t+"getstring/"+e});return console.log("url : ",t+"getstring/"+e),o}}angular.module("typali").service("datafetchService",n),n.$inject=["$http"]}(),angular.module("typali").filter("capitalize",function(){return function(n,e){var t=e?/([^\W_]+[^\s-]*) */g:/([^\W_]+[^\s-]*)/;return n?n.replace(t,function(n){return n.charAt(0).toUpperCase()+n.substr(1).toLowerCase()}):""}}),function(){function n(n,e){var t=function(n){e.localStorage["typali-token"]=n},o=function(){return e.localStorage["typali-token"]},i=function(){var n,t=o();return!!t&&(n=t.split(".")[1],n=e.atob(n),n=JSON.parse(n),n.exp>Date.now()/1e3)};return{currentUser:function(){if(i()){var n=o(),t=n.split(".")[1];return t=e.atob(t),t=JSON.parse(t),{email:t.email,name:t.name}}},saveToken:t,getToken:o,isLoggedIn:i,register:function(e){return n.post("/api/register",e).success(function(n){t(n.token)})},login:function(e){return n.post("/api/login",e).success(function(n){console.log(n.token),t(n.token)})},logout:function(){e.localStorage.removeItem("typali-token")}}}angular.module("typali").service("authentication",n),n.$inject=["$http","$window"]}(),angular.module("typali.common",[]);
--------------------------------------------------------------------------------
/client/services/keyboardlayout.service.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | angular.module('typali')
3 | .factory('keyboardlayout', function ($rootScope) {
4 |
5 | /*can add different keybord*/
6 |
7 | /*unicode default keyboard*/
8 | var keyboard = {};
9 | keyboard.unicode = {
10 | "qwerty": [
11 | {
12 | "code": "81",
13 | "en": "q",
14 | "npShift": "ठ",
15 | "np": "ट"
16 | },
17 | {
18 | "code": "87",
19 | "en": "w",
20 | "npShift": "औ",
21 | "np": "ौ"
22 | },
23 | {
24 | "code": "69",
25 | "en": "e",
26 | "npShift": "ै",
27 | "np": "े"
28 | },
29 | {
30 | "code": "82",
31 | "en": "r",
32 | "npShift": "ृ",
33 | "np": "र"
34 | },
35 | {
36 | "code": "84",
37 | "en": "t",
38 | "npShift": "थ",
39 | "np": "त"
40 | },
41 | {
42 | "code": "89",
43 | "en": "y",
44 | "npShift": "ञ",
45 | "np": "य"
46 | },
47 | {
48 | "code": "85",
49 | "en": "u",
50 | "npShift": "ू",
51 | "np": "ु"
52 | },
53 | {
54 | "code": "73",
55 | "en": "i",
56 | "npShift": "ी",
57 | "np": "ि"
58 | },
59 | {
60 | "code": "79",
61 | "en": "o",
62 | "npShift": "ओ",
63 | "np": "ो"
64 | },
65 | {
66 | "code": "80",
67 | "en": "p",
68 | "npShift": "फ",
69 | "np": "प"
70 | },
71 | {
72 | "code": "219",
73 | "en": "[",
74 | "npShift": "ई",
75 | "np": "इ"
76 | },
77 | {
78 | "code": "221",
79 | "en": "]",
80 | "npShift": "ऐ",
81 | "np": "ए"
82 | },
83 | {
84 | "code": "220",
85 | "en": "\\",
86 | "npShift": "ः",
87 | "np": "ॐ"
88 | }
89 | ],
90 | "asdfg": [
91 | {
92 | "code": "65",
93 | "en": "a",
94 | "npShift": "आ",
95 | "np": "ा"
96 | },
97 | {
98 | "code": "83",
99 | "en": "s",
100 | "npShift": "श",
101 | "np": "स"
102 | },
103 | {
104 | "code": "68",
105 | "en": "d",
106 | "npShift": "ध",
107 | "np": "द"
108 | },
109 | {
110 | "code": "70",
111 | "en": "f",
112 | "npShift": "ऊ",
113 | "np": "उ"
114 | },
115 | {
116 | "code": "71",
117 | "en": "g",
118 | "npShift": "घ",
119 | "np": "ग"
120 | },
121 | {
122 | "code": "72",
123 | "en": "h",
124 | "npShift": "अ",
125 | "np": "ह"
126 | },
127 | {
128 | "code": "74",
129 | "en": "j",
130 | "npShift": "झ",
131 | "np": "ज"
132 | },
133 | {
134 | "code": "75",
135 | "en": "k",
136 | "npShift": "ख",
137 | "np": "क"
138 | },
139 | {
140 | "code": "76",
141 | "en": "l",
142 | "npShift": "॥",
143 | "np": "ल"
144 | },
145 | {
146 | "code": "186",
147 | "en": "l",
148 | "npShift": "\:",
149 | "np": "\;"
150 | },
151 | {
152 | "code": "222",
153 | "en": "l",
154 | "npShift": "\"",
155 | "np": "\'"
156 | }
157 | ],
158 | "zxcvb": [
159 |
160 | {
161 | "code": "90",
162 | "en": "z",
163 | "npShift": "ऋ",
164 | "np": "ष"
165 | },
166 | {
167 | "code": "88",
168 | "en": "x",
169 | "npShift": "ढ",
170 | "np": "ड"
171 | },
172 | {
173 | "code": "67",
174 | "en": "c",
175 | "npShift": "च",
176 | "np": "छ"
177 | },
178 | {
179 | "code": "86",
180 | "en": "v",
181 | "npShift": "ँ",
182 | "np": "व"
183 | },
184 | {
185 | "code": "66",
186 | "en": "b",
187 | "npShift": "भ",
188 | "np": "ब"
189 | },
190 | {
191 | "code": "78",
192 | "en": "n",
193 | "npShift": "ण",
194 | "np": "न"
195 | },
196 | {
197 | "code": "77",
198 | "en": "m",
199 | "npShift": "ं",
200 | "np": "म"
201 | },
202 | {
203 | "code": "188",
204 | "en": ",",
205 | "npShift": "ङ",
206 | "np": ","
207 | },
208 | {
209 | "code": "190",
210 | "en": ".",
211 | "npShift": ">",
212 | "np": "।"
213 | },
214 | {
215 | "code": "191",
216 | "en": "/",
217 | "npShift": "?",
218 | "np": "्"
219 | }
220 | ],
221 | "1234": [
222 | {
223 | "code": "192",
224 | "en": "\`",
225 | "enShift": "\~",
226 | "npShift": "\~",
227 | "np": "\`"
228 | }, {
229 | "code": "49",
230 | "en": "1",
231 | "npShift": "!",
232 | "np": "१"
233 | }, {
234 | "code": "50",
235 | "en": "2",
236 | "npShift": "@",
237 | "np": "२"
238 | }, {
239 | "code": "51",
240 | "en": "3",
241 | "npShift": "#",
242 | "np": "३"
243 | }, {
244 | "code": "52",
245 | "en": "4",
246 | "npShift": "रु",
247 | "np": "४"
248 | }, {
249 | "code": "53",
250 | "en": "5",
251 | "npShift": "%",
252 | "np": "५"
253 | }, {
254 | "code": "54",
255 | "en": "6",
256 | "npShift": "^",
257 | "np": "६"
258 | }, {
259 | "code": "55",
260 | "en": "7",
261 | "npShift": "&",
262 | "np": "७"
263 | }, {
264 | "code": "56",
265 | "en": "8",
266 | "npShift": "*",
267 | "np": "८"
268 | }, {
269 | "code": "59",
270 | "en": "9",
271 | "npShift": "(",
272 | "np": "९"
273 | }, {
274 | "code": "48",
275 | "en": "0",
276 | "npShift": ")",
277 | "np": "०"
278 | }, {
279 | "code": "189",
280 | "en": "-",
281 | "npShift": "_",
282 | "np": "-"
283 | }, {
284 | "code": "187",
285 | "en": "=",
286 | "npShift": "+",
287 | "np": "="
288 | }
289 | ]
290 |
291 |
292 | }
293 |
294 | keyboard.unicodeTraditional = {
295 | "qwerty": [
296 | {
297 | "code": "81",
298 | "en": "q",
299 | "npShift": "त्त",
300 | "np": "त्र"
301 | },
302 | {
303 | "code": "87",
304 | "en": "w",
305 | "npShift": "ड्ढ",
306 | "np": "ध"
307 | },
308 | {
309 | "code": "69",
310 | "en": "e",
311 | "npShift": "ऐ",
312 | "np": "भ"
313 | },
314 | {
315 | "code": "82",
316 | "en": "r",
317 | "npShift": "द्ब",
318 | "np": "च"
319 | },
320 | {
321 | "code": "84",
322 | "en": "t",
323 | "npShift": "ट्ट",
324 | "np": "त"
325 | },
326 | {
327 | "code": "89",
328 | "en": "y",
329 | "npShift": "ठ्ठ",
330 | "np": "थ"
331 | },
332 | {
333 | "code": "85",
334 | "en": "u",
335 | "npShift": "ऊ",
336 | "np": "ग"
337 | },
338 | {
339 | "code": "73",
340 | "en": "i",
341 | "npShift": "क्ष",
342 | "np": "ष"
343 | },
344 | {
345 | "code": "79",
346 | "en": "o",
347 | "npShift": "इ",
348 | "np": "य"
349 | },
350 | {
351 | "code": "80",
352 | "en": "p",
353 | "npShift": "ए",
354 | "np": "उ"
355 | },
356 | {
357 | "code": "219",
358 | "en": "[",
359 | "npShift": "ृ",
360 | "np": "र्"
361 | },
362 | {
363 | "code": "221",
364 | "en": "]",
365 | "npShift": "ै",
366 | "np": "े"
367 | },
368 | {
369 | "code": "220",
370 | "en": "\\",
371 | "npShift": "ं",
372 | "np": "्"
373 | }
374 | ],
375 | "asdfg": [
376 | {
377 | "code": "65",
378 | "en": "a",
379 | "npShift": "आ",
380 | "np": "ब"
381 | },
382 | {
383 | "code": "83",
384 | "en": "s",
385 | "npShift": "ङ्क",
386 | "np": "क"
387 | },
388 | {
389 | "code": "68",
390 | "en": "d",
391 | "npShift": "ङ्ग",
392 | "np": "म"
393 | },
394 | {
395 | "code": "70",
396 | "en": "f",
397 | "npShift": "ँ",
398 | "np": "ा"
399 | },
400 | {
401 | "code": "71",
402 | "en": "g",
403 | "npShift": "द्द",
404 | "np": "न"
405 | },
406 | {
407 | "code": "72",
408 | "en": "h",
409 | "npShift": "झ",
410 | "np": "ज"
411 | },
412 | {
413 | "code": "74",
414 | "en": "j",
415 | "npShift": "ो",
416 | "np": "व"
417 | },
418 | {
419 | "code": "75",
420 | "en": "k",
421 | "npShift": "फ",
422 | "np": "प"
423 | },
424 | {
425 | "code": "76",
426 | "en": "l",
427 | "npShift": "ी",
428 | "np": "ि"
429 | },
430 | {
431 | "code": "186",
432 | "en": ";",
433 | "npShift": "ट्ठ",
434 | "np": "स"
435 | },
436 | {
437 | "code": "222",
438 | "en": "'",
439 | "npShift": "ू",
440 | "np": "ु"
441 | }
442 | ],
443 | "zxcvb": [
444 |
445 | {
446 | "code": "90",
447 | "en": "z",
448 | "npShift": "क्क",
449 | "np": "श"
450 | },
451 | {
452 | "code": "88",
453 | "en": "x",
454 | "npShift": "ह्य",
455 | "np": "ह"
456 | },
457 | {
458 | "code": "67",
459 | "en": "c",
460 | "npShift": "ऋ",
461 | "np": "अ"
462 | },
463 | {
464 | "code": "86",
465 | "en": "v",
466 | "npShift": "ॐ",
467 | "np": "ख"
468 | },
469 | {
470 | "code": "66",
471 | "en": "b",
472 | "npShift": "ौ",
473 | "np": "द"
474 | },
475 | {
476 | "code": "78",
477 | "en": "n",
478 | "npShift": "द्य",
479 | "np": "ल"
480 | },
481 | {
482 | "code": "77",
483 | "en": "m",
484 | "npShift": "ड्ड",
485 | "np": "ः"
486 | },
487 | {
488 | "code": "188",
489 | "en": ",",
490 | "npShift": "ङ",
491 | "np": "ऽ"
492 | },
493 | {
494 | "code": "190",
495 | "en": ".",
496 | "npShift": "श्र",
497 | "np": "।"
498 | },
499 | {
500 | "code": "191",
501 | "en": "/",
502 | "npShift": "रु",
503 | "np": "र"
504 | }
505 | ],
506 | "1234": [
507 | {
508 | "code": "192",
509 | "en": "\`",
510 | "enShift": "\~",
511 | "npShift": "\॥",
512 | "np": "ञ`"
513 | }, {
514 | "code": "49",
515 | "en": "1",
516 | "enShift": "!",
517 | "npShift": "ज्ञ",
518 | "np": "१"
519 | }, {
520 | "code": "50",
521 | "en": "2",
522 | "enShift": "@",
523 | "npShift": "ई",
524 | "np": "२"
525 | }, {
526 | "code": "51",
527 | "en": "3",
528 | "enShift": "#",
529 | "npShift": "घ",
530 | "np": "३"
531 | }, {
532 | "code": "52",
533 | "en": "4",
534 | "enShift": "$",
535 | "npShift": "द्ध",
536 | "np": "४"
537 | }, {
538 | "code": "53",
539 | "en": "5",
540 | "enShift": "%",
541 | "npShift": "छ",
542 | "np": "५"
543 | }, {
544 | "code": "54",
545 | "en": "6",
546 | "enShift": "^",
547 | "npShift": "ट",
548 | "np": "६"
549 | }, {
550 | "code": "55",
551 | "en": "7",
552 | "enShift": "&",
553 | "npShift": "ठ",
554 | "np": "७"
555 | }, {
556 | "code": "56",
557 | "en": "8",
558 | "enShift": "*",
559 | "npShift": "ड",
560 | "np": "८"
561 | }, {
562 | "code": "59",
563 | "en": "9",
564 | "enShift": "(",
565 | "npShift": "ढ",
566 | "np": "९"
567 | }, {
568 | "code": "48",
569 | "en": "0",
570 | "enShift": ")",
571 | "npShift": "ण",
572 | "np": "०"
573 | }, {
574 | "code": "189",
575 | "en": "-",
576 | "enShift": "_",
577 | "npShift": "ओ",
578 | "np": "औ"
579 | }, {
580 | "code": "187",
581 | "en": "=",
582 | "enShift": "+",
583 | "npShift": "",
584 | "np": ""
585 | }
586 | ]
587 |
588 |
589 | }
590 | return keyboard;
591 | });
592 |
--------------------------------------------------------------------------------