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>
Aquí hay un ejemplo de un servicio AngularJS para atajos de teclado: http://jsfiddle.net/firehist/nzUBg/
Puede ser usado así:
function MyController($scope, $timeout, keyboardManager) {
// Bind ctrl+shift+d
keyboardManager.bind(''ctrl+shift+d'', function() {
console.log(''Callback ctrl+shift+d'');
});
}
Actualización: ahora estoy usando http://chieffancypants.github.io/angular-hotkeys/ lugar.
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>
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.
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>
La solución requiere que incluya mousetrap.js, que es una biblioteca que lo ayuda a definir teclas rápidas.
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.
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
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>
puedes probar esta biblioteca, facilitó la administración de teclas de acceso rápido, ata y desenlaza automáticamente las teclas mientras navegas por la aplicación
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