Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Użycie klawiatury
Forum PHP.pl > Forum > Po stronie przeglądarki > JavaScript
pp-layouts
Napisałem ostatnio graficzny edytor działający w przeglądarce, w którym działa dość sporo klawiszy. We wszystkich poważniejszych programach graficznych i CAD jest możliwość precyzyjnego przesuwania obiektów za pomocą klawiszy strzałek. W aplikacji którą napisałem precyzyjne skalowanie jest kluczowe i użycie do tego klawiszy to w zasadzie konieczność. Problem w tym, że przeglądarki zachłannie przypisują większość skrótów klawiaturowych nie zostawiając dla aplikacji uruchamianej w przeglądarce zbyt wiele możliwości. Co więcej - każda przeglądarka przypisuje sobie inne skróty (serio). Wszystkie przeglądarki używają do czegoś samych klawiszy strzałek, niektóre dodatkowo przypisują jeszcze te strzałki z shiftem i controlem. Alt jest zarezerwowany, od niepamiętnych czasów alt+strzałki były używane do podstawowej nawigacji.

Mój wybór padł na control, co prawda Opera przypisuje sobie control + strzałki, ale na szczęście to aż tak bardzo nie przeszkadza. (W ogóle w Operze można wszystkie skróty ustawiać w opcjach, ale nie mogę wymagać od użytkownika, żeby przekonfigurowywał swoją przeglądarkę)

Czy istnieje jakiś sposób, żeby wymusić na przeglądarce brak reakcji na swoje skróty klawiaturowe? Jak obsługuję zdarzenie - zostaje prawidłowo odpalone w momencie wciśnięcia klawisza, co więcej - blokuję przekazywanie przez event.preventDefault(). Niestety, przeglądarki nadal odpalają swoją obsługę co praktycznie uniemożliwia wykorzystanie tego skrótu.

Gdyby nie dało się tego zrobić - praktycznie nie da się napisać gry w przeglądarce, chyba że taką, która nie używa klawiszy.

Do rzeczy: ktoś wie jak to zrobić? Da się w ogóle?
raidon
zamiast event.preventDefault() prawdopodobnie wystarczy zwrócić false, przeglądarka powinna zaprzestać jakichkolwiek akcji dalej.
pp-layouts
OK, to finalna, poprawiona wersja wtyczki jQuery obsługującej klawiaturę. W odróżnieniu od poprzedniej nie ma żadnych wymagań poza samym jQuery, automatycznie także dba o to, żeby pola typu input i textarea nie były objęte działaniem tej funkcji, NAWET TE KTÓRE ZOSTANĄ UTWORZONE JUŻ PO JEJ WYWOŁANIU. Do dyspozycji są tradycyjnie zmienne jQuery._SHIFT, jQuery._CTRL i jQuery._ALT. Do wykorzystania na elemencie document, zapewnia globalną obsługę skrótów klawiaturowych.

Można przypisać sobie takie klawisze jak DEL (kod 46), CTRL+SHIFT+strzałki (zaznaczanie tekstu) czy np same strzałki (domyślnie przewijanie strony).

Uwagi:
- żeby przeglądarka nie obsłużyła skrótu domyślnego, funkcja obsługi musi zwrócić false (tylko false, nie 0, nie null, nie undefined)
- funkcja obsługi nie może uruchamiać elementów modalnych takich jak alert() i dialog() - inaczej poprawna obsługa tylko w Operze 10.x

Sprawdzone w poważnej aplikacji (edytorze graficznym).

