angular-on-screen-keyboard-directive.js 7.28 KB
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;
                    }

                    var htmlKeyVal = angular.element(event.target || event.srcElement).text();
                    var lastInputCtrl = angular.element(ctrl.lastInputCtrl);
                    var val = lastInputCtrl.val();
                    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();
                    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;
                    }
                };

                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'
        };
    }]);