teclas teclado para metodos funciones crear combinaciones comandos cambiar atajos atajo abreviados javascript angularjs

javascript - teclado - metodos abreviados de word



¿Cuál es la forma de AngularJS de crear atajos de teclado globales? (12)

Supongo que debería usar la directiva, pero parece extraño agregar directivas al cuerpo, pero escuchar eventos en el documento.

¿Cuál es la forma correcta de hacer esto?

ACTUALIZACIÓN: Encontré AngularJS UI y vi their realización de la directiva de pulsación de tecla.


A continuación, le permite escribir toda su lógica de acceso directo en su controlador y la directiva se ocupará de todo lo demás.

Directiva

.directive(''shortcuts'', [''$document'', ''$rootScope'', function($document, $rootScope) { $rootScope.shortcuts = []; $document.on(''keydown'', function(e) { // Skip if it focused in input tag. if (event.target.tagName !== "INPUT") { $rootScope.shortcuts.forEach(function(eventHandler) { // Skip if it focused in input tag. if (event.target.tagName !== ''INPUT'' && eventHandler) eventHandler(e.originalEvent, e) }); } }) return { restrict: ''A'', scope: { ''shortcuts'': ''&'' }, link: function(scope, element, attrs) { $rootScope.shortcuts.push(scope.shortcuts()); } }; }])

Controlador

$scope.keyUp = function(key) { // H. if (72 == key.keyCode) $scope.toggleHelp(); };

Html

<div shortcuts="keyUp"> <!-- Stuff --> </div>



Así es como he hecho esto con jQuery: creo que hay una mejor manera.

var app = angular.module(''angularjs-starter'', []); app.directive(''shortcut'', function() { return { restrict: ''E'', replace: true, scope: true, link: function postLink(scope, iElement, iAttrs){ jQuery(document).on(''keypress'', function(e){ scope.$apply(scope.keyPressed(e)); }); } }; }); app.controller(''MainCtrl'', function($scope) { $scope.name = ''World''; $scope.keyCode = ""; $scope.keyPressed = function(e) { $scope.keyCode = e.which; }; });

<body ng-controller="MainCtrl"> <shortcut></shortcut> <h1>View keys pressed</h1> {{keyCode}} </body>

Demo de Plunker


Diría que una manera más apropiada (o "manera angular") sería agregarlo a una directiva. Aquí hay uno simple para que empieces (solo agrega el atributo keypress-events a <body> ):

angular.module(''myDirectives'', []).directive(''keypressEvents'', [ ''$document'', ''$rootScope'', function($document, $rootScope) { return { restrict: ''A'', link: function() { $document.bind(''keypress'', function(e) { console.log(''Got keypress:'', e.which); $rootScope.$broadcast(''keypress'', e); $rootScope.$broadcast(''keypress:'' + e.which, e); }); } }; } ]);

En su directiva, simplemente puede hacer algo como esto:

module.directive(''myDirective'', [ function() { return { restrict: ''E'', link: function(scope, el, attrs) { scope.keyPressed = ''no press :(''; // For listening to a keypress event with a specific code scope.$on(''keypress:13'', function(onEvent, keypressEvent) { scope.keyPressed = ''Enter''; }); // For listening to all keypress events scope.$on(''keypress'', function(onEvent, keypressEvent) { if (keypress.which === 120) { scope.keyPressed = ''x''; } else { scope.keyPressed = ''Keycode: '' + keypressEvent.which; } }); }, template: ''<h1>{{keyPressed}}</h1>'' }; } ]);


Hice un servicio para atajos.

Parece que:

angular.module(''myApp.services.shortcuts'', []) .factory(''Shortcuts'', function($rootScope) { var service = {}; service.trigger = function(keycode, items, element) { // write the shortcuts logic here... } return service; })

Y lo inyecté en un controlador:

angular.module(''myApp.controllers.mainCtrl'', []) .controller(''mainCtrl'', function($scope, $element, $document, Shortcuts) { // whatever blah blah $document.on(''keydown'', function(){ // skip if it focused in input tag if(event.target.tagName !== "INPUT") { Shortcuts.trigger(event.which, $scope.items, $element); } }) })

Funciona, pero es posible que notes que inyecto $ element y $ document en el controlador.

Es una mala práctica de control y viola la convención ''No accedas NUNCA al elemento $ en el controlador''.

Debería ponerlo en la directiva, luego usar ''nGKeydown'' y $ event para activar el servicio.

Pero creo que el servicio está bien y voy a volver a trabajar el controlador antes.

actualizado:

Parece que ''ng-keydown'' solo funciona en etiquetas de entrada.

Así que solo escribo una directiva e inyecto $ document:

angular.module(''myApp.controllers.mainCtrl'', []) .directive(''keyboard'', function($scope, $document, Shortcuts) { // whatever blah blah return { link: function(scope, element, attrs) { scope.items = ....;// something not important $document.on(''keydown'', function(){ // skip if it focused in input tag if(event.target.tagName !== "INPUT") { Shortcuts.trigger(event.which, scope.items, element); } }) } } })

Es mejor.


La respuesta un poco más corta es solo mirar la solución 3 a continuación. Si desea conocer más opciones, puede leer todo.

Estoy de acuerdo con jmagnusson. Pero creo que hay una solución más limpia. En lugar de enlazar las teclas con funciones en directiva, debería poder unirlas en html como definir un archivo de configuración, y las teclas de acceso directo deberían ser contextuales.

  1. A continuación se muestra una versión que usa mouse trap con una directiva personalizada. (Yo no era el autor de este violín).

    var app = angular.module(''keyExample'', []); app.directive(''keybinding'', function () { return { restrict: ''E'', scope: { invoke: ''&'' }, link: function (scope, el, attr) { Mousetrap.bind(attr.on, scope.invoke); } }; }); app.controller(''RootController'', function ($scope) { $scope.gotoInbox = function () { alert(''Goto Inbox''); }; }); app.controller(''ChildController'', function ($scope) { $scope.gotoLabel = function (label) { alert(''Goto Label: '' + label); }; });

    Necesitarás incluir mousetrap.js y lo usarás a continuación:

    <div ng-app="keyExample"> <div ng-controller="RootController"> <keybinding on="g i" invoke="gotoInbox()" /> <div ng-controller="ChildController"> <keybinding on="g l" invoke="gotoLabel(''Sent'')" /> </div> </div> <div>Click in here to gain focus and then try the following key strokes</div> <ul> <li>"g i" to show a "Goto Inbox" alert</li> <li>"g l" to show a "Goto Label" alert</li> </ul> </div>

    http://jsfiddle.net/BM2gG/3/

    La solución requiere que incluya mousetrap.js, que es una biblioteca que lo ayuda a definir teclas rápidas.

  2. Si desea evitar el problema de desarrollar su propia directiva personalizada, puede consultar esta lib:

    https://github.com/drahak/angular-hotkeys

    Y esto

    https://github.com/chieffancypants/angular-hotkeys

    El segundo proporciona un poco más de funciones y flexibilidad, es decir, hoja de trucos de clave activa generada automáticamente para su aplicación.

Actualización : la solución 3 ya no está disponible en la interfaz de usuario angular.

  1. Además de las soluciones anteriores, hay otra implementación realizada por el equipo angularui. Pero la desventaja es que la solución depende de JQuery lib, que no es la tendencia en la comunidad angular. (La comunidad angular intenta usar el jqLite que viene con angularjs y alejarse de las dependencias sobrecapacitadas). Aquí está el enlace

    http://angular-ui.github.io/ui-utils/#/keypress

El uso es así:

En su html, use el atributo ui-keydown para vincular la clave y las funciones.

<div class="modal-inner" ui-keydown="{ esc: ''cancelModal()'', tab: ''tabWatch($event)'', enter: ''initOrSetModel()'' }">

En su directiva, agregue esas funciones en su alcance.

app.directive(''yourDirective'', function () { return { restrict: ''E'', templateUrl: ''your-html-template-address.html'' link: function(){ scope.cancelModal() = function (){ console.log(''cancel modal''); }; scope.tabWatch() = function (){ console.log(''tabWatch''); }; scope.initOrSetModel() = function (){ console.log(''init or set model''); }; } }; });

Después de jugar con todas las soluciones, recomendaría la que está implementada por el equipo Angular UI, solución 3 que evitó muchos pequeños problemas extraños que he encontrado.


Mira este example de los chicos behid ng-newsletter.com; revise su tutorial sobre cómo crear un juego 2048, tiene un buen código usando un servicio para eventos de teclado.


Todavía no puedo responder, pero he empezado a echar un vistazo a AngularHotkeys.js:

http://chieffancypants.github.io/angular-hotkeys/

Se actualizará con más información una vez que tenga mis dientes.

Actualización 1: Oh, hay un paquete nuget: teclas angulares

Actualización 2: realmente muy fácil de usar, solo configure su encuadernación en su ruta o como lo estoy haciendo, en su controlador:

hotkeys.add(''n'', ''Create a new Category'', $scope.showCreateView); hotkeys.add(''e'', ''Edit the selected Category'', $scope.showEditView); hotkeys.add(''d'', ''Delete the selected Category'', $scope.remove);


Use $document.bind :

function FooCtrl($scope, $document) { ... $document.bind("keypress", function(event) { console.debug(event) }); ... }


no sé si es una forma realmente angular, pero lo que he hecho

$(document).on(''keydown'', function(e) { $(''.button[data-key='' + String.fromCharCode(e.which) + '']'').click(); }); <div class="button" data-key="1" ng-click="clickHandler($event)"> ButtonLabel </div>



Como una directiva

Esto es esencialmente cómo se hace en el código de documentación angular, es decir, presionar / para iniciar la búsqueda.

angular .module("app", []) .directive("keyboard", keyboard); function keyboard($document) { return { link: function(scope, element, attrs) { $document.on("keydown", function(event) { // if keycode... event.stopPropagation(); event.preventDefault(); scope.$apply(function() { // update scope... }); } }; }

Plunk usando una directiva de teclado

http://plnkr.co/edit/C61Gnn?p=preview

Como un servicio

Convertir esa directiva en un servicio es realmente fácil. La única diferencia real es que el alcance no está expuesto en el servicio. Para desencadenar un resumen, puede traer $rootScope o usar $timeout .

function Keyboard($document, $timeout, keyCodes) { var _this = this; this.keyHandlers = {}; $document.on("keydown", function(event) { var keyDown = _this.keyHandlers[event.keyCode]; if (keyDown) { event.preventDefault(); $timeout(function() { keyDown.callback(); }); } }); this.on = function(keyName, callback) { var keyCode = keyCodes[keyName]; this.keyHandlers[keyCode] = { callback: callback }; return this; }; }

Ahora puede registrar devoluciones de llamada en su controlador utilizando el método keyboard.on() .

function MainController(keyboard) { keyboard .on("ENTER", function() { // do something... }) .on("DELETE", function() { // do something... }) .on("SHIFT", function() { // do something... }) .on("INSERT", function() { // do something... }); }

Versión alternativa de Plunk usando un servicio

http://plnkr.co/edit/z9edu5?p=preview