angular.module('onScreenKeyboard', ['ngSanitize']) .directive('onScreenKeyboard', ['$timeout', '$document', function($timeout, $document) { return { restrict: 'E', bindToController: true, controllerAs: 'ctrl', scope: { rows : '=?', uppercaseAllWords : '@', alfanumeric : '=?', numeric : '=?' }, controller: ['$sce', '$scope', function($sce, $scope) { var ctrl = this; if (!ctrl.rows) { ctrl.rows = [ ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', { type: 'erase', colspan: 2, text: '⇐' }], ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '@'], ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', '-', '_', {type: 'margin'}], [ {type: 'shift', upperCase: '⇓', lowerCase: '⇑'}, 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', {type: 'shift', upperCase: '⇓', lowerCase: '⇑'} ], [{type: 'margin'}, {type: 'space', colspan: 9, text: ' '}] ]; } ctrl.getText = function(key) { if (key.type === 'margin') { return ''; } var val = ''; if (key.text) { val = key.text; } else if (key.lowerCase && !ctrl.isUpperCase) { val = key.lowerCase; } else if (key.upperCase && ctrl.isUpperCase) { val = key.upperCase; } else { val = ctrl.isUpperCase ? key.toUpperCase() : key.toLowerCase(); } if (val && val.indexOf('&') > -1) { return $sce.trustAsHtml(val); } return val; }; $scope.fondo = function() { $timeout(function() { ctrl.lastInputCtrl.focus(); $scope.$emit('focus'); }); }; }], link: function(scope, element, attr) { var ctrl = scope.ctrl; ctrl.isUpperCase = false; ctrl.lastInputCtrl = null; ctrl.startPos = null; ctrl.endPos = null; ctrl.printKeyStroke = function(key, event) { if (!ctrl.lastInputCtrl) { return; } ctrl.startPos = ctrl.lastInputCtrl.selectionStart; ctrl.endPos = ctrl.lastInputCtrl.selectionEnd; if (key.type === 'erase') { ctrl.eraseKeyStroke(); return; } else if (key.type === 'shift') { ctrl.isUpperCase = !ctrl.isUpperCase; return; } else if (key.type === 'enter') { ctrl.pressEnterKey(); return; } var htmlKeyVal = angular.element(event.target || event.srcElement).text(); var lastInputCtrl = angular.element(ctrl.lastInputCtrl); var val = lastInputCtrl.val(); if(lastInputCtrl[0].type === 'number') { var dato = parseInt(val + htmlKeyVal); lastInputCtrl.val(dato); lastInputCtrl.triggerHandler('change'); ctrl.setKeyboardLayout(); ctrl.refocus(); return; } var pre = val.substring(0, ctrl.startPos); var post = val.substring(ctrl.endPos, val.length); lastInputCtrl.val(pre + htmlKeyVal + post); lastInputCtrl.triggerHandler('change'); ctrl.startPos += htmlKeyVal.length; ctrl.endPos += htmlKeyVal.length; ctrl.lastInputCtrl.selectionStart = ctrl.startPos; ctrl.lastInputCtrl.selectionEnd = ctrl.startPos; ctrl.setKeyboardLayout(); ctrl.refocus(); }; ctrl.refocus = function() { ctrl.lastInputCtrl.focus(); }; ctrl.eraseKeyStroke = function() { if (!ctrl.lastInputCtrl) { return; } var hasSel = ctrl.startPos !== ctrl.endPos; var lastInputCtrl = angular.element(ctrl.lastInputCtrl); var val = lastInputCtrl.val(); if(lastInputCtrl[0].type === 'number') { lastInputCtrl.val(val.slice(0, -1)); lastInputCtrl.triggerHandler('change'); ctrl.setKeyboardLayout(); ctrl.refocus(); return; } var pre = val.substring(0, hasSel ? ctrl.startPos : ctrl.startPos - 1); var post = val.substring(ctrl.endPos, val.length); lastInputCtrl.val(pre + post); lastInputCtrl.triggerHandler('change'); if (hasSel) { ctrl.endPos = ctrl.startPos; } else { ctrl.startPos--; ctrl.endPos--; } ctrl.lastInputCtrl.selectionStart = ctrl.startPos; ctrl.lastInputCtrl.selectionEnd = ctrl.startPos; ctrl.setKeyboardLayout(); ctrl.refocus(); }; ctrl.setKeyboardLayout = function() { if (!ctrl.lastInputCtrl) { ctrl.isUpperCase = true; return; } else if (ctrl.lastInputCtrl.className && ctrl.isUpperCase) { ctrl.isUpperCase = true; } else if (angular.element(ctrl.lastInputCtrl).val().length === 0) { ctrl.isUpperCase = true; } else if ( angular.element(ctrl.lastInputCtrl).val().slice(-1) === ' ' && !ctrl.isUpperCase && attr.uppercaseAllWords !== undefined ) { ctrl.isUpperCase = true; } else{ ctrl.isUpperCase = true; } }; ctrl.pressEnterKey = function() { $timeout(function() { if (angular.element(':focus').length > 0) { var el = angular.element(':focus')[0], down = new KeyboardEvent('keydown', { which: 13, keyCode: 13, bubbles: true, cancelable: true, }), press = new KeyboardEvent('keypress', { which: 13, keyCode: 13, bubbles: true, cancelable: true, }), up = new KeyboardEvent('keyup', { which: 13, keyCode: 13, bubbles: true, cancelable: true, }); el.dispatchEvent(down); el.dispatchEvent(press); el.dispatchEvent(up); } }); }; var focusin = function(event) { var e = event.target || event.srcElement; if (e.tagName === 'INPUT' || e.tagName === 'TEXTAREA') { ctrl.lastInputCtrl = e; ctrl.setKeyboardLayout(); } }; var keyup = function() { if (!ctrl.lastInputCtrl) { return; } ctrl.startPos = ctrl.lastInputCtrl.selectionStart; ctrl.endPos = ctrl.lastInputCtrl.selectionEnd; ctrl.setKeyboardLayout(); scope.$digest(); }; $document.bind('focusin', focusin); $document.bind('keyup', keyup); scope.$on('$destroy', function() { $document.unbind('focusin', focusin); $document.unbind('keyup', keyup); }); element.bind('contextmenu', function(event) { event.preventDefault(); return false; }); $timeout(function() { ctrl.isUpperCase = true; }, 0); }, templateUrl: 'src/views/angular-on-screen-keyboard.html' }; }]);