[JAVASCRIPT] pobierz, plaintext
  1. /**
  2.  * Binds keyboard events, cross-browser compatible, prevents default handlers if listener returned false
  3.  * @param {string} events
  4.  * @param {function} listener
  5.  * @param {object} data
  6.  */
  7. jQuery.prototype.xbind = function(events, listener, data) {
  8. var i, kEvents = ['keydown', 'keypress', 'keyup'], fEvents = events ? events.split(' ') : [], kEvent = true;
  9. var set_EDIT = function() { jQuery._EDIT = true; }, clear_EDIT = function() { jQuery._EDIT = false; };
  10. for (i in fEvents) if (kEvents.indexOf(fEvents[i]) < 0) kEvent = false;
  11. if (kEvent) { // keyboard events
  12. if (typeof(jQuery._SHIFT) == 'undefined') jQuery._SHIFT = false;
  13. if (typeof(jQuery._CTRL) == 'undefined') jQuery._CTRL = false;
  14. if (typeof(jQuery._ALT) == 'undefined') jQuery._ALT = false;
  15. if (typeof(jQuery._PREVENT_DEFAULT) == 'undefined') jQuery._PREVENT_DEFAULT = false;
  16. if (typeof(jQuery._EDIT == 'undefined')) jQuery._EDIT = false;
  17. $(document).bind('DOMNodeInserted', function(event) {
  18. if (['input','textarea'].indexOf(event.target.nodeName.toLowerCase()) >= 0)
  19. $('input,textarea').unbind('focus', set_EDIT).unbind('blur', clear_EDIT).bind('focus', set_EDIT).bind('blur', clear_EDIT);
  20. });
  21. $(document).trigger('DOMNodeInserted');
  22. $(this).bind(kEvents.join(' '), function(theEvent) {
  23. var tag = this.nodeName ? this.nodeName.toLowerCase() : '?';
  24. switch (theEvent.type) {
  25. case 'keydown':
  26. switch (theEvent.which) {
  27. case 16: jQuery._SHIFT = true; break;
  28. case 17: jQuery._CTRL = true; break;
  29. case 18: jQuery._ALT = true; break;
  30. default:
  31. if (!jQuery._EDIT) {
  32. if (fEvents.indexOf('keydown') >= 0 || fEventsOf('keypress') >= 0)
  33. if (listener(theEvent, data) === false) {
  34. theEvent.preventDefault(); // for Chrome
  35. jQuery._PREVENT_DEFAULT = true;
  36. } else {
  37. jQuery._PREVENT_DEFAULT = false;
  38. }
  39. }
  40. }
  41. break;
  42. case 'keypress':
  43. if (jQuery._PREVENT_DEFAULT) {
  44. theEvent.preventDefault(); // for Opera and Firefox
  45. jQuery._PREVENT_DEFAULT = false;
  46. }
  47. break;
  48. case 'keyup':
  49. switch (theEvent.which) {
  50. case 16: jQuery._SHIFT = false; break;
  51. case 17: jQuery._CTRL = false; break;
  52. case 18: jQuery._ALT = false; break;
  53. default:
  54. if (jQuery._PREVENT_DEFAULT) {
  55. theEvent.preventDefault();
  56. jQuery._PREVENT_DEFAULT = false;
  57. }
  58. if (!jQuery._EDIT) {
  59. if (fEvents.indexOf('keyup') >= 0) if (listener(theEvent, data) === false) theEvent.preventDefault();
  60. }
  61. }
  62. }
  63. }, data);
  64. } else { // all other events
  65. $(this).bind(events, listener, data);
  66. }
  67. };
[JAVASCRIPT] pobierz, plaintext


Prosty test:

  1. <!doctype html>
  2. <meta charset="utf-8">
  3. jquery.xbind test
  4. </title>
  5. * { font-family: sans-serif; font-size: 10px; }
  6. </style>
  7. <script src="http://code.jquery.com/jquery-1.4.2.min.js"></script>
  8. <script src="jquery.xbind.js"></script>
  9.  
  10. $(document).ready(function() {
  11.  
  12. var body = document.getElementsByTagName('body').item(0);
  13. var div = document.createElement('div'); div.setAttribute('style', 'height:2048px;border:1px dotted blue');
  14. var input = document.createElement('input'); input.setAttribute('type', 'text');
  15. body.appendChild(input);
  16. body.appendChild(div);
  17.  
  18. $(document).xbind('keydown', function(event) {
  19. if (jQuery._CTRL && event.which == 82) {
  20. div.appendChild(document.createTextNode('CTRL+R'));
  21. div.appendChild(document.createElement('br'));
  22. return false;
  23. }
  24. });
  25.  
  26. });
  27. </script>
  28. </head>
  29. </body>
  30. </html>
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.