Commit f367ed65607e716a5d876429afedfe762a212d00

Authored by Pablo Marco del Pont
Exists in master

Merge branch 'master' into 'master'

Master (pmarco)

See merge request modulos-npm/foca-teclado!2
1 const clean = require('gulp-clean'); 1 const clean = require('gulp-clean');
2 const concat = require('gulp-concat'); 2 const concat = require('gulp-concat');
3 const connect = require('gulp-connect'); 3 const connect = require('gulp-connect');
4 const gulp = require('gulp'); 4 const gulp = require('gulp');
5 const htmlmin = require('gulp-htmlmin'); 5 const htmlmin = require('gulp-htmlmin');
6 const jshint = require('gulp-jshint'); 6 const jshint = require('gulp-jshint');
7 const pump = require('pump'); 7 const pump = require('pump');
8 const rename = require('gulp-rename'); 8 const rename = require('gulp-rename');
9 const replace = require('gulp-replace'); 9 const replace = require('gulp-replace');
10 const templateCache = require('gulp-angular-templatecache'); 10 const templateCache = require('gulp-angular-templatecache');
11 const uglify = require('gulp-uglify-es').default; 11 const uglify = require('gulp-uglify-es').default;
12 const sass = require('gulp-sass'); 12 const sass = require('gulp-sass');
13 13
14 var paths = { 14 var paths = {
15 dist: 'dist/', 15 dist: 'dist/',
16 srcJS: 'src/js/*.js', 16 srcJS: 'src/js/*.js',
17 srcViews: 'src/views/*.html', 17 srcViews: 'src/views/*.html',
18 tmp: 'tmp' 18 tmp: 'tmp'
19 }; 19 };
20 20
21 gulp.task('templates', function() { 21 gulp.task('templates', function() {
22 return pump( 22 return pump(
23 [ 23 [
24 gulp.src(paths.srcViews), 24 gulp.src(paths.srcViews),
25 htmlmin(), 25 htmlmin(),
26 templateCache('views.js', { 26 templateCache('views.js', {
27 module: 'focaTeclado', 27 module: 'focaTeclado',
28 root: '' 28 root: ''
29 }), 29 }),
30 gulp.dest(paths.tmp) 30 gulp.dest(paths.tmp)
31 ] 31 ]
32 ); 32 );
33 }); 33 });
34 34
35 gulp.task('sass', function() { 35 gulp.task('sass', function() {
36 return gulp.src('src/sass/*.scss') 36 return gulp.src('src/sass/*.scss')
37 .pipe(sass({outputStyle: 'compressed'}).on('error', sass.logError)) 37 .pipe(sass({outputStyle: 'compressed'}).on('error', sass.logError))
38 .pipe(gulp.dest('css')); 38 .pipe(gulp.dest('css'));
39 }); 39 });
40 40
41 gulp.task('uglify', ['templates'], function() { 41 gulp.task('uglify', ['templates'], function() {
42 return pump( 42 return pump(
43 [ 43 [
44 gulp.src([ 44 gulp.src([
45 paths.srcJS, 45 paths.srcJS,
46 'tmp/views.js' 46 'tmp/views.js'
47 ]), 47 ]),
48 concat('foca-teclado.js'), 48 concat('foca-teclado.js'),
49 replace('src/views/', ''), 49 replace('src/views/', ''),
50 replace("'ngSanitize', 'onScreenKeyboard'", ''), 50 replace("'ngSanitize', 'onScreenKeyboard'", ''),
51 gulp.dest(paths.tmp), 51 gulp.dest(paths.tmp),
52 rename('foca-teclado.min.js'), 52 rename('foca-teclado.min.js'),
53 uglify(), 53 uglify(),
54 gulp.dest(paths.dist) 54 gulp.dest(paths.dist)
55 ] 55 ]
56 ); 56 );
57 }); 57 });
58 58
59 gulp.task('clean', function() { 59 gulp.task('clean', function() {
60 return gulp.src(['tmp', 'dist'], {read: false}) 60 return gulp.src(['tmp', 'dist'], {read: false})
61 .pipe(clean()); 61 .pipe(clean());
62 }); 62 });
63 63
64 gulp.task('pre-commit', function() { 64 gulp.task('pre-commit', function() {
65 pump( 65 pump(
66 [ 66 [
67 gulp.src(paths.srcJS), 67 gulp.src(paths.srcJS),
68 jshint('.jshintrc'), 68 jshint('.jshintrc'),
69 jshint.reporter('default'), 69 jshint.reporter('default'),
70 jshint.reporter('fail') 70 jshint.reporter('fail')
71 ] 71 ]
72 ); 72 );
73 }); 73 });
74 74
75 gulp.task('webserver', function() { 75 gulp.task('webserver', function() {
76 pump [ 76 pump [
77 connect.server( 77 connect.server(
78 { 78 {
79 port: 3000 79 port: 3000
80 } 80 }
81 ) 81 )
82 ] 82 ]
83 }); 83 });
84 84
85 gulp.task('clean-post-install', function() { 85 gulp.task('clean-post-install', function() {
86 return gulp.src(['src', 'tmp', '.jshintrc','readme.md', '.gitignore', 'gulpfile.js', 86 return gulp.src(['src', 'tmp', '.jshintrc','readme.md', '.gitignore', 'gulpfile.js',
87 'index.html'], {read: false}) 87 'index.html'], {read: false})
88 .pipe(clean()); 88 .pipe(clean());
89 }); 89 });
90 90
91 gulp.task('default', ['webserver']); 91 gulp.task('default', ['webserver']);
92
93 gulp.task('watch', function() {
94 gulp.watch([paths.srcJS, paths.srcViews], ['uglify']);
95 });
92 96
src/js/angular-on-screen-keyboard-directive.js
File was created 1 angular.module('onScreenKeyboard', ['ngSanitize'])
2 .directive('onScreenKeyboard', ['$timeout', '$document', function($timeout, $document) {
3 return {
4 restrict: 'E',
5 bindToController: true,
6 controllerAs: 'ctrl',
7 scope: {
8 rows : '=?',
9 uppercaseAllWords : '@',
10 alfanumeric : '=?',
11 numeric : '=?'
12 },
13 controller: ['$sce', '$scope', function($sce, $scope) {
14 var ctrl = this;
15
16 if (!ctrl.rows) {
17 ctrl.rows = [
18 ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', {
19 type: 'erase', colspan: 2, text: '⇐'
20 }],
21 ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '@'],
22 ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', '-', '_', {type: 'margin'}],
23 [
24 {type: 'shift', upperCase: '⇓', lowerCase: '⇑'},
25 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.',
26 {type: 'shift', upperCase: '⇓', lowerCase: '⇑'}
27 ],
28 [{type: 'margin'}, {type: 'space', colspan: 9, text: ' '}]
29 ];
30 }
31
32 ctrl.getText = function(key) {
33 if (key.type === 'margin') {
34 return '';
35 }
36
37 var val = '';
38
39 if (key.text) {
40 val = key.text;
41 }
42 else if (key.lowerCase && !ctrl.isUpperCase) {
43 val = key.lowerCase;
44 }
45 else if (key.upperCase && ctrl.isUpperCase) {
46 val = key.upperCase;
47 }
48 else {
49 val = ctrl.isUpperCase ? key.toUpperCase() : key.toLowerCase();
50 }
51
52 if (val && val.indexOf('&') > -1) {
53 return $sce.trustAsHtml(val);
54 }
55
56 return val;
57 };
58 $scope.fondo = function() {
59 $timeout(function() {
60 ctrl.lastInputCtrl.focus();
61 $scope.$emit('focus');
62 });
63 };
64 }],
65 link: function(scope, element, attr) {
66 var ctrl = scope.ctrl;
67 ctrl.isUpperCase = false;
68 ctrl.lastInputCtrl = null;
69 ctrl.startPos = null;
70 ctrl.endPos = null;
71
72 ctrl.printKeyStroke = function(key, event) {
73
74 if (!ctrl.lastInputCtrl) {
75 return;
76 }
77
78 ctrl.startPos = ctrl.lastInputCtrl.selectionStart;
79 ctrl.endPos = ctrl.lastInputCtrl.selectionEnd;
80
81 if (key.type === 'erase') {
82 ctrl.eraseKeyStroke();
83 return;
84 } else if (key.type === 'shift') {
85 ctrl.isUpperCase = !ctrl.isUpperCase;
86 return;
87 }
88
89 var htmlKeyVal = angular.element(event.target || event.srcElement).text();
90 var lastInputCtrl = angular.element(ctrl.lastInputCtrl);
91 var val = lastInputCtrl.val();
92 var pre = val.substring(0, ctrl.startPos);
93 var post = val.substring(ctrl.endPos, val.length);
94 lastInputCtrl.val(pre + htmlKeyVal + post);
95 lastInputCtrl.triggerHandler('change');
96
97 ctrl.startPos += htmlKeyVal.length;
98 ctrl.endPos += htmlKeyVal.length;
99 ctrl.lastInputCtrl.selectionStart = ctrl.startPos;
100 ctrl.lastInputCtrl.selectionEnd = ctrl.startPos;
101 ctrl.setKeyboardLayout();
102 ctrl.refocus();
103 };
104
105 ctrl.refocus = function() {
106 ctrl.lastInputCtrl.focus();
107 };
108
109 ctrl.eraseKeyStroke = function() {
110 if (!ctrl.lastInputCtrl) {
111 return;
112 }
113
114 var hasSel = ctrl.startPos !== ctrl.endPos;
115
116 var lastInputCtrl = angular.element(ctrl.lastInputCtrl);
117 var val = lastInputCtrl.val();
118 var pre = val.substring(0, hasSel ? ctrl.startPos : ctrl.startPos - 1);
119 var post = val.substring(ctrl.endPos, val.length);
120
121 lastInputCtrl.val(pre + post);
122 lastInputCtrl.triggerHandler('change');
123
124 if (hasSel) {
125 ctrl.endPos = ctrl.startPos;
126 }
127 else {
128 ctrl.startPos--;
129 ctrl.endPos--;
130 }
131 ctrl.lastInputCtrl.selectionStart = ctrl.startPos;
132 ctrl.lastInputCtrl.selectionEnd = ctrl.startPos;
133 ctrl.setKeyboardLayout();
134 ctrl.refocus();
135 };
136
137 ctrl.setKeyboardLayout = function() {
138 if (!ctrl.lastInputCtrl) {
139 ctrl.isUpperCase = true;
140 return;
141 }
142 else if (ctrl.lastInputCtrl.className && ctrl.isUpperCase) {
143 ctrl.isUpperCase = true;
144 }
145 else if (angular.element(ctrl.lastInputCtrl).val().length === 0) {
146 ctrl.isUpperCase = true;
147 }
148 else if (
149 angular.element(ctrl.lastInputCtrl).val().slice(-1) === ' ' &&
150 !ctrl.isUpperCase && attr.uppercaseAllWords !== undefined
151 ) {
152 ctrl.isUpperCase = true;
153 }
154 else{
155 ctrl.isUpperCase = true;
156 }
157 };
158
159 var focusin = function(event) {
160 var e = event.target || event.srcElement;
161
162 if (e.tagName === 'INPUT' || e.tagName === 'TEXTAREA') {
163 ctrl.lastInputCtrl = e;
164 ctrl.setKeyboardLayout();
165 }
166 };
167
168 var keyup = function() {
169 if (!ctrl.lastInputCtrl) {
170 return;
171 }
172
173 ctrl.startPos = ctrl.lastInputCtrl.selectionStart;
174 ctrl.endPos = ctrl.lastInputCtrl.selectionEnd;
175
176 ctrl.setKeyboardLayout();
177 scope.$digest();
178 };
179
180 $document.bind('focusin', focusin);
181 $document.bind('keyup', keyup);
182
183 scope.$on("$destroy", function() {
184 $document.unbind('focusin', focusin);
185 $document.unbind('keyup', keyup);
186 });
187
188 element.bind('contextmenu', function(event) {
189 event.preventDefault();
190 return false;
191 });
192
193 $timeout(function() {
194 ctrl.isUpperCase = true;
195 }, 0);
196 },
197 templateUrl: 'src/views/angular-on-screen-keyboard.html'
198 };
199 }]);
200
src/views/angular-on-screen-keyboard.html
File was created 1 <div class="keyboard" ng-mousedown="fondo()">
2 <div class="row">
3 <table
4 class="form-group col-12 col-sm-6 col-md-9"
5 ng-show="ctrl.alfanumeric"
6 >
7 <tr ng-repeat="row in ctrl.rows.alfa">
8 <td ng-repeat="key in row"
9 ng-click="ctrl.printKeyStroke(key, $event)"
10 colspan="{{key.colspan || 1}}"
11 ng-class="{
12 'number': key.type === 'number', 'letter': key.type !== 'margin' &&
13 key.type !== 'number'
14 }"
15 ng-bind-html="ctrl.getText(key)"
16 >
17 </td>
18 </tr>
19 </table>
20 <table
21 class="form-group col-12 col-sm-6 col-md-3"
22 ng-show="ctrl.numeric"
23 >
24 <tr ng-repeat="row in ctrl.rows.numeric">
25 <td ng-repeat="key in row"
26 ng-click="ctrl.printKeyStroke(key, $event)"
27 colspan="{{key.colspan || 1}}"
28 ng-class="{
29 'number': key.type === 'number', 'letter': key.type !== 'margin' &&
30 key.type !== 'number'
31 }"
32 ng-bind-html="ctrl.getText(key)"
33 >
34 </td>
35 </tr>
36 </table>
37 </div>
38 </div>
39
src/views/teclado.html
1 <on-screen-keyboard 1 <on-screen-keyboard
2 rows="rows" 2 rows="rows"
3 alfanumeric="$ctrl.alfanumeric" 3 alfanumeric="$ctrl.alfanumeric"
4 numeric="$ctrl.numeric" 4 numeric="$ctrl.numeric"
5 ></on-screen-keyboard> 5 ></on-screen-keyboard>
6 6