yvanui.shortcut.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. var startDomListener = false;
  2. var shortcut = {
  3. echo: function (shortcust) {
  4. var r = this.parse(shortcust);
  5. if ($.type(r) === 'object') {
  6. return r.echo;
  7. }
  8. },
  9. processButton: function ($dom, item, context) {
  10. //处理按钮
  11. if ($.type(item.shortcut) === 'string') {
  12. var bind = shortcut.parse(item.shortcut);
  13. if ($.type(bind) === 'object') {
  14. var echo = bind.echo;
  15. echo = "<u style='font-size: smaller;'>(" + echo + ")</u>";
  16. item.text = item.text + echo;
  17. bind.handler = function () {
  18. $dom.trigger('click');
  19. };
  20. //在容器中注册快捷键
  21. context.shortcutContainer.bind.push(bind);
  22. }
  23. }
  24. if ($.type(item.ff) === 'number') {
  25. setTimeout(function () {
  26. var $ff = $dom;
  27. if ($ff.length > 0) {
  28. $ff.focus();
  29. }
  30. }, item.ff);
  31. }
  32. },
  33. processGrid: function ($dg, item, context) {
  34. //处理表格
  35. if ($.type(item.ff) === 'number') {
  36. setTimeout(function () {
  37. $dom.closest('.datagrid-view').focus();
  38. }, item.ff);
  39. }
  40. var $dom = $dg.closest('.datagrid-view');
  41. //允许所有 datagrid 有焦点
  42. $dom.attr('tabIndex', 10);
  43. //不允许 pagination 有焦点
  44. var pagination = $dg.datagrid('getPager');
  45. pagination.attr('tabIndex', -1);
  46. pagination.find('a').attr('tabIndex', -1);
  47. pagination.find('select').attr('tabIndex', -1);
  48. pagination.find('input').attr('tabIndex', -1);
  49. },
  50. processEgridEditor: function ($dg, index, row) {
  51. //处理 egrid.columns 里面每一个 editor
  52. var editors = $dg.datagrid('getEditors', index);
  53. for (var i = 0; i < editors.length; i++) {
  54. if ($.inArray(editors[i].type, ['textbox', 'numberbox', 'numberspinner', 'combobox', 'combotree', 'combogrid', 'datebox', 'datetimebox', 'searchbox']) >= 0) {
  55. var $editor = editors[i].target;
  56. $editor.textbox('textbox').keydown(function (e) {
  57. var success = shortcut.processKey(e);
  58. if (success) {
  59. if (e.preventDefault) {
  60. e.preventDefault();
  61. } else {
  62. e.returnValue = false;
  63. }
  64. }
  65. });
  66. }
  67. }
  68. },
  69. processInputAfter: function ($dom, item, context) {
  70. //$dom.textbox('textbox').attr('tabIndex', 10);
  71. },
  72. processInput: function ($dom, item, context) {
  73. //处理输入框
  74. var handler = function ($dom) {
  75. var $ff = $dom.next('span').find('.validatebox-text');
  76. if ($ff.length > 0) {
  77. $ff.focus();
  78. }
  79. };
  80. $dom.attr('tabIndex', 10);
  81. if ($.type(item.shortcut) === 'string') {
  82. var bind = this.parse(item.shortcut);
  83. if ($.type(bind) === 'object') {
  84. var echo = bind.echo.replace('Alt+', '');
  85. echo = "<u style='font-size: smaller;'>" + echo + "</u>";
  86. item.label = item.label + echo;
  87. bind.handler = function () {
  88. handler($dom);
  89. };
  90. //在容器中注册快捷键
  91. context.shortcutContainer.bind.push(bind);
  92. }
  93. }
  94. if ($.type(item.ff) === 'number') {
  95. setTimeout(function () {
  96. handler($dom);
  97. }, item.ff);
  98. }
  99. },
  100. ffApply:function($container) {
  101. var vv = $container.find('[ff]:first')
  102. var xtype = vv.attr('xtype')
  103. if(xtype === 'textbox' || xtype==='searchbox' || xtype==='numberbox'){
  104. vv.next().children('input:first').focus();
  105. }
  106. },
  107. disableLayroTabIndex: function (layero) {
  108. //禁用 layer 中的tabIndex辅助按钮
  109. layero.find('.layui-layer-setwin>a').attr('tabIndex', -1);
  110. },
  111. registe: function ($dom, shortcut, handler) {
  112. if (!$dom.is('.shortcutContainer')) {
  113. $dom = $dom.closest('.shortcutContainer');
  114. }
  115. if ($dom.length <= 0) {
  116. return false;
  117. }
  118. $.data($dom[0], 'shortcut').bind.push(
  119. $.extend(this.parse(shortcut), {
  120. handler: handler
  121. })
  122. );
  123. },
  124. parse: function (shortcust, hasEcho) {
  125. shortcust = shortcust.toLowerCase();
  126. var bind = {};
  127. bind.key = shortcust.replace('+', '').replace(' ', '').replace(',', '').replace('ctrl', '').replace('shift', '').replace('alt', '');
  128. if ($.type(bind.key) !== 'string' || !$.trim(bind.key)) {
  129. console.log("非法的快捷键定义:" + shortcust);
  130. return;
  131. }
  132. var array = ['F1',
  133. 'F2',
  134. 'F3',
  135. 'F4',
  136. 'F5',
  137. 'F6',
  138. 'F7',
  139. 'F8',
  140. 'F9',
  141. 'F10',
  142. 'F11',
  143. 'F12',
  144. 'Escape',
  145. 'Enter',
  146. 'PageDown',
  147. 'PageUp',
  148. 'Home',
  149. 'End',
  150. 'Delete',
  151. 'Insert',
  152. 'ArrowUp',
  153. 'ArrowDown',
  154. 'ArrowLeft',
  155. 'ArrowRight'];
  156. //别名定义
  157. switch (bind.key) {
  158. case 'esc':
  159. bind.key = 'escape';
  160. break;
  161. case 'up':
  162. bind.key = 'ArrowUp';
  163. break;
  164. case 'down':
  165. bind.key = 'ArrowDown';
  166. break;
  167. case 'left':
  168. bind.key = 'ArrowLeft';
  169. break;
  170. case 'right':
  171. bind.key = 'ArrowRight';
  172. break;
  173. }
  174. var find = $.inArray(bind.key, array.map(function (v) {
  175. return v.toLowerCase()
  176. }));
  177. if (bind.key.length !== 1 && find < 0) {
  178. console.log("非法的快捷键定义:" + shortcust);
  179. return;
  180. }
  181. bind.ctrl = shortcust.indexOf("ctrl") >= 0;
  182. bind.shift = shortcust.indexOf("shift") >= 0;
  183. bind.alt = shortcust.indexOf("alt") >= 0;
  184. if (find < 0) {
  185. bind.key = bind.key.toUpperCase();
  186. if (!bind.ctrl && !bind.shift && !bind.alt) {
  187. bind.alt = true;
  188. }
  189. } else {
  190. bind.key = array[find];
  191. }
  192. if (hasEcho !== false) {
  193. bind.echo = (bind.ctrl ? "Ctrl+" : "") +
  194. (bind.alt ? "Alt+" : "") +
  195. (bind.shift ? "Shift+" : "") +
  196. bind.key;
  197. }
  198. bind.key = bind.key.toUpperCase();
  199. return bind;
  200. },
  201. createContainer: function ($dom, context) {
  202. if (context.hasOwnProperty('shortcutContainer')) {
  203. //已经包含 shortcutContainer 的设定
  204. return;
  205. }
  206. $dom.addClass('shortcutContainer');
  207. var shortcutContainer = {bind: []};
  208. $.data($dom[0], 'shortcut', shortcutContainer);
  209. context.shortcutContainer = shortcutContainer;
  210. },
  211. processKey: function (e) {
  212. //传入keydown事件参数,如果处理成功 返回true,否则返回false
  213. var log = function () {
  214. var arg = ['shortcut'];
  215. for (var i = 0; i < arguments.length; i++) {
  216. arg.push(arguments[i]);
  217. }
  218. console.log.apply(this, arg);
  219. };
  220. var hooks = {
  221. datagrid: function ($f, e) {
  222. var dff = function (xtype) {
  223. if (e.code === 'PageDown') {
  224. if ($f.down(xtype).datagrid('getPager').length <= 0) return false;
  225. log(xtype, 'PageDown');
  226. var $next = $.data($f.down(xtype).datagrid('getPager')[0]).pagination.bb.next;
  227. if (!$next.is('.l-btn-disabled')) {
  228. $next.trigger('click');
  229. }
  230. return true;
  231. } else if (e.code === 'PageUp') {
  232. if ($f.down(xtype).datagrid('getPager').length <= 0) return false;
  233. log(xtype, 'PageUp');
  234. var $prev = $.data($f.down(xtype).datagrid('getPager')[0]).pagination.bb.prev;
  235. if (!$prev.is('.l-btn-disabled')) {
  236. $prev.trigger('click');
  237. }
  238. return true;
  239. } else if (e.code === 'ArrowUp') {
  240. log(xtype, 'ArrowUp');
  241. var $dg = $f.down(xtype);
  242. var row = $dg.datagrid('getSelected');
  243. if (!row) return true;
  244. var index = $dg.datagrid('getRowIndex', row);
  245. if (index <= 0) return true;
  246. $dg.datagrid('selectRow', index - 1);
  247. return true;
  248. } else if (e.code === 'ArrowDown') {
  249. log(xtype, 'ArrowDown');
  250. var $dg = $f.down(xtype);
  251. var row = $dg.datagrid('getSelected');
  252. if (xtype === 'egrid') {
  253. //egrid 没有任何数据时按"下"键,需要添加操作,并聚焦到第一个编辑框
  254. var rowsLength = $dg.datagrid('getRows').length;
  255. if (rowsLength <= 0) {
  256. $dg.edatagrid('addRow');
  257. setTimeout(function () {
  258. $dg.edatagrid('focusEditor');
  259. }, 50);
  260. return true;
  261. }
  262. }
  263. if (!row) return true;
  264. var index = $dg.datagrid('getRowIndex', row);
  265. if (xtype === 'egrid') {
  266. //egrid 最后一行按"下"键,需要添加操作,并聚焦到第一个编辑框
  267. if (index >= rowsLength - 1) {
  268. //最后一行
  269. $dg.edatagrid('addRow');
  270. setTimeout(function () {
  271. $dg.edatagrid('focusEditor');
  272. }, 50);
  273. return true;
  274. }
  275. }
  276. if (index < 0) return true;
  277. $dg.datagrid('selectRow', index + 1);
  278. return true;
  279. } else if (e.code === 'Escape') {
  280. if (xtype === 'egrid') {
  281. log(xtype, 'Escape');
  282. var $dg = $f.down(xtype);
  283. var editRowIndex = $dg.edatagrid('getEditRowIndex');
  284. if ($.type(editRowIndex) === 'number' && editRowIndex >= 0) {
  285. $dg.edatagrid('cancelRow');
  286. }
  287. }
  288. }
  289. };
  290. if ($f.down('list').length > 0) {
  291. return dff('list');
  292. } else if ($f.down('grid').length > 0) {
  293. return dff('grid');
  294. } else if ($f.down('egrid').length > 0) {
  295. return dff('egrid');
  296. }
  297. return false;
  298. }
  299. };
  300. if (e.key === 'Control' || e.key === 'Shift' || e.key === 'Alt') {
  301. return false;
  302. }
  303. if (e.ctrlKey && e.shiftKey && e.altKey && e.key.toLocaleLowerCase() === 'a') {
  304. console.log($("[tabindex]"));
  305. return true;
  306. }
  307. if (e.ctrlKey && e.shiftKey && e.altKey && e.key.toLocaleLowerCase() === 'c') {
  308. console.log($(document.activeElement));
  309. return true;
  310. }
  311. var $f = $(document.activeElement);
  312. if ($f.is('div.datagrid-view')) {
  313. //当前是在 grid 体系的容器里
  314. if (hooks.datagrid($f, e)) {
  315. return true;
  316. }
  317. } else if ($f.closest('div.datagrid-view').down('egrid').length > 0) {
  318. //当前是在 egrid 表格容器的grid里
  319. if (hooks.datagrid($f.closest('div.datagrid-view'), e)) {
  320. return true;
  321. }
  322. }
  323. //找到当前焦点控件的快捷键容器
  324. var shortcutContainer = $f;
  325. if (!$f.is('.shortcutContainer')) {
  326. shortcutContainer = $f.closest('.shortcutContainer');
  327. }
  328. if (shortcutContainer.length <= 0) {
  329. return false;
  330. }
  331. shortcutContainer = $.data(shortcutContainer[0], 'shortcut');
  332. //寻找容器中有没有注册当前的按键
  333. for (var i = 0; i < shortcutContainer.bind.length; i++) {
  334. var bind = shortcutContainer.bind[i];
  335. if ((bind.alt === e.altKey) &&
  336. (bind.ctrl === e.ctrlKey) &&
  337. (bind.shift === e.shiftKey) &&
  338. (bind.key === e.key.toUpperCase())) {
  339. bind.handler();
  340. }
  341. }
  342. return false;
  343. }
  344. };
  345. $(function () {
  346. var setupGridTabIndex = function (data) {
  347. var $dg = $(this);
  348. var $dom = $dg.closest('.datagrid-view');
  349. //允许所有 datagrid 有焦点
  350. $dom.attr('tabIndex', 10);
  351. //不允许 pagination 有焦点
  352. var pagination = $dg.datagrid('getPager');
  353. pagination.attr('tabIndex', -1);
  354. pagination.find('a').attr('tabIndex', -1);
  355. pagination.find('select').attr('tabIndex', -1);
  356. pagination.find('input').attr('tabIndex', -1);
  357. //默认选中第一行
  358. if (data && data.rows.length > 0) {
  359. $dg.datagrid('selectRow', 0);
  360. }
  361. };
  362. if ($.fn.edatagrid) {
  363. $.fn.edatagrid.defaults.onLoadSuccess = setupGridTabIndex;
  364. }
  365. if ($.fn.datagrid) {
  366. $.fn.datagrid.defaults.onLoadSuccess = setupGridTabIndex;
  367. }
  368. document.onkeydown = function (e) {
  369. var success = shortcut.processKey(e);
  370. if (success) {
  371. if (e.preventDefault) {
  372. e.preventDefault();
  373. } else {
  374. e.returnValue = false;
  375. }
  376. }
  377. };
  378. });