| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | **********************************************************************/ | 
					
						
							| 
									
										
										
										
											2016-08-21 02:19:24 +03:00
										 |  |  | ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define) | 
					
						
							|  |  |  | (function(require){ var module={} // make module AMD/node compatible...
 | 
					
						
							| 
									
										
										
										
											2016-08-20 22:49:36 +03:00
										 |  |  | /*********************************************************************/ | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | var actions = require('lib/actions') | 
					
						
							|  |  |  | var features = require('lib/features') | 
					
						
							|  |  |  | var toggler = require('lib/toggler') | 
					
						
							| 
									
										
										
										
											2017-01-12 02:09:59 +03:00
										 |  |  | var keyboard = require('lib/keyboard') | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | var core = require('features/core') | 
					
						
							| 
									
										
										
										
											2016-04-30 18:39:14 +03:00
										 |  |  | var widgets = require('features/ui-widgets') | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-07 04:58:22 +03:00
										 |  |  | var browse = require('lib/widget/browse') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-28 03:57:54 +03:00
										 |  |  | var collections = require('features/collections') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var GLOBAL_KEYBOARD = | 
					
						
							| 
									
										
										
										
											2017-01-20 23:03:09 +03:00
										 |  |  | module.GLOBAL_KEYBOARD = { | 
					
						
							| 
									
										
										
										
											2018-11-13 04:24:07 +03:00
										 |  |  | 	// NOTE: the order of sections is important, it determines in what 
 | 
					
						
							|  |  |  | 	// 		order the keys are handled...
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 	'Global': { | 
					
						
							|  |  |  | 		doc: 'Global bindings that take priority over other sections.', | 
					
						
							|  |  |  | 		pattern: '*', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 	'Slideshow': { | 
					
						
							|  |  |  | 		pattern: '.slideshow-running', | 
					
						
							|  |  |  | 		drop: [ | 
					
						
							| 
									
										
										
										
											2017-11-26 07:56:26 +03:00
										 |  |  | 			'Space', 'Backspace', | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 			'Esc', | 
					
						
							|  |  |  | 			'Up', 'Down', 'Enter', | 
					
						
							|  |  |  | 			'R', 'L', 'G', 'T', | 
					
						
							|  |  |  | 		], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Esc: 'toggleSlideshow: "off" -- Exit slideshow', | 
					
						
							|  |  |  | 		Enter: 'slideshowDialog', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-12 00:50:35 +03:00
										 |  |  | 		// XXX do we need a spearate slideshow paused mode???
 | 
					
						
							|  |  |  | 		Space: 'toggleSlideshowTimer', | 
					
						
							|  |  |  | 		// XXX not sure about these yet...
 | 
					
						
							|  |  |  | 		//Left: 'resetSlideshowTimer',
 | 
					
						
							|  |  |  | 		//Right: 'resetSlideshowTimer',
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		Home: 'resetSlideshowTimer', | 
					
						
							|  |  |  | 		End: 'resetSlideshowTimer', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		T: 'slideshowIntervalDialog', | 
					
						
							| 
									
										
										
										
											2017-01-11 20:03:33 +03:00
										 |  |  | 		R: 'toggleSlideshowDirection -- Reverse slideshow direction', | 
					
						
							|  |  |  | 		L: 'toggleSlideshowLooping -- Toggle slideshow looping', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-11 00:52:39 +03:00
										 |  |  | 	'Preview filter': { | 
					
						
							|  |  |  | 		pattern: '.filter-applied', | 
					
						
							|  |  |  | 		drop: [ | 
					
						
							|  |  |  | 			'Esc', | 
					
						
							|  |  |  | 		], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Esc: 'togglePreviewFilter: "No filters" -- Clear preview filter', | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 	// XXX do we need to prevent up/down navigation here, it may get confusing?
 | 
					
						
							|  |  |  | 	// XXX do we need to disable fast sorting here???
 | 
					
						
							|  |  |  | 	'Single Image': { | 
					
						
							|  |  |  | 		pattern: '.single-image-mode', | 
					
						
							|  |  |  | 		drop: [ | 
					
						
							|  |  |  | 			'Esc', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// do not crop in single image mode...
 | 
					
						
							|  |  |  | 			'C', 'F2', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// zooming...
 | 
					
						
							|  |  |  | 			'#0', '#1', '#2', '#3', '#4', '#5', '#6', '#7', '#8', '#9', | 
					
						
							|  |  |  | 		], | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 00:41:35 +03:00
										 |  |  | 		// handle in next section...
 | 
					
						
							| 
									
										
										
										
											2017-01-12 21:23:16 +03:00
										 |  |  | 		'(': 'NEXT', | 
					
						
							|  |  |  | 		')': 'NEXT', | 
					
						
							| 
									
										
										
										
											2017-05-20 04:39:52 +03:00
										 |  |  | 		'^': 'NEXT', | 
					
						
							|  |  |  | 		'$': 'NEXT', | 
					
						
							| 
									
										
										
										
											2017-12-27 05:34:51 +03:00
										 |  |  | 		// NOTE: we need to handle these explicitly...
 | 
					
						
							|  |  |  | 		alt_C: 'NEXT', | 
					
						
							|  |  |  | 		ctrl_C: 'NEXT', | 
					
						
							| 
									
										
										
										
											2018-12-04 02:27:40 +03:00
										 |  |  | 		'ctrl+#6': 'NEXT', | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// zooming...
 | 
					
						
							|  |  |  | 		'#1': 'fitScreen', | 
					
						
							|  |  |  | 		// XXX should these also be implemented in the same way as 4-9???
 | 
					
						
							|  |  |  | 		'#2': 'fitNormal', | 
					
						
							|  |  |  | 		'alt+#2': 'setNormalScale -- Set current image size as normal', | 
					
						
							|  |  |  | 		'ctrl+shift+#2': 'setNormalScale: null -- Reset normal image size to default', | 
					
						
							|  |  |  | 		'#3': 'fitSmall', | 
					
						
							|  |  |  | 		'alt+#3': 'setSmallScale -- Set current image size as small', | 
					
						
							|  |  |  | 		'ctrl+shift+#3': 'setSmallScale: null -- Reset small image size to default', | 
					
						
							| 
									
										
										
										
											2017-01-09 05:40:24 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// NOTE: these are the same, the only difference is the number...
 | 
					
						
							|  |  |  | 		'#4': 'fitCustom: 4 -- Set cutom image size', | 
					
						
							|  |  |  | 		'alt+#4': 'setCustomSize: 4 -- Set current image size as custom', | 
					
						
							|  |  |  | 		'ctrl+shift+#4': 'setCustomSize: 4 null -- Clear custom image size', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		'#5': 'fitCustom: 5 -- Set cutom image size', | 
					
						
							|  |  |  | 		'alt+#5': 'setCustomSize: 5 -- Set current image size as custom', | 
					
						
							|  |  |  | 		'ctrl+shift+#5': 'setCustomSize: 5 null -- Clear custom image size', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		'#6': 'fitCustom: 6 -- Set cutom image size', | 
					
						
							|  |  |  | 		'alt+#6': 'setCustomSize: 6 -- Set current image size as custom', | 
					
						
							|  |  |  | 		'ctrl+shift+#6': 'setCustomSize: 6 null -- Clear custom image size', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		'#7': 'fitCustom: 7 -- Set cutom image size', | 
					
						
							|  |  |  | 		'alt+#7': 'setCustomSize: 7 -- Set current image size as custom', | 
					
						
							|  |  |  | 		'ctrl+shift+#7': 'setCustomSize: 7 null -- Clear custom image size', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		'#8': 'fitCustom: 8 -- Set cutom image size', | 
					
						
							|  |  |  | 		'alt+#8': 'setCustomSize: 8 -- Set current image size as custom', | 
					
						
							|  |  |  | 		'ctrl+shift+#8': 'setCustomSize: 8 null -- Clear custom image size', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		'#9': 'fitCustom: 9 -- Set cutom image size', | 
					
						
							|  |  |  | 		'alt+#9': 'setCustomSize: 9 -- Set current image size as custom', | 
					
						
							|  |  |  | 		'ctrl+shift+#9': 'setCustomSize: 9 null -- Clear custom image size', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		'#0': 'fitCustom: 0 -- Set cutom image size', | 
					
						
							|  |  |  | 		'alt+#0': 'setCustomSize: 0 -- Set current image size as custom', | 
					
						
							|  |  |  | 		'ctrl+shift+#0': 'setCustomSize: 0 null -- Clear custom image size', | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		Esc: 'toggleSingleImage: "off" -- Exit single image view', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// ignore sorting and reversing...
 | 
					
						
							|  |  |  | 		// XXX not sure about these yet, especially reversing...
 | 
					
						
							| 
									
										
										
										
											2017-01-11 00:41:35 +03:00
										 |  |  | 		shift_R: 'DROP', | 
					
						
							|  |  |  | 		shift_S: 'DROP', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-18 18:00:38 +03:00
										 |  |  | 	'Crop': { | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		pattern: '.crop-mode', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-28 00:50:37 +03:00
										 |  |  | 		drop: [ | 
					
						
							|  |  |  | 			'Esc', | 
					
						
							| 
									
										
										
										
											2017-09-08 22:29:45 +03:00
										 |  |  | 			'Del', | 
					
						
							| 
									
										
										
										
											2017-08-28 00:50:37 +03:00
										 |  |  | 		], | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		Esc: 'uncrop', | 
					
						
							| 
									
										
										
										
											2017-08-28 00:50:37 +03:00
										 |  |  | 		shift_Esc: 'uncropAll', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 06:01:42 +03:00
										 |  |  | 		W: 'testAction2 -- XXX DEBUG: remove when done...', | 
					
						
							| 
									
										
										
										
											2017-09-08 18:52:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-08 22:03:16 +03:00
										 |  |  | 		Del: 'removeFromCrop', | 
					
						
							|  |  |  | 		shift_Del: 'removeMarkedFromCrop', | 
					
						
							| 
									
										
										
										
											2017-12-29 18:33:59 +03:00
										 |  |  | 		ctrl_Del: 'removeRibbonFromCrop', | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-28 00:50:37 +03:00
										 |  |  | 	'Collection': { | 
					
						
							|  |  |  | 		pattern: '.collection-mode', | 
					
						
							| 
									
										
										
										
											2017-09-08 22:29:45 +03:00
										 |  |  | 		drop: [ | 
					
						
							|  |  |  | 			'Esc', | 
					
						
							|  |  |  | 			'Del', | 
					
						
							|  |  |  | 		], | 
					
						
							| 
									
										
										
										
											2017-08-28 00:50:37 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-28 03:57:54 +03:00
										 |  |  | 		Esc: 'loadCollection: "'+ collections.MAIN_COLLECTION_TITLE +'" -- Load all images', | 
					
						
							| 
									
										
										
										
											2017-09-08 18:52:51 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		Del: 'uncollect', | 
					
						
							| 
									
										
										
										
											2017-09-08 22:03:16 +03:00
										 |  |  | 		shift_Del: 'uncollectMarked', | 
					
						
							| 
									
										
										
										
											2017-08-28 00:50:37 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 	'Range': { | 
					
						
							|  |  |  | 		doc: 'Range editing', | 
					
						
							|  |  |  | 		pattern: '.brace', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		// XXX add:
 | 
					
						
							|  |  |  | 		// 		- range navigation
 | 
					
						
							|  |  |  | 		// 		- range manipulation
 | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		Esc: 'clearRange', | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 	// XXX add "save as collection..." (???)
 | 
					
						
							|  |  |  | 	// XXX cleanup...
 | 
					
						
							|  |  |  | 	'Viewer': { | 
					
						
							|  |  |  | 		doc: 'NOTE: binding priority is the same as the order of sections '+ | 
					
						
							|  |  |  | 			'on this page.', | 
					
						
							|  |  |  | 		pattern: '*', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 		F1: 'browseActions: "/Help/" -- Help menu...', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		alt_X: 'close', | 
					
						
							|  |  |  | 		alt_F4: 'close', | 
					
						
							|  |  |  | 		meta_Q: 'close', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		// XXX
 | 
					
						
							| 
									
										
										
										
											2017-01-16 23:27:05 +03:00
										 |  |  | 		F5: 'reload!: "full" -- Reload viewer (full)', | 
					
						
							| 
									
										
										
										
											2017-01-16 18:16:07 +03:00
										 |  |  | 		/*F5: keyboard.doc('Reload viewer (full)',  | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 			function(){  | 
					
						
							|  |  |  | 				//a.stop()
 | 
					
						
							| 
									
										
										
										
											2017-01-16 18:16:07 +03:00
										 |  |  | 				//killAllWorkers()
 | 
					
						
							|  |  |  | 				//	.done(function(){
 | 
					
						
							|  |  |  | 				//		reload() 
 | 
					
						
							|  |  |  | 				//	})
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 				location.reload() | 
					
						
							|  |  |  | 				return false | 
					
						
							|  |  |  | 			}), | 
					
						
							| 
									
										
										
										
											2017-01-16 18:16:07 +03:00
										 |  |  | 		//*/
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		F12: 'showDevTools', | 
					
						
							|  |  |  | 		// NOTE: these are for systems where F** keys are not available 
 | 
					
						
							|  |  |  | 		// 		or do other stuff...
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		meta_alt_I: 'F12', | 
					
						
							|  |  |  | 		ctrl_shift_p: 'F12', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// dialogs...
 | 
					
						
							|  |  |  | 		// XXX should this be all here or in respective sections???
 | 
					
						
							|  |  |  | 		alt_A: 'browseActions', | 
					
						
							| 
									
										
										
										
											2017-04-22 19:21:58 +03:00
										 |  |  | 		alt_F: 'browseActions: "/File/" -- File menu...', | 
					
						
							|  |  |  | 		alt_E: 'browseActions: "/Edit/" -- Edit menu...', | 
					
						
							|  |  |  | 		alt_N: 'browseActions: "/Navigate/" -- Navigate menu...', | 
					
						
							| 
									
										
										
										
											2018-11-08 21:10:58 +03:00
										 |  |  | 		alt_T: 'browseActions: "/Tag/" -- Tag menu...', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 		//alt_S: 'browseActions: "/Sort/" -- Sort menu...',
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// open/save...
 | 
					
						
							|  |  |  | 		O: 'browsePath', | 
					
						
							|  |  |  | 		ctrl_S: 'saveIndexHere', | 
					
						
							|  |  |  | 		ctrl_shift_S: 'exportDialog', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// external editors...
 | 
					
						
							|  |  |  | 		// XXX not sure if this is the right way to go...
 | 
					
						
							|  |  |  | 		E: 'openInExtenalEditor', | 
					
						
							|  |  |  | 		shift_E: 'openInExtenalEditor: 1 -- Open in alternative editor', | 
					
						
							| 
									
										
										
										
											2017-04-22 19:21:58 +03:00
										 |  |  | 		ctrl_E: 'listExtenalEditors', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// history...
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		ctrl_H: 'listURLHistory', | 
					
						
							|  |  |  | 		ctrl_shift_H: 'listSaveHistory', | 
					
						
							| 
									
										
										
										
											2018-11-29 13:27:59 +03:00
										 |  |  | 		'ctrl_#6': 'openPreviousLoadedURL', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		U: 'undo', | 
					
						
							|  |  |  | 		ctrl_Z: 'undo', | 
					
						
							|  |  |  | 		shift_U: 'redo', | 
					
						
							|  |  |  | 		ctrl_shift_Z: 'redo', | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 		alt_H: 'browseActions: "/History/" -- History menu...', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		// tilt...
 | 
					
						
							|  |  |  | 		// XXX experimental, not sure if wee need this with a keyboard...
 | 
					
						
							| 
									
										
										
										
											2018-11-15 19:00:16 +03:00
										 |  |  | 		ctrl_T: 'rotateRibbonCCW -- Tilt ribbons counter clock wise', | 
					
						
							|  |  |  | 		ctrl_shift_T: 'rotateRibbonCW -- Tilt ribbons clock wise', | 
					
						
							|  |  |  | 		ctrl_alt_T: 'resetRibbonRotation -- Reset ribbon tilt', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		// NOTE: this is handled by the wrapper at this point, so we do 
 | 
					
						
							|  |  |  | 		// 		not have to do anything here...
 | 
					
						
							| 
									
										
										
										
											2017-10-06 17:43:02 +03:00
										 |  |  | 		F11: 'toggleFullScreen!',  | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		ctrl_F: 'F11', | 
					
						
							|  |  |  | 		meta_F: 'F11', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		ctrl_R: 'loadNewImages!', | 
					
						
							|  |  |  | 		ctrl_alt_R: 'reload!', | 
					
						
							|  |  |  | 		ctrl_shift_R: 'F5', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		// modes... 
 | 
					
						
							| 
									
										
										
										
											2018-08-31 01:59:01 +03:00
										 |  |  | 		Enter: '@500 toggleSingleImage', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		S: 'slideshowDialog', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// statusbar...
 | 
					
						
							|  |  |  | 		shift_I: 'toggleStatusBar', | 
					
						
							|  |  |  | 		G: 'editStatusBarIndex!', | 
					
						
							|  |  |  | 		shift_G: 'toggleStatusBarIndexMode!', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// theme...
 | 
					
						
							| 
									
										
										
										
											2017-07-27 11:38:05 +03:00
										 |  |  | 		//ctrl_B: 'toggleTheme!',
 | 
					
						
							|  |  |  | 		//ctrl_shift_B: 'toggleTheme!: "prev"',
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		'ctrl+-': 'darkerTheme!', | 
					
						
							|  |  |  | 		'ctrl++': 'lighterTheme!', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// navigation...
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		Left: 'prevImage', | 
					
						
							| 
									
										
										
										
											2017-02-07 18:58:37 +03:00
										 |  |  | 		shift_Space: 'Left', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		Backspace: 'Left', | 
					
						
							|  |  |  | 		Right: 'nextImage', | 
					
						
							|  |  |  | 		Space: 'Right', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		'(': 'prevImageInOrder', | 
					
						
							|  |  |  | 		')': 'nextImageInOrder', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		PgUp: 'prevScreen', | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		ctrl_Left: 'prevScreen', | 
					
						
							|  |  |  | 		// XXX need to prevent default on mac + browser...
 | 
					
						
							|  |  |  | 		meta_Left: 'prevScreen', | 
					
						
							| 
									
										
										
										
											2017-01-09 03:51:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		PgDown: 'nextScreen', | 
					
						
							|  |  |  | 		ctrl_Right: 'nextScreen', | 
					
						
							|  |  |  | 		// XXX need to prevent default on mac + browser...
 | 
					
						
							|  |  |  | 		meta_Right: 'nextScreen', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		Home: 'firstImage', | 
					
						
							|  |  |  | 		ctrl_Home: 'firstGlobalImage', | 
					
						
							|  |  |  | 		shift_Home: 'firstRibbon', | 
					
						
							|  |  |  | 		End: 'lastImage', | 
					
						
							|  |  |  | 		ctrl_End: 'lastGlobalImage', | 
					
						
							|  |  |  | 		shift_End: 'lastRibbon', | 
					
						
							| 
									
										
										
										
											2017-05-20 04:52:10 +03:00
										 |  |  | 		// NOTE: these (vim-like) bindings have been added by request as
 | 
					
						
							|  |  |  | 		// 		it would seem that not all keyboards have a convenient 
 | 
					
						
							|  |  |  | 		// 		Home/End buttons...
 | 
					
						
							|  |  |  | 		'^': 'Home', | 
					
						
							| 
									
										
										
										
											2017-05-20 04:39:52 +03:00
										 |  |  | 		'$': 'End', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		Up: 'prevRibbon', | 
					
						
							| 
									
										
										
										
											2017-04-22 06:20:12 +03:00
										 |  |  | 		caps_shift_Up: 'prevRibbon', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		Down: 'nextRibbon', | 
					
						
							| 
									
										
										
										
											2017-04-22 06:20:12 +03:00
										 |  |  | 		caps_shift_Down: 'nextRibbon', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// shifting...
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		shift_Up: 'shiftImageUp', | 
					
						
							| 
									
										
										
										
											2017-04-22 06:20:12 +03:00
										 |  |  | 		caps_Up: 'shiftImageUp', | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		alt_shift_Up: 'travelImageUp', | 
					
						
							|  |  |  | 		ctrl_shift_Up: 'shiftImageUpNewRibbon', | 
					
						
							| 
									
										
										
										
											2017-03-30 14:07:50 +03:00
										 |  |  | 		ctrl_Up: 'shiftMarkedUp', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		shift_Down: 'shiftImageDown', | 
					
						
							| 
									
										
										
										
											2017-04-22 06:20:12 +03:00
										 |  |  | 		caps_Down: 'shiftImageDown', | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		alt_shift_Down: 'travelImageDown', | 
					
						
							|  |  |  | 		ctrl_shift_Down: 'shiftImageDownNewRibbon', | 
					
						
							| 
									
										
										
										
											2017-03-30 14:07:50 +03:00
										 |  |  | 		ctrl_Down: 'shiftMarkedDown', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		alt_Left: 'shiftImageLeft!', | 
					
						
							|  |  |  | 		alt_Right: 'shiftImageRight!', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-14 16:02:11 +03:00
										 |  |  | 		shift_B: 'setBaseRibbon', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 16:34:13 +03:00
										 |  |  | 		alt_PgUp: 'shiftRibbonUp', | 
					
						
							|  |  |  | 		alt_PgDown: 'shiftRibbonDown', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// editing...
 | 
					
						
							|  |  |  | 		R: 'rotateCW', | 
					
						
							|  |  |  | 		L: 'rotateCCW', | 
					
						
							|  |  |  | 		H: 'flipHorizontal', | 
					
						
							|  |  |  | 		V: 'flipVertical', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// ribbon image stuff...
 | 
					
						
							| 
									
										
										
										
											2017-09-11 16:24:27 +03:00
										 |  |  | 		Menu: 'showContextMenu', | 
					
						
							| 
									
										
										
										
											2018-01-16 02:08:46 +03:00
										 |  |  | 		//alt_I: 'Menu',
 | 
					
						
							|  |  |  | 		alt_I: 'browseActions: "/Image/" -- Image menu...', | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 		alt_R: 'browseActions: "/Ribbon/" -- Ribbon menu...', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// ranges...
 | 
					
						
							|  |  |  | 		// XXX experimental
 | 
					
						
							|  |  |  | 		// XXX add border jumping to Home/End...
 | 
					
						
							|  |  |  | 		'{': 'openRange', | 
					
						
							|  |  |  | 		'}': 'closeRange', | 
					
						
							|  |  |  | 		'*': 'setRangeBorder', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// zooming...
 | 
					
						
							|  |  |  | 		'+': 'zoomIn', | 
					
						
							|  |  |  | 		'=': '+', | 
					
						
							|  |  |  | 		'-': 'zoomOut', | 
					
						
							|  |  |  | 		'_': '-', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		'#0': 'fitMax', | 
					
						
							|  |  |  | 		'#1': 'fitImage', | 
					
						
							|  |  |  | 		'shift+#1': 'fitRibbon', | 
					
						
							|  |  |  | 		'ctrl+#1': 'fitOrig!', | 
					
						
							|  |  |  | 		'#2': 'fitImage: 2 -- Fit 2 Images', | 
					
						
							|  |  |  | 		'#3': 'fitImage: 3 -- Fit 3 images', | 
					
						
							|  |  |  | 		'shift+#3': 'fitRibbon: 3.5 -- Fit 3.5 ribbons', | 
					
						
							|  |  |  | 		'#4': 'fitImage: 4 -- Fit 4 images', | 
					
						
							|  |  |  | 		'#5': 'fitImage: 5 -- Fit 5 images', | 
					
						
							|  |  |  | 		'shift+#5': 'fitRibbon: 5.5 -- Fit 5.5 ribbons', | 
					
						
							|  |  |  | 		'#6': 'fitImage: 6 -- Fit 6 images', | 
					
						
							|  |  |  | 		'#7': 'fitImage: 7 -- Fit 7 images', | 
					
						
							| 
									
										
										
										
											2018-03-12 00:50:35 +03:00
										 |  |  | 		'#8': 'fitImage: 8 -- Fit 8 images', | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		'#9': 'fitImage: 9 -- Fit 9 images', | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		// cropping...
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		F2: 'cropRibbon', | 
					
						
							| 
									
										
										
										
											2017-01-26 21:49:32 +03:00
										 |  |  | 		D: 'cropOutRibbon', | 
					
						
							|  |  |  | 		shift_F2: 'cropOutRibbonsBelow', | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		ctrl_F2: 'cropMarked', | 
					
						
							|  |  |  | 		alt_F2: 'cropBookmarked', | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 		C: 'browseActions: "/Crop/" -- Crop menu...', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-16 14:23:34 +03:00
										 |  |  | 		// collections...
 | 
					
						
							| 
									
										
										
										
											2017-08-17 19:53:39 +03:00
										 |  |  | 		//alt_C: 'browseCollections',
 | 
					
						
							|  |  |  | 		alt_C: 'browseActions: "/Collections/" -- Collections menu...', | 
					
						
							| 
									
										
										
										
											2017-08-23 19:52:17 +03:00
										 |  |  | 		shift_O: 'browseCollections', | 
					
						
							| 
									
										
										
										
											2017-12-23 02:55:54 +03:00
										 |  |  | 		F8: 'collect!', | 
					
						
							| 
									
										
										
										
											2017-09-06 07:20:31 +03:00
										 |  |  | 		shift_F8: 'addMarkedToCollection!', | 
					
						
							| 
									
										
										
										
											2017-08-16 14:23:34 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		// metadata...
 | 
					
						
							|  |  |  | 		I: 'showMetadata', | 
					
						
							| 
									
										
										
										
											2018-03-26 13:27:23 +03:00
										 |  |  | 		//ctrl_shift_I: 'showMetadata: "current" "full" -- Show full metadata',
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-08 21:10:58 +03:00
										 |  |  | 		// XXX
 | 
					
						
							| 
									
										
										
										
											2018-11-15 19:00:16 +03:00
										 |  |  | 		T: 'showTagCloud', | 
					
						
							| 
									
										
										
										
											2018-11-08 21:10:58 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// marking...
 | 
					
						
							|  |  |  | 		M: 'toggleMark', | 
					
						
							| 
									
										
										
										
											2018-03-26 13:27:23 +03:00
										 |  |  | 		ctrl_A: 'markRibbon!', | 
					
						
							|  |  |  | 		ctrl_shift_A: 'markLoaded!', | 
					
						
							|  |  |  | 		ctrl_D: 'unmarkRibbon!', | 
					
						
							|  |  |  | 		ctrl_shift_D: 'unmarkLoaded!', | 
					
						
							|  |  |  | 		ctrl_I: 'toggleMarkRibbon!', | 
					
						
							|  |  |  | 		ctrl_shift_I: 'toggleMarkBlock!', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		',': 'prevMarked', | 
					
						
							|  |  |  | 		'.': 'nextMarked', | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 		alt_M: 'browseActions: "/Mark/" -- Mark menu...', | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		// bookmarking...
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		B: 'toggleBookmark', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		'[': 'prevBookmarked', | 
					
						
							|  |  |  | 		']': 'nextBookmarked', | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 		alt_B: 'browseActions: "/Bookmark/" -- Bookmark menu...', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// copy/paste...
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		// do the default copy thing...
 | 
					
						
							|  |  |  | 		// NOTE: this stops the default: handler from getting the ctrl:
 | 
					
						
							|  |  |  | 		// 		key case...
 | 
					
						
							|  |  |  | 		ctrl_C: '', | 
					
						
							| 
									
										
										
										
											2017-01-11 00:41:35 +03:00
										 |  |  | 		ctrl_V: '', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// sort...
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		//shift_S: 'sortImages: "Date" -- Sort images by date',
 | 
					
						
							|  |  |  | 		shift_S: 'sortImages -- Sort images', | 
					
						
							|  |  |  | 		// XXX need to make this save to base_path if it exists and
 | 
					
						
							|  |  |  | 		// 		ask the user if it does not... now it always asks.
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		shift_R: 'reverseImages', | 
					
						
							|  |  |  | 		alt_S: 'sortDialog', | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-26 18:56:17 +03:00
										 |  |  | 		// filters...
 | 
					
						
							| 
									
										
										
										
											2018-11-11 00:52:39 +03:00
										 |  |  | 		// NOTE: Esc will also clear the filter (see "Preview filter" mode above)...
 | 
					
						
							|  |  |  | 		shift_F: 'browseActions: "/Image/Preview filter/" -- Preview filters...', | 
					
						
							| 
									
										
										
										
											2017-03-26 18:56:17 +03:00
										 |  |  | 		';': 'togglePreviewFilter: "Show shadows" -- Preview shadows', | 
					
						
							| 
									
										
										
										
											2018-03-12 00:50:35 +03:00
										 |  |  | 		':': 'togglePreviewFilter: "Show highlights" -- Preview highlights', | 
					
						
							| 
									
										
										
										
											2018-03-18 01:11:02 +03:00
										 |  |  | 		'caps+:': ':', | 
					
						
							| 
									
										
										
										
											2017-03-26 18:56:17 +03:00
										 |  |  | 		"'": 'togglePreviewFilter: "Black and white" -- Preview black and white', | 
					
						
							| 
									
										
										
										
											2018-11-10 04:01:53 +03:00
										 |  |  | 		'"': 'togglePreviewFilter: "Edge detect" -- Show edges', | 
					
						
							|  |  |  | 		'caps+"': '"', | 
					
						
							| 
									
										
										
										
											2017-03-26 18:56:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		// doc...
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		// XXX for debug...
 | 
					
						
							|  |  |  | 		//ctrl_G: function(){ $('.viewer').toggleClass('visible-gid') },
 | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 		//'?': 'showKeyboardBindings',
 | 
					
						
							|  |  |  | 		'?': 'browseKeyboardBindings', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-13 06:35:11 +03:00
										 |  |  | 		//W: 'testAction -- XXX DEBUG: remove when done...',
 | 
					
						
							|  |  |  | 		W: 'nonAction -- XXX DEBUG: remove when done...', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | /*********************************************************************/ | 
					
						
							| 
									
										
										
										
											2016-04-03 06:30:30 +03:00
										 |  |  | // XXX add loading/storing of kb bindings...
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-25 07:38:38 +03:00
										 |  |  | // XXX need a clean deep copy to restore...
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | var KeyboardActions = actions.Actions({ | 
					
						
							|  |  |  | 	config: { | 
					
						
							| 
									
										
										
										
											2016-12-03 17:28:58 +03:00
										 |  |  | 		// Sets the target element to which the keyboard event handler 
 | 
					
						
							|  |  |  | 		// is bound...
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// Supported values:
 | 
					
						
							|  |  |  | 		// 	'window'			- window element
 | 
					
						
							|  |  |  | 		// 	'document'			- document element
 | 
					
						
							|  |  |  | 		// 	'viewer'			- the viewer (default)
 | 
					
						
							|  |  |  | 		// 	null				- default element
 | 
					
						
							|  |  |  | 		// 	<css selector>		- any css selector
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// NOTE: this value is not live, to update the target restart 
 | 
					
						
							|  |  |  | 		// 		the handler by cycling the toggler off and on...
 | 
					
						
							|  |  |  | 		// NOTE: the target element must be focusable...
 | 
					
						
							|  |  |  | 		'keyboard-event-source': 'window', | 
					
						
							| 
									
										
										
										
											2017-01-12 21:23:16 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-13 06:35:11 +03:00
										 |  |  | 		// limit key repeat to one per N milliseconds.
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// Set this to -1 or null to run keys without any limitations.
 | 
					
						
							| 
									
										
										
										
											2017-04-20 03:46:35 +03:00
										 |  |  | 		'keyboard-max-key-repeat-rate': 0, | 
					
						
							| 
									
										
										
										
											2017-01-13 06:35:11 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// The amount of keyboard "quiet" time to wait for when
 | 
					
						
							|  |  |  | 		// .pauseKeyboardRepeat(..) is called...
 | 
					
						
							|  |  |  | 		'keyboard-repeat-pause-check': 100, | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 	get keybindings(){ | 
					
						
							| 
									
										
										
										
											2017-01-03 02:55:25 +03:00
										 |  |  | 		return this.__keyboard_config }, | 
					
						
							| 
									
										
										
										
											2017-01-11 00:41:35 +03:00
										 |  |  | 	get keyboard(){ | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | 		var that = this | 
					
						
							|  |  |  | 		// XXX should this be here on in start event???
 | 
					
						
							|  |  |  | 		var kb = this.__keyboard_object =  | 
					
						
							|  |  |  | 			this.__keyboard_object  | 
					
						
							|  |  |  | 				|| keyboard.KeyboardWithCSSModes( | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 					function(data){  | 
					
						
							|  |  |  | 						if(data){ | 
					
						
							|  |  |  | 							that.__keyboard_config = data | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							return that.__keyboard_config | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}, | 
					
						
							| 
									
										
										
										
											2017-05-16 00:26:37 +03:00
										 |  |  | 					function(){ return that.dom }) | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | 		return kb }, | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-31 01:59:01 +03:00
										 |  |  | 	// Add debounce support to keyboard handling... 
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2018-08-31 17:11:35 +03:00
										 |  |  | 	// Syntax:
 | 
					
						
							|  |  |  | 	// 	@0.5s actionName: arg arg -- doc...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Supported units:	
 | 
					
						
							|  |  |  | 	// 	ms (default)	- Milliseconds
 | 
					
						
							|  |  |  | 	// 	s				- Seconds 
 | 
					
						
							|  |  |  | 	// 	m 				- Minutes
 | 
					
						
							|  |  |  | 	// 	hz				- Hertz
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2018-08-31 01:59:01 +03:00
										 |  |  | 	// NOTE: these are not actions to make the call as light as possible...
 | 
					
						
							|  |  |  | 	parseStringHandler: function(txt, ...rest){ | 
					
						
							|  |  |  | 		var debounce = 0 | 
					
						
							|  |  |  | 		var scale = { | 
					
						
							|  |  |  | 			ms: 1, | 
					
						
							|  |  |  | 			s: 1000, | 
					
						
							|  |  |  | 			m: 1000 * 60, | 
					
						
							| 
									
										
										
										
											2018-08-31 17:11:35 +03:00
										 |  |  | 			hz: function(v){ return 1000 / v }, | 
					
						
							| 
									
										
										
										
											2018-08-31 01:59:01 +03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		txt = txt.replace(/^\s*@([^\s]*)\s*/, | 
					
						
							|  |  |  | 			function(_, time){ | 
					
						
							|  |  |  | 				var unit = time | 
					
						
							| 
									
										
										
										
											2018-08-31 17:11:35 +03:00
										 |  |  | 					.replace(/(\d+|\d*\.\d+)([^\s]*)/, '$2') | 
					
						
							|  |  |  | 					.toLowerCase() | 
					
						
							| 
									
										
										
										
											2018-09-01 02:20:08 +03:00
										 |  |  | 				unit = unit == '' ? 'ms' : unit | 
					
						
							| 
									
										
										
										
											2018-08-31 17:11:35 +03:00
										 |  |  | 				debounce = scale[unit] instanceof Function ? | 
					
						
							|  |  |  | 					scale[unit](parseFloat(time)) | 
					
						
							|  |  |  | 					: parseFloat(time) * scale[unit] | 
					
						
							| 
									
										
										
										
											2018-08-31 01:59:01 +03:00
										 |  |  | 				return ''  | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return debounce > 0 ? | 
					
						
							|  |  |  | 			Object.assign( | 
					
						
							|  |  |  | 				this.parseStringAction(txt, ...rest),  | 
					
						
							|  |  |  | 				{debounce: debounce}) | 
					
						
							|  |  |  | 			: this.parseStringAction(txt, ...rest) | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	callKeyboardHandler: function(data, context){ | 
					
						
							|  |  |  | 		context = context || this | 
					
						
							|  |  |  | 		var meth = data.action | 
					
						
							|  |  |  | 			.split('.') | 
					
						
							|  |  |  | 			.reduce(function(res, e){  | 
					
						
							|  |  |  | 				context = res | 
					
						
							|  |  |  | 				return res[e]  | 
					
						
							|  |  |  | 			}, this) | 
					
						
							|  |  |  | 		return data.debounce ? | 
					
						
							|  |  |  | 			// debounce...
 | 
					
						
							| 
									
										
										
										
											2018-09-01 23:45:00 +03:00
										 |  |  | 			this.debounce({ | 
					
						
							|  |  |  | 					timeout: data.debounce,  | 
					
						
							|  |  |  | 					tag: 'tag:'+data.action, | 
					
						
							|  |  |  | 					retrigger: true, | 
					
						
							|  |  |  | 					returns: 'dropped', | 
					
						
							|  |  |  | 				}, | 
					
						
							| 
									
										
										
										
											2018-08-31 01:59:01 +03:00
										 |  |  | 				meth.bind(context), ...data.arguments) | 
					
						
							|  |  |  | 			// direct call...
 | 
					
						
							|  |  |  | 			: meth.call(context, ...data.arguments) }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 22:32:16 +03:00
										 |  |  | 	testKeyboardDoc: ['- Interface/', | 
					
						
							| 
									
										
										
										
											2017-01-26 04:53:17 +03:00
										 |  |  | 		core.doc`Self-test action keyboard configuration.`, | 
					
						
							| 
									
										
										
										
											2017-01-11 22:32:16 +03:00
										 |  |  | 		{self_test: true}, | 
					
						
							|  |  |  | 		function(){ | 
					
						
							|  |  |  | 			var that = this | 
					
						
							|  |  |  | 			var keys = this.keyboard.keys() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var index = {} | 
					
						
							|  |  |  | 			Object.keys(keys).forEach(function(mode){ | 
					
						
							|  |  |  | 				Object.keys(keys[mode]).forEach(function(code){ | 
					
						
							|  |  |  | 					if(code == ''){ | 
					
						
							|  |  |  | 						return | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-20 04:25:22 +03:00
										 |  |  | 					// XXX we should also check if code is a key (i.e. alias)...
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-31 01:59:01 +03:00
										 |  |  | 					var a = that.parseStringHandler(code, that) | 
					
						
							| 
									
										
										
										
											2018-03-20 04:25:22 +03:00
										 |  |  | 					// skip aliases that look like actions (namely ':') and bad actions...
 | 
					
						
							|  |  |  | 					if(a.action == ''){ | 
					
						
							|  |  |  | 						return | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2017-12-09 01:39:06 +03:00
										 |  |  | 					var doc = a.doc  | 
					
						
							|  |  |  | 						|| (that.getDocTitle && that.getDocTitle(a.action))  | 
					
						
							|  |  |  | 						|| null | 
					
						
							| 
									
										
										
										
											2017-01-11 22:32:16 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// check if we have no doc...
 | 
					
						
							|  |  |  | 					if(doc == null || doc == ''){ | 
					
						
							|  |  |  | 						console.warn('Action has no doc: "' | 
					
						
							|  |  |  | 							+ a.action +'" at: "'+ code +'"')  | 
					
						
							| 
									
										
										
										
											2017-12-09 01:39:06 +03:00
										 |  |  | 						// XXX ???
 | 
					
						
							|  |  |  | 						return | 
					
						
							| 
									
										
										
										
											2017-01-11 22:32:16 +03:00
										 |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// see if two actions have the same doc...
 | 
					
						
							| 
									
										
										
										
											2017-01-11 22:34:57 +03:00
										 |  |  | 					//
 | 
					
						
							|  |  |  | 					// This problem can be fixed by:
 | 
					
						
							|  |  |  | 					// 	- setting a different doc in .keybindings...
 | 
					
						
							|  |  |  | 					// 	- updating action doc...
 | 
					
						
							| 
									
										
										
										
											2017-01-11 22:32:16 +03:00
										 |  |  | 					if(index[doc] && index[doc] != a.action){ | 
					
						
							| 
									
										
										
										
											2017-01-11 22:34:57 +03:00
										 |  |  | 						console.warn('Actions have same doc/title: "'  | 
					
						
							| 
									
										
										
										
											2017-01-11 22:32:16 +03:00
										 |  |  | 							+ index[doc] +'" and "'+ a.action | 
					
						
							|  |  |  | 							+'" at: "'+ code +'"') | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					index[doc] = a.action | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-13 06:35:11 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Key bindings ---------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 	// XXX need a clean deep copy to restore...
 | 
					
						
							|  |  |  | 	resetKeyBindings: ['Interface/Restore default key bindings', | 
					
						
							| 
									
										
										
										
											2017-01-26 04:53:17 +03:00
										 |  |  | 		core.doc`Restore default keyboard bindings`, | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 		function(){  | 
					
						
							|  |  |  | 			thiis.__keyboard_config = GLOBAL_KEYBOARD }], | 
					
						
							|  |  |  | 	keyHandler: ['- Interface/Get or set key handler', | 
					
						
							| 
									
										
										
										
											2017-01-25 07:38:38 +03:00
										 |  |  | 		// XXX this is essentially a copy of the docs for keyboard.handler(..), 
 | 
					
						
							|  |  |  | 		// 		find a way to reuse...
 | 
					
						
							|  |  |  | 		core.doc`Get/set/unset handler for key...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		In general if handler is not passed this will get the handlers, | 
					
						
							|  |  |  | 		if a handler is given this will set the handler, if the passed  | 
					
						
							|  |  |  | 		handler is either null or '' then it will be unbound. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Get handler for key in all modes... | 
					
						
							|  |  |  | 			.keyHandler(<key>) | 
					
						
							|  |  |  | 			.keyHandler('*', <key>) | 
					
						
							|  |  |  | 				-> <info>  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Get handlers for key in applicable modes... | 
					
						
							|  |  |  | 			.keyHandler('?', <key>) | 
					
						
							|  |  |  | 			.keyHandler('test', <key>) | 
					
						
							|  |  |  | 				-> <info>  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Get handler for key in a specific mode... | 
					
						
							|  |  |  | 			.keyHandler(<mode>, <key>) | 
					
						
							|  |  |  | 				-> <info>  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Get handler for key in a specific list of modes... | 
					
						
							|  |  |  | 			.keyHandler([ <mode>, .. ], <key>) | 
					
						
							|  |  |  | 				-> <info>  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Bind handler to key in specific mode... | 
					
						
							|  |  |  | 			.keyHandler(mode, key, handler) | 
					
						
							|  |  |  | 				-> this | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			Bind handler to key in all modes... | 
					
						
							|  |  |  | 			.keyHandler('*', key, handler) | 
					
						
							|  |  |  | 				-> this | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			Bind handler to key in applicable modes... | 
					
						
							|  |  |  | 			.keyHandler('?', key, handler) | 
					
						
							|  |  |  | 			.keyHandler('test', key, handler) | 
					
						
							|  |  |  | 				-> this | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			Bind handler to key in a specific list of modes... | 
					
						
							|  |  |  | 			.keyHandler([mode, ..], key, handler) | 
					
						
							|  |  |  | 				-> this  | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			Unbind handler from key in specific mode... | 
					
						
							|  |  |  | 			.keyHandler(mode, key, null) | 
					
						
							|  |  |  | 			.keyHandler(mode, key, '') | 
					
						
							|  |  |  | 				-> this | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			Unbind handler from key in all modes... | 
					
						
							|  |  |  | 			.keyHandler('*', key, null) | 
					
						
							|  |  |  | 			.keyHandler('*', key, '') | 
					
						
							|  |  |  | 				-> this | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			Unbind handler from key in applicable modes... | 
					
						
							|  |  |  | 			.keyHandler('?', key, null) | 
					
						
							|  |  |  | 			.keyHandler('?', key, '') | 
					
						
							|  |  |  | 			.keyHandler('test', key, null) | 
					
						
							|  |  |  | 			.keyHandler('test', key, '') | 
					
						
							|  |  |  | 				-> this | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			Unbind handler from key in a specific list of modes... | 
					
						
							|  |  |  | 			.keyHandler([mode, ..], key, null) | 
					
						
							|  |  |  | 			.keyHandler([mode, ..], key, '') | 
					
						
							|  |  |  | 				-> this  | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		<info> format: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				<mode>: <handler>, | 
					
						
							|  |  |  | 				... | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		NOTE: this is essentially aproxy to .keyboard.handler(..) for  | 
					
						
							|  |  |  | 				more info see its docs. | 
					
						
							|  |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 		function(mode, key, action){  | 
					
						
							| 
									
										
										
										
											2017-01-11 22:32:16 +03:00
										 |  |  | 			var res = this.keyboard.handler(mode, key, action)  | 
					
						
							|  |  |  | 			// return res only if we get a handler...
 | 
					
						
							|  |  |  | 			if(!action){ | 
					
						
							|  |  |  | 				return res | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}], | 
					
						
							| 
									
										
										
										
											2017-09-09 00:32:26 +03:00
										 |  |  | 	// XXX NEXT/DROP handling needs more testing...
 | 
					
						
							|  |  |  | 	// XXX should dropped key handling be done here or in .keyboard.keys()??? 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 	getKeysForAction: ['- Interface/', | 
					
						
							| 
									
										
										
										
											2017-01-18 00:56:08 +03:00
										 |  |  | 		core.doc`Get normalized, flat set of actions and keys that trigger them...
 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		Format: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				<action>: [ | 
					
						
							|  |  |  | 					<key>, | 
					
						
							|  |  |  | 					... | 
					
						
							|  |  |  | 				], | 
					
						
							|  |  |  | 				... | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		NOTE: this does not check overloading between modes i.e. if two | 
					
						
							|  |  |  | 			actions in two different modes are bound to the same key  | 
					
						
							|  |  |  | 			only one is shown... | 
					
						
							|  |  |  | 			XXX is this a bug??? | 
					
						
							|  |  |  | 				...at this point can't find when this produces inconsistencies... | 
					
						
							|  |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 		function(actions, modes){ | 
					
						
							|  |  |  | 			var that = this | 
					
						
							|  |  |  | 			var res = {} | 
					
						
							| 
									
										
										
										
											2017-09-09 00:32:26 +03:00
										 |  |  | 			var kb = this.keyboard | 
					
						
							|  |  |  | 			var keybindings = this.keybindings | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// Normalize handler to one of the following forms:
 | 
					
						
							|  |  |  | 			// 	- "<action>"
 | 
					
						
							|  |  |  | 			// 	- "<action>: <arg> ..."
 | 
					
						
							|  |  |  | 			//
 | 
					
						
							|  |  |  | 			// We intentionally the following because they are not 
 | 
					
						
							|  |  |  | 			// relevant to the actual action function:
 | 
					
						
							|  |  |  | 			// 	- .doc
 | 
					
						
							|  |  |  | 			// 	- .no_default
 | 
					
						
							|  |  |  | 			// 	- .stop_propagation
 | 
					
						
							|  |  |  | 			var normalizeHandler = function(action){ | 
					
						
							| 
									
										
										
										
											2018-08-31 01:59:01 +03:00
										 |  |  | 				var a = that.parseStringHandler(action.doc || action, that) | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 				return a.action in that ? | 
					
						
							|  |  |  | 					a.action  | 
					
						
							|  |  |  | 						+(a.arguments.length > 0 ?  | 
					
						
							|  |  |  | 							(': '+ a.arguments.map(JSON.stringify)) | 
					
						
							|  |  |  | 							: '') | 
					
						
							|  |  |  | 					: null  | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			actions = actions || '*' | 
					
						
							|  |  |  | 			actions = (actions != '*' && actions instanceof Array) ? | 
					
						
							|  |  |  | 				actions  | 
					
						
							|  |  |  | 				: [actions] | 
					
						
							|  |  |  | 			actions = actions != '*' ?  | 
					
						
							|  |  |  | 				// normalize the inputs...
 | 
					
						
							|  |  |  | 				actions.map(normalizeHandler)  | 
					
						
							|  |  |  | 				: actions | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-09 00:32:26 +03:00
										 |  |  | 			modes = modes || kb.modes() | 
					
						
							|  |  |  | 			modes = modes == '*' ? Object.keys(keybindings) | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 				: modes instanceof Array ? modes  | 
					
						
							|  |  |  | 				: [modes] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-09 00:32:26 +03:00
										 |  |  | 			var keys = kb.keys('?') | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// build the result -- flatten the key list...
 | 
					
						
							|  |  |  | 			modes.forEach(function(mode){ | 
					
						
							| 
									
										
										
										
											2017-09-09 00:32:26 +03:00
										 |  |  | 				if(mode in keys){ | 
					
						
							|  |  |  | 					Object.keys(keys[mode]) | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 						// parse the actions...
 | 
					
						
							|  |  |  | 						.forEach(function(action){  | 
					
						
							|  |  |  | 							var t = normalizeHandler(action) | 
					
						
							|  |  |  | 							if(t && (actions == '*' || actions.indexOf(t) >= 0)){ | 
					
						
							|  |  |  | 								res[t] = (res[t] || []).concat(keys[mode][action]) | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						}) | 
					
						
							| 
									
										
										
										
											2017-09-09 00:32:26 +03:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return res | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-13 06:35:11 +03:00
										 |  |  | 	// keyboard handling ----------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2017-01-16 23:27:05 +03:00
										 |  |  | 	keyPress: ['- Interface/Handle key or keyboard event', | 
					
						
							| 
									
										
										
										
											2017-01-18 00:56:08 +03:00
										 |  |  | 		core.doc`Handle key / keyboard event...
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 			Handle key... | 
					
						
							|  |  |  | 			.keyPress(<key>) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			Handle key and call func if key is not bound... | 
					
						
							|  |  |  | 			.keyPress(<key>, <func>) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			Handle key event... | 
					
						
							|  |  |  | 			.keyPress(<event>) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			Handle key and call func if key is not bound... | 
					
						
							|  |  |  | 			.keyPress(<event>, <func>) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		NOTE: care must be taken when using or binding to this (especially  | 
					
						
							|  |  |  | 	 		the .pre stage) as this may introduce a lag into user input. | 
					
						
							|  |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2017-01-17 21:48:31 +03:00
										 |  |  | 		{ keepDialogTitle: true }, | 
					
						
							| 
									
										
										
										
											2017-01-16 23:27:05 +03:00
										 |  |  | 		function(key, no_match){ | 
					
						
							| 
									
										
										
										
											2017-03-08 21:07:29 +03:00
										 |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2017-01-18 18:00:38 +03:00
										 |  |  | 			// get/set the handler...
 | 
					
						
							|  |  |  | 			var handler = this.__key_press_handler =  | 
					
						
							|  |  |  | 				this.__key_press_handler  | 
					
						
							| 
									
										
										
										
											2017-03-08 21:07:29 +03:00
										 |  |  | 					//|| keyboard.makeKeyboardHandler(this.keyboard, null, this)
 | 
					
						
							|  |  |  | 					|| keyboard.makePausableKeyboardHandler( | 
					
						
							|  |  |  | 						this.keyboard,  | 
					
						
							|  |  |  | 						null,  | 
					
						
							|  |  |  | 						this,  | 
					
						
							|  |  |  | 						function(){ return that.config['keyboard-repeat-pause-check'] }) | 
					
						
							| 
									
										
										
										
											2017-01-18 18:00:38 +03:00
										 |  |  | 			// do the call...
 | 
					
						
							|  |  |  | 			return handler(key, no_match) | 
					
						
							| 
									
										
										
										
											2017-01-16 23:27:05 +03:00
										 |  |  | 		}], | 
					
						
							| 
									
										
										
										
											2017-01-05 03:06:06 +03:00
										 |  |  | 	toggleKeyboardHandling: ['- Interface/Keyboard handling', | 
					
						
							| 
									
										
										
										
											2017-01-26 04:53:17 +03:00
										 |  |  | 		core.doc`Toggle keyboard handling on/off`, | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		toggler.Toggler(null, function(_, state){  | 
					
						
							| 
									
										
										
										
											2017-01-12 21:23:16 +03:00
										 |  |  | 			var that = this | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 			if(state == null){ | 
					
						
							|  |  |  | 				return this.__keyboard_handler ? 'on' : 'off' | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | 			var kb = this.keyboard | 
					
						
							| 
									
										
										
										
											2017-01-11 00:41:35 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 			// start/reset keyboard handling...
 | 
					
						
							|  |  |  | 			if(state == 'on'){ | 
					
						
							| 
									
										
										
										
											2016-12-03 17:28:58 +03:00
										 |  |  | 				// NOTE: the target element must be focusable...
 | 
					
						
							|  |  |  | 				var target = | 
					
						
							|  |  |  | 				this.__keyboard_event_source = | 
					
						
							| 
									
										
										
										
											2017-05-16 00:26:37 +03:00
										 |  |  | 					this.config['keyboard-event-source'] == null ? this.dom  | 
					
						
							| 
									
										
										
										
											2017-01-11 22:32:16 +03:00
										 |  |  | 					: this.config['keyboard-event-source'] == 'window' ? $(window) | 
					
						
							| 
									
										
										
										
											2017-05-16 00:26:37 +03:00
										 |  |  | 					: this.config['keyboard-event-source'] == 'viewer' ? this.dom | 
					
						
							| 
									
										
										
										
											2016-12-03 17:28:58 +03:00
										 |  |  | 					: this.config['keyboard-event-source'] == 'document' ? $(document) | 
					
						
							|  |  |  | 					: $(this.config['keyboard-event-source']) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 				// need to reset...
 | 
					
						
							| 
									
										
										
										
											2017-01-12 21:23:16 +03:00
										 |  |  | 				this.__keyboard_handler | 
					
						
							|  |  |  | 					&& target.off('keydown', this.__keyboard_handler) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// make the base handler...
 | 
					
						
							| 
									
										
										
										
											2017-03-08 21:07:29 +03:00
										 |  |  | 				var handler = this.keyPress.bind(this) | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// setup base keyboard for devel, in case something breaks...
 | 
					
						
							|  |  |  | 				// This branch does not drop keys...
 | 
					
						
							| 
									
										
										
										
											2017-04-20 03:46:35 +03:00
										 |  |  | 				if(this.config['keyboard-max-key-repeat-rate'] < 0  | 
					
						
							|  |  |  | 						|| this.config['keyboard-max-key-repeat-rate'] == null){ | 
					
						
							| 
									
										
										
										
											2017-01-12 21:23:16 +03:00
										 |  |  | 					this.__keyboard_handler = handler | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// drop keys if repeating too fast...
 | 
					
						
							|  |  |  | 				// NOTE: this is done for smoother animations...
 | 
					
						
							|  |  |  | 				} else { | 
					
						
							| 
									
										
										
										
											2017-01-12 21:23:16 +03:00
										 |  |  | 					handler =  | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 					this.__keyboard_handler = | 
					
						
							| 
									
										
										
										
											2017-01-12 21:23:16 +03:00
										 |  |  | 						keyboard.dropRepeatingkeys( | 
					
						
							|  |  |  | 							handler, | 
					
						
							|  |  |  | 							function(){  | 
					
						
							| 
									
										
										
										
											2017-04-20 03:46:35 +03:00
										 |  |  | 								return that.config['keyboard-max-key-repeat-rate'] }) | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				target.keydown(handler) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// stop keyboard handling...
 | 
					
						
							|  |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2016-12-03 17:28:58 +03:00
										 |  |  | 				this.__keyboard_event_source | 
					
						
							|  |  |  | 					&& this.__keyboard_event_source | 
					
						
							|  |  |  | 						.off('keydown', this.__keyboard_handler) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 00:41:35 +03:00
										 |  |  | 				//delete this.__keyboard_object
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 				delete this.__keyboard_handler | 
					
						
							| 
									
										
										
										
											2016-12-03 17:28:58 +03:00
										 |  |  | 				delete this.__keyboard_event_source | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-04-03 20:57:03 +03:00
										 |  |  | 		['on', 'off'])], | 
					
						
							| 
									
										
										
										
											2017-01-18 00:56:08 +03:00
										 |  |  | 	pauseKeyboardRepeat: ['- Interface/Drop keys until none are pressed for a timout', | 
					
						
							|  |  |  | 		core.doc`Drop keys until non are pressed for a timeout...
 | 
					
						
							| 
									
										
										
										
											2016-04-03 20:57:03 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-18 00:56:08 +03:00
										 |  |  | 		This is useful for stopping repeating (held down) keys after some | 
					
						
							|  |  |  | 		event.`,
 | 
					
						
							| 
									
										
										
										
											2017-03-08 21:07:29 +03:00
										 |  |  | 		function(){  | 
					
						
							|  |  |  | 			this.config['keyboard-repeat-pause-check'] > 0 | 
					
						
							|  |  |  | 				&& this.keyboard.pauseRepeat | 
					
						
							|  |  |  | 				&& this.keyboard.pauseRepeat() }], | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | }) | 
					
						
							| 
									
										
										
										
											2017-01-13 06:35:11 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | var Keyboard =  | 
					
						
							|  |  |  | module.Keyboard = core.ImageGridFeatures.Feature({ | 
					
						
							|  |  |  | 	title: '', | 
					
						
							|  |  |  | 	doc: '', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tag: 'keyboard', | 
					
						
							|  |  |  | 	depends: [ | 
					
						
							|  |  |  | 		'ui', | 
					
						
							|  |  |  | 	], | 
					
						
							|  |  |  | 	suggested: [ | 
					
						
							|  |  |  | 		'self-test', | 
					
						
							|  |  |  | 		'keyboard-ui', | 
					
						
							|  |  |  | 	], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	actions: KeyboardActions,  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	handlers: [ | 
					
						
							|  |  |  | 		['start', | 
					
						
							|  |  |  | 			function(){ | 
					
						
							|  |  |  | 				var that = this | 
					
						
							|  |  |  | 				this.__keyboard_config = this.keybindings || GLOBAL_KEYBOARD | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-04 04:28:29 +03:00
										 |  |  | 				// string action call parser...
 | 
					
						
							| 
									
										
										
										
											2018-08-31 01:59:01 +03:00
										 |  |  | 				//this.parseStringHandler = this.parseStringAction
 | 
					
						
							|  |  |  | 				//this.parseStringHandler = this.parseStringActionWithDebounce
 | 
					
						
							| 
									
										
										
										
											2017-08-04 04:28:29 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | 				this.toggleKeyboardHandling('on') | 
					
						
							|  |  |  | 			}], | 
					
						
							| 
									
										
										
										
											2017-12-09 01:39:06 +03:00
										 |  |  | 	 | 
					
						
							|  |  |  | 		['stop', | 
					
						
							|  |  |  | 			function(){ | 
					
						
							|  |  |  | 				this.toggleKeyboardHandling('off') }], | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// pause keyboard repeat...
 | 
					
						
							|  |  |  | 		['shiftImageUp.pre shiftImageDown.pre', | 
					
						
							|  |  |  | 			function(){ | 
					
						
							|  |  |  | 				var r = this.current_ribbon | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				return function(){ | 
					
						
							|  |  |  | 					// pause repeat if shifting last image out of the ribbon... 
 | 
					
						
							|  |  |  | 					if(this.data.ribbons[r] == null  | 
					
						
							|  |  |  | 							|| this.data.ribbons[r].len == 0){ | 
					
						
							|  |  |  | 						this.pauseKeyboardRepeat() | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* | 
					
						
							|  |  |  | 		['keyHandler', | 
					
						
							|  |  |  | 			function(res, mode, key, action){ | 
					
						
							|  |  |  | 				action && this.testKeyboardDoc() }], | 
					
						
							|  |  |  | 		//*/
 | 
					
						
							|  |  |  | 	], | 
					
						
							|  |  |  | }) | 
					
						
							| 
									
										
										
										
											2017-01-03 02:55:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-29 07:32:07 +03:00
										 |  |  | // XXX make these usable for any keyboard handler, not just the builtin...
 | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | var KeyboardUIActions = actions.Actions({ | 
					
						
							|  |  |  | 	config: { | 
					
						
							| 
									
										
										
										
											2017-01-25 07:38:38 +03:00
										 |  |  | 		// NOTE: this is defined in ui-dialogs feature...
 | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | 		//'ui-confirm-timeout': 2000,
 | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-09 05:11:29 +03:00
										 |  |  | 	// XXX sub-group by path (???)
 | 
					
						
							| 
									
										
										
										
											2017-01-29 07:32:07 +03:00
										 |  |  | 	// XXX make this usable for other other handlers...
 | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | 	browseKeyboardBindings: ['Help/Keyboard bindings...', | 
					
						
							| 
									
										
										
										
											2017-01-18 00:56:08 +03:00
										 |  |  | 		core.doc`Keyboard bindings viewer...
 | 
					
						
							| 
									
										
										
										
											2017-01-26 04:53:17 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		This adds several keyboard bindings to the dialog: | 
					
						
							|  |  |  | 			?		- show current action doc, if available. | 
					
						
							| 
									
										
										
										
											2017-01-18 00:56:08 +03:00
										 |  |  | 	 | 
					
						
							|  |  |  | 		options format: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				// Classes to add to the dialog...
 | 
					
						
							|  |  |  | 				cls: 'edit', | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 				// If true, show non-actions in the list...
 | 
					
						
							|  |  |  | 				// This would include:
 | 
					
						
							|  |  |  | 				//	- aliases
 | 
					
						
							|  |  |  | 				//	- special handlers (like: DROP, NEXT, ...) 
 | 
					
						
							|  |  |  | 				//	- actions of features not loaded or not available
 | 
					
						
							|  |  |  | 				show_non_actions: false, | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 				// If true will show the placeholder text in sections that 
 | 
					
						
							|  |  |  | 				// contain no mappings...
 | 
					
						
							|  |  |  | 				//
 | 
					
						
							|  |  |  | 				// This can also be a string, which will be shown as empty 
 | 
					
						
							|  |  |  | 				// section text.
 | 
					
						
							|  |  |  | 				empty_section_text: true, | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 				// Function used to get/generate text to represent an action
 | 
					
						
							|  |  |  | 				// in the list.
 | 
					
						
							|  |  |  | 				//
 | 
					
						
							|  |  |  | 				// If not defined or false action doc will be used if 
 | 
					
						
							|  |  |  | 				// available.
 | 
					
						
							|  |  |  | 				get_key_text: <function>, | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 				// Button structures for different sections...
 | 
					
						
							|  |  |  | 				//
 | 
					
						
							|  |  |  | 				// All of these must confirm to the lib/widget/browse buttons
 | 
					
						
							|  |  |  | 				// format:
 | 
					
						
							|  |  |  | 				//	{
 | 
					
						
							|  |  |  | 				//		[<html>: <func>],
 | 
					
						
							|  |  |  | 				//		...
 | 
					
						
							|  |  |  | 				//	}
 | 
					
						
							|  |  |  | 				//
 | 
					
						
							|  |  |  | 				// (see: browse.Browser.update(..) doc for more info)
 | 
					
						
							|  |  |  | 				//
 | 
					
						
							|  |  |  | 				// Mode section title...
 | 
					
						
							|  |  |  | 				mode_buttons: <buttons>, | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 				// Mode actions...
 | 
					
						
							|  |  |  | 				//
 | 
					
						
							|  |  |  | 				// If false or undefined the element will not be shown.
 | 
					
						
							|  |  |  | 				//
 | 
					
						
							|  |  |  | 				// NOTE: these are shown at the end of a section.
 | 
					
						
							|  |  |  | 				mode_actions: <buttons>, | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 				// Key binding buttons...
 | 
					
						
							|  |  |  | 				key_buttons: <buttons>, | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 				// Dropped key list buttons...
 | 
					
						
							|  |  |  | 				drop_buttons: <buttons>, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		NOTE: this is designed to be a viewer by default but provide enough | 
					
						
							|  |  |  | 			configurability to support editing without actually including | 
					
						
							|  |  |  | 			any editing mechanics. | 
					
						
							|  |  |  | 			This should separate the editing mechanics from the actual  | 
					
						
							|  |  |  | 			view layout while at the same time keeping it consistent. | 
					
						
							|  |  |  | 			The main drawback could be that this will complicate the  | 
					
						
							|  |  |  | 			layout development until (if) it stabilizes. | 
					
						
							|  |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 		widgets.makeUIDialog(function(path, options){ | 
					
						
							|  |  |  | 			options = options || {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2017-01-11 05:53:05 +03:00
										 |  |  | 			var kb = this.keyboard | 
					
						
							| 
									
										
										
										
											2017-01-05 03:06:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 			// get doc...
 | 
					
						
							| 
									
										
										
										
											2017-01-18 00:56:08 +03:00
										 |  |  | 			var getKeyText = options.get_key_text === undefined ? | 
					
						
							|  |  |  | 				function(action){ | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 					var doc = action.doc ? action.doc | 
					
						
							|  |  |  | 						: action.action in this ? this.getDocTitle(action.action) | 
					
						
							|  |  |  | 						: action.action  | 
					
						
							|  |  |  | 					return doc.length == 0 ? action.action : doc | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-01-18 00:56:08 +03:00
										 |  |  | 				: options.get_key_text | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-09 15:13:36 +03:00
										 |  |  | 			return browse.makeLister(null,  | 
					
						
							| 
									
										
										
										
											2017-01-05 04:53:46 +03:00
										 |  |  | 				function(path, make){ | 
					
						
							| 
									
										
										
										
											2017-01-18 00:56:08 +03:00
										 |  |  | 					var keys = kb.keys('*') | 
					
						
							| 
									
										
										
										
											2017-01-29 07:32:07 +03:00
										 |  |  | 					var keybindings = kb.keyboard | 
					
						
							| 
									
										
										
										
											2017-01-18 00:56:08 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 					Object.keys(keybindings) | 
					
						
							| 
									
										
										
										
											2017-01-05 04:53:46 +03:00
										 |  |  | 						.forEach(function(mode){ | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 							var dropped = keybindings[mode].drop || [] | 
					
						
							| 
									
										
										
										
											2017-01-06 02:18:21 +03:00
										 |  |  | 							var bound_ignored = [] | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-25 18:17:04 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 							// section heading (mode)...
 | 
					
						
							| 
									
										
										
										
											2017-01-27 08:26:10 +03:00
										 |  |  | 							make.Heading(mode, {  | 
					
						
							|  |  |  | 									doc: keybindings[mode].doc, | 
					
						
							| 
									
										
										
										
											2017-01-25 18:17:04 +03:00
										 |  |  | 									not_filtered_out: true, | 
					
						
							|  |  |  | 									// XXX should sections be searchable???
 | 
					
						
							|  |  |  | 									//not_searchable: true,
 | 
					
						
							|  |  |  | 									buttons: options.mode_buttons, | 
					
						
							|  |  |  | 								}) | 
					
						
							| 
									
										
										
										
											2017-01-27 08:26:10 +03:00
										 |  |  | 								.attr({ mode: mode }) | 
					
						
							| 
									
										
										
										
											2017-01-06 02:18:21 +03:00
										 |  |  | 								.addClass('mode') | 
					
						
							| 
									
										
										
										
											2017-01-05 07:38:56 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 04:53:46 +03:00
										 |  |  | 							// bindings...
 | 
					
						
							| 
									
										
										
										
											2017-01-06 02:18:21 +03:00
										 |  |  | 							var c = 0 | 
					
						
							| 
									
										
										
										
											2017-01-11 00:41:35 +03:00
										 |  |  | 							Object.keys(keys[mode] || {}).forEach(function(action){ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-31 01:59:01 +03:00
										 |  |  | 								var o = that.parseStringHandler(action, that) | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 								if(getKeyText){ | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 									var doc = '' | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 									var text = getKeyText.call(that, o) | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 								} else { | 
					
						
							|  |  |  | 									var doc = o.doc | 
					
						
							| 
									
										
										
										
											2018-08-31 15:19:35 +03:00
										 |  |  | 									var text = (o.debounce ?  | 
					
						
							|  |  |  | 											`@${o.debounce} `  | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 											: '') | 
					
						
							| 
									
										
										
										
											2018-08-31 15:19:35 +03:00
										 |  |  | 										+ o.code.split('--')[0].trim() | 
					
						
							|  |  |  | 										 | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 								} | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 								var hidden = !options.show_non_actions | 
					
						
							|  |  |  | 									// hide all non-actions...
 | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 									&& !(o.action in that | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 										// except: functions represented by their doc...
 | 
					
						
							|  |  |  | 										|| keybindings[mode][action] == null | 
					
						
							|  |  |  | 											&& kb.handler(mode, keys[mode][action][0])  | 
					
						
							|  |  |  | 												instanceof Function) | 
					
						
							| 
									
										
										
										
											2017-01-11 00:41:35 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 								// NOTE: wee need the button spec to be
 | 
					
						
							|  |  |  | 								// 		searchable, thus we are not using 
 | 
					
						
							|  |  |  | 								// 		the keys attr as in .browseActions(..)
 | 
					
						
							| 
									
										
										
										
											2017-01-11 04:45:34 +03:00
										 |  |  | 								make([text, ' ', '$BUTTONS'] | 
					
						
							| 
									
										
										
										
											2017-01-11 00:41:35 +03:00
										 |  |  | 										.concat($('<span>') | 
					
						
							|  |  |  | 											.addClass('text') | 
					
						
							|  |  |  | 											.html(keys[mode][action] | 
					
						
							| 
									
										
										
										
											2017-01-17 20:48:57 +03:00
										 |  |  | 												// mark key if it's dropped...
 | 
					
						
							| 
									
										
										
										
											2017-01-11 00:41:35 +03:00
										 |  |  | 												.map(function(s){  | 
					
						
							| 
									
										
										
										
											2017-01-17 20:48:57 +03:00
										 |  |  | 													if(dropped == '*'){ | 
					
						
							|  |  |  | 														s += '<sup>*</sup>' | 
					
						
							|  |  |  | 													} else { | 
					
						
							|  |  |  | 														s = s.split('+') | 
					
						
							|  |  |  | 														var k = s.pop()  | 
					
						
							|  |  |  | 														var i = dropped.indexOf(k) | 
					
						
							|  |  |  | 														i >= 0  | 
					
						
							|  |  |  | 															&& bound_ignored | 
					
						
							|  |  |  | 																.push(dropped[i]) | 
					
						
							|  |  |  | 														s.push(k + (i >= 0 ?  '<sup>*</sup>' : '')) | 
					
						
							|  |  |  | 														s = s.join('+') | 
					
						
							|  |  |  | 													} | 
					
						
							|  |  |  | 													return s  | 
					
						
							|  |  |  | 												}) | 
					
						
							| 
									
										
										
										
											2017-01-11 05:53:05 +03:00
										 |  |  | 												.join(' / '))), | 
					
						
							|  |  |  | 									{ | 
					
						
							|  |  |  | 										// hide stuff that is not an action...
 | 
					
						
							|  |  |  | 										hidden: hidden,	 | 
					
						
							|  |  |  | 										disabled: hidden,	 | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 										buttons: options.key_buttons, | 
					
						
							| 
									
										
										
										
											2017-01-11 05:53:05 +03:00
										 |  |  | 									}) | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 									.attr({ | 
					
						
							|  |  |  | 										'mode': mode, | 
					
						
							|  |  |  | 										'code': action, | 
					
						
							| 
									
										
										
										
											2017-01-25 22:56:18 +03:00
										 |  |  | 										'action': o.action, | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 										'doc': doc.trim() != '' ?  | 
					
						
							| 
									
										
										
										
											2017-01-11 00:41:35 +03:00
										 |  |  | 											doc  | 
					
						
							| 
									
										
										
										
											2017-01-11 05:53:05 +03:00
										 |  |  | 											: (kb.special_handlers[action]  | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 												|| null), | 
					
						
							| 
									
										
										
										
											2018-08-31 15:19:35 +03:00
										 |  |  | 										'debounce': o.debounce || '', | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 									}) | 
					
						
							| 
									
										
										
										
											2017-01-11 05:16:03 +03:00
										 |  |  | 									.addClass('key' | 
					
						
							|  |  |  | 										// special stuff...
 | 
					
						
							| 
									
										
										
										
											2017-01-11 05:53:05 +03:00
										 |  |  | 										+ (action in kb.special_handlers ? | 
					
						
							| 
									
										
										
										
											2017-01-11 05:16:03 +03:00
										 |  |  | 										   	' special-action'  | 
					
						
							|  |  |  | 											: '') | 
					
						
							|  |  |  | 										// aliases...
 | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 										+ (o.action in that ? '' : ' non-action')) | 
					
						
							| 
									
										
										
										
											2017-01-11 00:41:35 +03:00
										 |  |  | 								c++ | 
					
						
							| 
									
										
										
										
											2017-01-06 02:18:21 +03:00
										 |  |  | 							}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							// no keys in view mode...
 | 
					
						
							|  |  |  | 							// XXX is adding info stuff like this a correct 
 | 
					
						
							|  |  |  | 							// 		thing to do in code?
 | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 							c == 0 && options.empty_section_text !== false | 
					
						
							| 
									
										
										
										
											2017-08-09 15:36:03 +03:00
										 |  |  | 								&& make.Empty(options.empty_section_text || 'No bindings...') | 
					
						
							| 
									
										
										
										
											2017-01-15 04:36:48 +03:00
										 |  |  | 									.attr('mode', mode) | 
					
						
							| 
									
										
										
										
											2017-01-06 02:18:21 +03:00
										 |  |  | 									.addClass('info') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							// unpropagated and unbound keys...
 | 
					
						
							|  |  |  | 							make(['Unpropagated and unbound keys:', | 
					
						
							|  |  |  | 									// NOTE: this blank is so as to avoid
 | 
					
						
							|  |  |  | 									// 		sticking the action and keys 
 | 
					
						
							|  |  |  | 									// 		together in path...
 | 
					
						
							|  |  |  | 									' ', | 
					
						
							|  |  |  | 									'$BUTTONS', | 
					
						
							| 
									
										
										
										
											2017-01-17 20:48:57 +03:00
										 |  |  | 									dropped == '*' ?  | 
					
						
							|  |  |  | 										dropped  | 
					
						
							|  |  |  | 										: dropped | 
					
						
							|  |  |  | 											.filter(function(k){  | 
					
						
							|  |  |  | 												return bound_ignored.indexOf(k) == -1 }) | 
					
						
							|  |  |  | 											.join(' / ')], | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 								{ | 
					
						
							|  |  |  | 									buttons: options.drop_buttons, | 
					
						
							|  |  |  | 								}) | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 								.addClass('drop-list') | 
					
						
							|  |  |  | 								.attr('mode', mode) | 
					
						
							| 
									
										
										
										
											2017-01-05 04:53:46 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 23:00:49 +03:00
										 |  |  | 							// controls...
 | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 							if(options.mode_actions){ | 
					
						
							| 
									
										
										
										
											2017-01-25 06:44:46 +03:00
										 |  |  | 								var elem = make('New:', { | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 										buttons: options.mode_actions, | 
					
						
							|  |  |  | 									}) | 
					
						
							| 
									
										
										
										
											2017-01-15 04:36:48 +03:00
										 |  |  | 									.attr('mode', mode) | 
					
						
							| 
									
										
										
										
											2017-01-05 23:00:49 +03:00
										 |  |  | 									.addClass('new') | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2017-01-05 04:53:46 +03:00
										 |  |  | 						}) | 
					
						
							| 
									
										
										
										
											2017-01-06 02:18:21 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// notes...
 | 
					
						
							|  |  |  | 					// XXX is adding info stuff like this a correct 
 | 
					
						
							|  |  |  | 					// 		thing to do in code?
 | 
					
						
							|  |  |  | 					make('---') | 
					
						
							|  |  |  | 					make($('<span>') | 
					
						
							|  |  |  | 							.addClass('text') | 
					
						
							|  |  |  | 							.html('<sup>*</sup> keys not propogated to next section.'),  | 
					
						
							|  |  |  | 						{  | 
					
						
							|  |  |  | 							disabled: true , | 
					
						
							|  |  |  | 							hide_on_search: true, | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 						.addClass('info') | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 				},  | 
					
						
							|  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2017-01-17 20:48:57 +03:00
										 |  |  | 					path: path, | 
					
						
							| 
									
										
										
										
											2017-01-05 23:00:49 +03:00
										 |  |  | 					cls: [ | 
					
						
							|  |  |  | 						'key-bindings', | 
					
						
							|  |  |  | 						'no-item-numbers', | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 						options.cls, | 
					
						
							| 
									
										
										
										
											2017-01-05 23:00:49 +03:00
										 |  |  | 					].join(' '), | 
					
						
							| 
									
										
										
										
											2017-01-05 04:53:46 +03:00
										 |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2018-03-09 15:13:36 +03:00
										 |  |  | 				// setup extra kb actions...
 | 
					
						
							|  |  |  | 				.run(function(){ | 
					
						
							|  |  |  | 					// clone the bindings so as not to mess up the global browser...
 | 
					
						
							|  |  |  | 					this.keybindings = JSON.parse(JSON.stringify(this.keybindings)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// handle '?' button to browse path...
 | 
					
						
							|  |  |  | 					this.showDoc = function(){ | 
					
						
							|  |  |  | 						var action = this.select('!').attr('action') | 
					
						
							|  |  |  | 						action  | 
					
						
							|  |  |  | 							&& action in that  | 
					
						
							|  |  |  | 							&& that.showDoc(action) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					this.keyboard.handler('General', '?', 'showDoc') | 
					
						
							| 
									
										
										
										
											2017-01-05 04:53:46 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-09 15:13:36 +03:00
										 |  |  | 					// edit keys on 'E' press...
 | 
					
						
							|  |  |  | 					if(that.editKeyboardBindings){ | 
					
						
							|  |  |  | 						this.editKeys = function(){  | 
					
						
							|  |  |  | 							that.editKeyboardBindings()  | 
					
						
							|  |  |  | 							this.close() | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						this.keyboard.handler('General', 'e', 'editKeys') | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 				}) })], | 
					
						
							| 
									
										
										
										
											2017-08-16 05:41:49 +03:00
										 |  |  | 	// XXX this does not handle the passed container protocol...
 | 
					
						
							|  |  |  | 	// 		.editKeyboardBindings('Drawer') is broken...
 | 
					
						
							| 
									
										
										
										
											2017-01-05 23:00:49 +03:00
										 |  |  | 	editKeyboardBindings: ['Interface/Keyboard bindings editor...', | 
					
						
							| 
									
										
										
										
											2017-01-26 04:53:17 +03:00
										 |  |  | 		core.doc`Keyboard bindings editor...
 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		This is similar to .browseKeyboardBindings(..) but adds editing | 
					
						
							|  |  |  | 		functionality... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		This adds several keyboard bindings to the dialog: | 
					
						
							|  |  |  | 			N / K	- add new key binding to current mode. | 
					
						
							|  |  |  | 			M		- add new mode. | 
					
						
							| 
									
										
										
										
											2017-01-18 00:56:08 +03:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2017-01-26 04:53:17 +03:00
										 |  |  | 		NOTE: current mode is the one where focus/selection is, if no  | 
					
						
							|  |  |  | 			item is selected first mode is assumed. | 
					
						
							|  |  |  | 		NOTE: for more details see: .browseKeyboardBindings(..)`,
 | 
					
						
							| 
									
										
										
										
											2017-01-05 23:00:49 +03:00
										 |  |  | 		widgets.uiDialog(function(path){  | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2017-01-25 07:38:38 +03:00
										 |  |  | 			var to_select | 
					
						
							| 
									
										
										
										
											2017-01-15 04:36:48 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			var sortModes = function(list){ | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 				that.keyboard.sortModes( | 
					
						
							|  |  |  | 					list.find('[mode]') | 
					
						
							|  |  |  | 						.map(function(){ return $(this).attr('mode')}) | 
					
						
							|  |  |  | 						.toArray() | 
					
						
							|  |  |  | 						.unique()) | 
					
						
							| 
									
										
										
										
											2017-01-15 04:36:48 +03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 			return this.browseKeyboardBindings( | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 				path,  | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					cls: 'edit', | 
					
						
							|  |  |  | 					show_non_actions: true, | 
					
						
							|  |  |  | 					empty_section_text: false, | 
					
						
							| 
									
										
										
										
											2017-01-18 00:56:08 +03:00
										 |  |  | 					get_key_text: false, | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// mode...
 | 
					
						
							|  |  |  | 					mode_buttons: [ | 
					
						
							| 
									
										
										
										
											2017-01-15 04:36:48 +03:00
										 |  |  | 						// up...
 | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 						['⏶', function(_, cur){ | 
					
						
							| 
									
										
										
										
											2017-01-15 04:36:48 +03:00
										 |  |  | 								var mode = cur.attr('mode') | 
					
						
							|  |  |  | 								var elems = cur.parent().find('[mode="'+mode+'"]') | 
					
						
							|  |  |  | 								var prev = elems.first().prev('[mode]').attr('mode') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 								// move only if we have somewhere to move...
 | 
					
						
							|  |  |  | 								if(prev){ | 
					
						
							|  |  |  | 									cur.parent().find('[mode="'+prev+'"]') | 
					
						
							|  |  |  | 										.first() | 
					
						
							|  |  |  | 										.before(elems) | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 									this.select(elems.first()) | 
					
						
							| 
									
										
										
										
											2017-01-15 04:36:48 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 									// do the actual section ordering...
 | 
					
						
							|  |  |  | 									sortModes(cur.parent()) | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 							}], | 
					
						
							| 
									
										
										
										
											2017-01-15 04:36:48 +03:00
										 |  |  | 						// down...
 | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 						['⏷', function(_, cur){ | 
					
						
							| 
									
										
										
										
											2017-01-15 04:36:48 +03:00
										 |  |  | 								var mode = cur.attr('mode') | 
					
						
							|  |  |  | 								var elems = cur.parent().find('[mode="'+mode+'"]') | 
					
						
							|  |  |  | 								var next = elems.last().next('[mode]').attr('mode') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 								// move only if we have somewhere to move...
 | 
					
						
							|  |  |  | 								if(next){ | 
					
						
							|  |  |  | 									cur.parent().find('[mode="'+next+'"]') | 
					
						
							|  |  |  | 										.last() | 
					
						
							|  |  |  | 										.after(elems) | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 									this.select(elems.first()) | 
					
						
							| 
									
										
										
										
											2017-01-15 04:36:48 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 									// do the actual section ordering...
 | 
					
						
							|  |  |  | 									sortModes(cur.parent()) | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 							}], | 
					
						
							|  |  |  | 					], | 
					
						
							|  |  |  | 					mode_actions: [ | 
					
						
							| 
									
										
										
										
											2017-01-25 06:44:46 +03:00
										 |  |  | 						// XXX focus resulting key...
 | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 						['key', function(_, cur){ | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 							var dialog = this | 
					
						
							| 
									
										
										
										
											2017-01-25 07:38:38 +03:00
										 |  |  | 							that.editKeyBinding( | 
					
						
							|  |  |  | 									cur.attr('mode'),  | 
					
						
							|  |  |  | 									null,  | 
					
						
							|  |  |  | 									function(e){ to_select = e }) | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 								.close(function(){ dialog.update() }) }], | 
					
						
							| 
									
										
										
										
											2017-01-15 04:36:48 +03:00
										 |  |  | 						// XXX place element...
 | 
					
						
							| 
									
										
										
										
											2017-01-25 06:44:46 +03:00
										 |  |  | 						// XXX focus resulting mode...
 | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 						['mode', function(_, cur){ | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 							var dialog = this | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 							// XXX need to pass order info...
 | 
					
						
							| 
									
										
										
										
											2017-01-25 07:38:38 +03:00
										 |  |  | 							that.editKeyboardMode( | 
					
						
							|  |  |  | 									null,  | 
					
						
							|  |  |  | 									function(e){ to_select = e }) | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 								.close(function(){ dialog.update() }) }], | 
					
						
							|  |  |  | 					], | 
					
						
							|  |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 				// XXX should this be only a button thing (done in .browseKeyboardBindings(..))
 | 
					
						
							|  |  |  | 				// 		or also the main action???
 | 
					
						
							|  |  |  | 	   			.open(function(){ | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 					var dialog = this | 
					
						
							|  |  |  | 					var cur = this.select('!') | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 					var sub_dialog | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// key...
 | 
					
						
							|  |  |  | 					if(cur.hasClass('key')){ | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 						sub_dialog = that | 
					
						
							| 
									
										
										
										
											2017-01-25 07:38:38 +03:00
										 |  |  | 							.editKeyBinding( | 
					
						
							|  |  |  | 								cur.attr('mode'),  | 
					
						
							|  |  |  | 								cur.attr('code'), | 
					
						
							|  |  |  | 								function(e){ to_select = e }) | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// mode...
 | 
					
						
							|  |  |  | 					} else if(cur.hasClass('mode')){ | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 						sub_dialog = that | 
					
						
							| 
									
										
										
										
											2017-01-25 07:38:38 +03:00
										 |  |  | 							.editKeyboardMode( | 
					
						
							|  |  |  | 								cur.attr('mode'),  | 
					
						
							|  |  |  | 								null,  | 
					
						
							|  |  |  | 								function(e){ to_select = e }) | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 					// dropped...
 | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 					} else if(cur.hasClass('drop-list')){ | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 						sub_dialog = that | 
					
						
							|  |  |  | 							.editKeyboardModeDroppedKeys(cur.attr('mode')) | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					sub_dialog  | 
					
						
							|  |  |  | 						&& sub_dialog | 
					
						
							| 
									
										
										
										
											2017-01-30 05:37:55 +03:00
										 |  |  | 							.close(function(evt, mode){  | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 								dialog.update() }) | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 				})  | 
					
						
							| 
									
										
										
										
											2017-01-25 07:38:38 +03:00
										 |  |  | 				// select updated/new items...
 | 
					
						
							|  |  |  | 				.on('update', function(){ | 
					
						
							|  |  |  | 					to_select  | 
					
						
							|  |  |  | 						// XXX this does not work for modes...
 | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 						&& this.select(to_select) | 
					
						
							| 
									
										
										
										
											2017-01-25 07:38:38 +03:00
										 |  |  | 					to_select = null | 
					
						
							|  |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 				// setup keyboard...
 | 
					
						
							|  |  |  | 				.run(function(){ | 
					
						
							|  |  |  | 					this.newKey = function(){ | 
					
						
							|  |  |  | 						that.editKeyBinding( | 
					
						
							|  |  |  | 								this.select('!').attr('mode') | 
					
						
							|  |  |  | 									|| Object.keys(kb.keyboard)[0])  | 
					
						
							|  |  |  | 							.close(function(evt, mode){  | 
					
						
							|  |  |  | 								this.update() }.bind(this)) } | 
					
						
							|  |  |  | 					this.newMode = function(){  | 
					
						
							|  |  |  | 						that.editKeyboardMode()  | 
					
						
							|  |  |  | 							.close(function(evt, mode){  | 
					
						
							|  |  |  | 								this.update() }.bind(this)) } | 
					
						
							| 
									
										
										
										
											2017-01-25 22:56:18 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 					this.keyboard | 
					
						
							|  |  |  | 						.handler('General', 'N', 'newKey') | 
					
						
							|  |  |  | 						.handler('General', 'K', 'newKey') | 
					
						
							|  |  |  | 						.handler('General', 'M', 'newMode') | 
					
						
							|  |  |  | 				}) })], | 
					
						
							| 
									
										
										
										
											2017-01-25 18:17:04 +03:00
										 |  |  | 	// XXX add action completion... (???)
 | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 	editKeyBinding: ['- Interface/Key mapping...', | 
					
						
							| 
									
										
										
										
											2017-01-26 04:53:17 +03:00
										 |  |  | 		core.doc`Key mapping editor...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Changes made in the editor are applied only when the dialog is  | 
					
						
							|  |  |  | 		closed, so it is possible to cancel any edit within the dialog | 
					
						
							|  |  |  | 		by either pressing Q or the "Cancel edits" button. | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		This adds several keyboard bindings to the dialog: | 
					
						
							|  |  |  | 			Q		- quit without saving changes. | 
					
						
							|  |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2017-01-25 07:38:38 +03:00
										 |  |  | 		widgets.makeUIDialog(function(mode, code, callback){ | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 			var orig_code = code | 
					
						
							| 
									
										
										
										
											2017-01-17 20:48:57 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// list the keys (cache)...
 | 
					
						
							|  |  |  | 			var keys = that.keyboard.keys(code) | 
					
						
							|  |  |  | 			keys = mode in keys ?  | 
					
						
							|  |  |  | 				(keys[mode][code] || []) | 
					
						
							|  |  |  | 				: []  | 
					
						
							| 
									
										
										
										
											2017-01-18 00:56:08 +03:00
										 |  |  | 			var orig_keys = keys.slice() | 
					
						
							| 
									
										
										
										
											2017-01-17 20:48:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 			return browse.makeLister(null,  | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 				function(path, make){ | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 					var cfg = { | 
					
						
							|  |  |  | 						start_on: 'open', | 
					
						
							|  |  |  | 						edit_text: 'last', | 
					
						
							|  |  |  | 						clear_on_edit: false, | 
					
						
							|  |  |  | 						reset_on_commit: false, | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// XXX make editable???
 | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 					make(['Mode:', mode || '']) | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-22 01:39:46 +03:00
										 |  |  | 					// XXX add completion...
 | 
					
						
							|  |  |  | 					// 		...datalist seems not to work with non input fields...
 | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 					make.Editable(['Code:', code || ''], { | 
					
						
							|  |  |  | 							start_on: 'open', | 
					
						
							|  |  |  | 							edit_text: 'last', | 
					
						
							|  |  |  | 							clear_on_edit: false, | 
					
						
							|  |  |  | 							reset_on_commit: false, | 
					
						
							|  |  |  | 							buttons: [ | 
					
						
							|  |  |  | 								['⋯', function(evt, elem){ | 
					
						
							| 
									
										
										
										
											2017-01-30 20:01:24 +03:00
										 |  |  | 									code = code || '' | 
					
						
							| 
									
										
										
										
											2017-01-22 01:39:46 +03:00
										 |  |  | 									// highlight the current action...
 | 
					
						
							| 
									
										
										
										
											2018-08-31 01:59:01 +03:00
										 |  |  | 									var a = that.parseStringHandler(code, that) | 
					
						
							| 
									
										
										
										
											2017-01-22 01:39:46 +03:00
										 |  |  | 									var p = a.action in that ?  | 
					
						
							|  |  |  | 										that.getDocPath(a.action) | 
					
						
							|  |  |  | 										: '' | 
					
						
							|  |  |  | 									// use the action menu to select actions...
 | 
					
						
							|  |  |  | 									var dialog = that.browseActions(p, { | 
					
						
							|  |  |  | 										no_disabled: true, | 
					
						
							|  |  |  | 										no_hidden: true, | 
					
						
							|  |  |  | 										callback: function(action){ | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 											code = action | 
					
						
							|  |  |  | 											elem.find('.text').last().text(action) | 
					
						
							|  |  |  | 											dialog.close() | 
					
						
							| 
									
										
										
										
											2017-01-22 01:39:46 +03:00
										 |  |  | 										}, | 
					
						
							|  |  |  | 									}) | 
					
						
							| 
									
										
										
										
											2017-01-25 22:56:18 +03:00
										 |  |  | 									 | 
					
						
							|  |  |  | 									dialog.dom.attr({ | 
					
						
							|  |  |  | 										'dialog-title': 'Action picker...', | 
					
						
							|  |  |  | 										'keep-dialog-title': true, | 
					
						
							|  |  |  | 									}) | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 								}], | 
					
						
							|  |  |  | 							], | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 						.on('edit-commit',  | 
					
						
							|  |  |  | 							function(evt, text){ code = text }) | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-31 01:59:01 +03:00
										 |  |  | 					// XXX should we edit/view this separately???
 | 
					
						
							|  |  |  | 					//make(['Debounce:', that.parseStringHandler(code).debounce || ''])
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 					make('---') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-25 06:44:46 +03:00
										 |  |  | 					make.EditableList(keys, { | 
					
						
							|  |  |  | 						unique: true, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						normalize: keyboard.normalizeKey, | 
					
						
							|  |  |  | 						check: keyboard.isKey, | 
					
						
							|  |  |  | 					}) | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					make('---') | 
					
						
							|  |  |  | 					 | 
					
						
							| 
									
										
										
										
											2017-01-15 04:36:48 +03:00
										 |  |  | 					make.ConfirmAction('Delete', { | 
					
						
							| 
									
										
										
										
											2017-01-25 06:44:46 +03:00
										 |  |  | 						callback: function(){ | 
					
						
							|  |  |  | 							keys = [] | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 							make.dialog.close()  | 
					
						
							| 
									
										
										
										
											2017-01-25 06:44:46 +03:00
										 |  |  | 						},  | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | 						timeout: that.config['ui-confirm-timeout'] || 2000, | 
					
						
							| 
									
										
										
										
											2017-01-18 01:34:06 +03:00
										 |  |  | 						buttons: [ | 
					
						
							| 
									
										
										
										
											2017-01-18 03:38:57 +03:00
										 |  |  | 							['Cancel edit', function(){  | 
					
						
							| 
									
										
										
										
											2017-01-30 05:37:55 +03:00
										 |  |  | 								make.dialog.close('cancel') | 
					
						
							| 
									
										
										
										
											2017-01-18 01:34:06 +03:00
										 |  |  | 							}], | 
					
						
							|  |  |  | 						], | 
					
						
							| 
									
										
										
										
											2017-01-15 04:36:48 +03:00
										 |  |  | 					}) | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 				}, | 
					
						
							|  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2017-05-14 00:06:55 +03:00
										 |  |  | 					cls: 'table-view', | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2017-01-17 20:48:57 +03:00
										 |  |  | 				// save the keys...
 | 
					
						
							| 
									
										
										
										
											2017-01-22 01:39:46 +03:00
										 |  |  | 				// XXX for some reason when Esc this is called twice...
 | 
					
						
							| 
									
										
										
										
											2017-08-10 14:09:01 +03:00
										 |  |  | 				.on('close', function(_, m){ | 
					
						
							|  |  |  | 					if(m == 'cancel'){ | 
					
						
							| 
									
										
										
										
											2017-01-18 01:34:06 +03:00
										 |  |  | 						return | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-18 00:56:08 +03:00
										 |  |  | 					// remove keys...
 | 
					
						
							|  |  |  | 					orig_keys | 
					
						
							|  |  |  | 						.filter(function(k){ return keys.indexOf(k) < 0 }) | 
					
						
							|  |  |  | 						.forEach(function(k){ | 
					
						
							|  |  |  | 							that.keyHandler(mode, k, '') | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-22 01:39:46 +03:00
										 |  |  | 					var new_keys = code == orig_code ? | 
					
						
							| 
									
										
										
										
											2017-08-17 15:40:51 +03:00
										 |  |  | 						keys.filter(function(k){ return orig_keys.indexOf(k) < 0 }) | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 						: keys | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-18 00:56:08 +03:00
										 |  |  | 					// add keys...
 | 
					
						
							| 
									
										
										
										
											2017-01-22 01:39:46 +03:00
										 |  |  | 					new_keys | 
					
						
							| 
									
										
										
										
											2017-01-18 00:56:08 +03:00
										 |  |  | 						.forEach(function(k){ | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 							that.keyHandler(mode, k, code) }) | 
					
						
							| 
									
										
										
										
											2017-01-25 07:38:38 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					callback  | 
					
						
							|  |  |  | 						&& callback.call(that, code) | 
					
						
							| 
									
										
										
										
											2017-01-17 20:48:57 +03:00
										 |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 				.run(function(){ | 
					
						
							|  |  |  | 					this.abort = function(){ | 
					
						
							|  |  |  | 						this.close('cancel') } | 
					
						
							|  |  |  | 					this.keyboard.handler('General', 'Q', 'abort') | 
					
						
							|  |  |  | 				}) })], | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 	editKeyboardMode: ['- Interface/Mode...', | 
					
						
							| 
									
										
										
										
											2017-01-26 04:53:17 +03:00
										 |  |  | 		core.doc`Mode editor...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Create new mode... | 
					
						
							|  |  |  | 			.editKeyboardMode() | 
					
						
							|  |  |  | 				-> dialog | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Edit/create mode by <name>... | 
					
						
							|  |  |  | 			.editKeyboardMode(<name>) | 
					
						
							|  |  |  | 				-> dialog | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Changes made in the editor are applied only when the dialog is  | 
					
						
							|  |  |  | 		closed, so it is possible to cancel any edit within the dialog | 
					
						
							|  |  |  | 		by either pressing Q or the "Cancel edits" button. | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		This adds several keyboard bindings to the dialog: | 
					
						
							|  |  |  | 			Q		- quit without saving changes. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		NOTE: empty mode name will not get saved. | 
					
						
							|  |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2017-01-25 07:38:38 +03:00
										 |  |  | 		widgets.makeUIDialog(function(mode, callback){ | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 			var doc = (that.keybindings[mode] || {}).doc | 
					
						
							|  |  |  | 			var pattern = (that.keybindings[mode] || {}).pattern || mode | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-26 04:53:17 +03:00
										 |  |  | 			var orig_mode = mode in that.keybindings ? mode : null | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 			return browse.makeLister(null,  | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 				function(path, make){ | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 					var cfg = { | 
					
						
							|  |  |  | 						start_on: 'open', | 
					
						
							|  |  |  | 						edit_text: 'last', | 
					
						
							|  |  |  | 						clear_on_edit: false, | 
					
						
							|  |  |  | 						reset_on_commit: false, | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					make.Editable(['Mode:', mode || ''], cfg) | 
					
						
							|  |  |  | 						.on('edit-commit',  | 
					
						
							| 
									
										
										
										
											2017-01-26 04:53:17 +03:00
										 |  |  | 							function(evt, text){ mode = text.trim() }) | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 					make.Editable(['Doc:', doc || ''], cfg) | 
					
						
							|  |  |  | 						.on('edit-commit',  | 
					
						
							| 
									
										
										
										
											2017-01-26 04:53:17 +03:00
										 |  |  | 							function(evt, text){ doc = text.trim() }) | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 					make.Editable(['Pattern:', pattern], cfg) | 
					
						
							|  |  |  | 						.on('edit-commit',  | 
					
						
							|  |  |  | 							function(evt, text){ pattern = text }) | 
					
						
							| 
									
										
										
										
											2017-01-13 09:00:22 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					make('---') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-15 04:36:48 +03:00
										 |  |  | 					make.ConfirmAction('Delete', { | 
					
						
							|  |  |  | 						callback: function(){ | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 							if(mode in that.keybindings){ | 
					
						
							|  |  |  | 								delete that.keybindings[mode] | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 							make.dialog.close() | 
					
						
							| 
									
										
										
										
											2017-01-15 04:36:48 +03:00
										 |  |  | 						},  | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | 						timeout: that.config['ui-confirm-timeout'] || 2000, | 
					
						
							| 
									
										
										
										
											2017-01-18 01:34:06 +03:00
										 |  |  | 						buttons: [ | 
					
						
							| 
									
										
										
										
											2017-01-18 03:38:57 +03:00
										 |  |  | 							['Cancel edit', function(){  | 
					
						
							| 
									
										
										
										
											2017-01-30 05:37:55 +03:00
										 |  |  | 								make.dialog.close('cancel') | 
					
						
							| 
									
										
										
										
											2017-01-18 01:34:06 +03:00
										 |  |  | 							}], | 
					
						
							|  |  |  | 						], | 
					
						
							| 
									
										
										
										
											2017-01-15 04:36:48 +03:00
										 |  |  | 					}) | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 				}, | 
					
						
							|  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2017-05-14 00:06:55 +03:00
										 |  |  | 					cls: 'table-view', | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2017-08-10 14:09:01 +03:00
										 |  |  | 				.on('close', function(_, m){ | 
					
						
							|  |  |  | 					if(m == 'cancel'){ | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 						return | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-25 06:44:46 +03:00
										 |  |  | 					var data = that.keybindings[orig_mode] || {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					data.doc = doc | 
					
						
							|  |  |  | 					data.pattern = pattern | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// update mode name if it changed... 
 | 
					
						
							| 
									
										
										
										
											2017-01-26 04:53:17 +03:00
										 |  |  | 					if(mode != orig_mode && mode != ''){ | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 						var order = Object.keys(that.keybindings) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-26 04:53:17 +03:00
										 |  |  | 						if(orig_mode){ | 
					
						
							|  |  |  | 							order[order.indexOf(orig_mode)] = mode | 
					
						
							|  |  |  | 							delete that.keybindings[orig_mode] | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 						that.keybindings[mode] = data | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						that.keyboard.sortModes(order) | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2017-01-25 07:38:38 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					callback  | 
					
						
							|  |  |  | 						&& callback.call(that, mode) | 
					
						
							| 
									
										
										
										
											2017-01-21 23:39:41 +03:00
										 |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 				.run(function(){ | 
					
						
							|  |  |  | 					this.abort = function(){ | 
					
						
							|  |  |  | 						this.close('cancel') } | 
					
						
							|  |  |  | 					this.keyboard.handler('General', 'Q', 'abort') | 
					
						
							|  |  |  | 				}) })], | 
					
						
							| 
									
										
										
										
											2017-01-15 00:49:19 +03:00
										 |  |  | 	editKeyboardModeDroppedKeys: ['- Interface/Dropped keys...', | 
					
						
							| 
									
										
										
										
											2017-01-26 04:53:17 +03:00
										 |  |  | 		core.doc`Edit keys dropped after a mode...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Edit the first mode... | 
					
						
							|  |  |  | 			.editKeyboardModeDroppedKeys() | 
					
						
							|  |  |  | 				-> dialog | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Edit a specific mode... | 
					
						
							|  |  |  | 			.editKeyboardModeDroppedKeys(<mode>) | 
					
						
							|  |  |  | 				-> dialog | 
					
						
							|  |  |  | 				-> false | 
					
						
							|  |  |  | 				NOTE: if a mode does not exist this will not create a  | 
					
						
							|  |  |  | 					dialog and will return false. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Changes made in the editor are applied only when the dialog is  | 
					
						
							|  |  |  | 		closed, so it is possible to cancel any edit within the dialog | 
					
						
							|  |  |  | 		by either pressing Q or the "Cancel edits" button. | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		This adds several keyboard bindings to the dialog: | 
					
						
							|  |  |  | 			Q		- quit without saving changes. | 
					
						
							|  |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 		widgets.makeUIDialog(function(mode){ | 
					
						
							| 
									
										
										
										
											2017-01-13 09:00:22 +03:00
										 |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2017-01-26 04:53:17 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			mode = mode || Object.keys(that.keybindings)[0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(!(mode in that.keybindings)){ | 
					
						
							|  |  |  | 				return false | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-18 01:34:06 +03:00
										 |  |  | 			var drop = (that.keybindings[mode].drop || []).slice() | 
					
						
							| 
									
										
										
										
											2017-01-13 09:00:22 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 			return browse.makeLister(null,  | 
					
						
							| 
									
										
										
										
											2017-01-17 20:48:57 +03:00
										 |  |  | 				function(path, make){ | 
					
						
							|  |  |  | 					var drop_all  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// the list editor...
 | 
					
						
							|  |  |  | 					make.EditableList(function(keys){ | 
					
						
							|  |  |  | 						// get...
 | 
					
						
							|  |  |  | 						if(keys === undefined){ | 
					
						
							|  |  |  | 							return drop && drop != '*' ? drop : [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						// set...
 | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							drop = drop_all ? '*' : keys | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					},  | 
					
						
							|  |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2017-01-18 20:48:30 +03:00
										 |  |  | 						unique: true, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						normalize: keyboard.normalizeKey, | 
					
						
							|  |  |  | 						check: keyboard.isKey, | 
					
						
							| 
									
										
										
										
											2017-01-17 20:48:57 +03:00
										 |  |  | 					}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-18 01:34:06 +03:00
										 |  |  | 					make.Separator() | 
					
						
							| 
									
										
										
										
											2017-01-17 20:48:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-18 01:34:06 +03:00
										 |  |  | 					// '*' toggler...
 | 
					
						
							|  |  |  | 					// XXX should this close the dialog???
 | 
					
						
							|  |  |  | 					make.ConfirmAction('Drop all keys', { | 
					
						
							|  |  |  | 						callback: function(){  | 
					
						
							|  |  |  | 							drop_all = '*' | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 							make.dialog.close()  | 
					
						
							|  |  |  | 						},  | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | 						timeout: that.config['ui-confirm-timeout'] || 2000, | 
					
						
							| 
									
										
										
										
											2017-01-17 20:48:57 +03:00
										 |  |  | 						buttons: [ | 
					
						
							| 
									
										
										
										
											2017-01-18 03:38:57 +03:00
										 |  |  | 							['Cancel edit', function(){  | 
					
						
							| 
									
										
										
										
											2017-01-30 05:37:55 +03:00
										 |  |  | 								make.dialog.close('cancel') | 
					
						
							| 
									
										
										
										
											2017-01-17 20:48:57 +03:00
										 |  |  | 							}], | 
					
						
							| 
									
										
										
										
											2017-01-18 01:34:06 +03:00
										 |  |  | 						], | 
					
						
							|  |  |  | 					}) | 
					
						
							| 
									
										
										
										
											2017-01-17 20:48:57 +03:00
										 |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2017-08-10 14:09:01 +03:00
										 |  |  | 				.on('close', function(_, m){ | 
					
						
							|  |  |  | 					if(m != 'cancel'){ | 
					
						
							| 
									
										
										
										
											2017-01-17 20:48:57 +03:00
										 |  |  | 						that.keybindings[mode].drop = drop | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2018-03-09 17:51:27 +03:00
										 |  |  | 				.run(function(){ | 
					
						
							|  |  |  | 					this.abort = function(){ | 
					
						
							|  |  |  | 						this.close('cancel') } | 
					
						
							|  |  |  | 					this.keyboard.handler('General', 'Q', 'abort') | 
					
						
							|  |  |  | 				}) })], | 
					
						
							| 
									
										
										
										
											2017-01-05 05:23:29 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-29 06:20:58 +03:00
										 |  |  | 	/*/ XXX move to gen2 | 
					
						
							| 
									
										
										
										
											2017-01-11 01:46:47 +03:00
										 |  |  | 	// XXX need to pre-process the docs...
 | 
					
						
							|  |  |  | 	// 		- remove the path component...
 | 
					
						
							|  |  |  | 	// 		- insert the action name where not doc present...
 | 
					
						
							|  |  |  | 	// XXX cleanup CSS
 | 
					
						
							| 
									
										
										
										
											2017-01-13 08:42:47 +03:00
										 |  |  | 	showKeyboardBindings: ['- Interface/Show keyboard bindings...', | 
					
						
							| 
									
										
										
										
											2017-01-11 01:46:47 +03:00
										 |  |  | 		widgets.makeUIDialog('Drawer',  | 
					
						
							|  |  |  | 			function(){ | 
					
						
							|  |  |  | 				return keyboard.buildKeybindingsHelpHTML( | 
					
						
							|  |  |  | 					this.__keyboard_config,  | 
					
						
							|  |  |  | 					this,  | 
					
						
							|  |  |  | 					function(action){ | 
					
						
							|  |  |  | 						return Object.keys(this.getPath(action))[0] }) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				background: 'white', | 
					
						
							|  |  |  | 				focusable: true, | 
					
						
							|  |  |  | 			})], | 
					
						
							| 
									
										
										
										
											2017-01-29 06:20:58 +03:00
										 |  |  | 	//*/
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | var KeyboardUI =  | 
					
						
							|  |  |  | module.KeyboardUI = core.ImageGridFeatures.Feature({ | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 	title: '', | 
					
						
							|  |  |  | 	doc: '', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | 	tag: 'keyboard-ui', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 	depends: [ | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | 		'keyboard', | 
					
						
							|  |  |  | 		'ui-dialogs', | 
					
						
							| 
									
										
										
										
											2017-01-11 22:32:16 +03:00
										 |  |  | 	], | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-20 01:12:48 +03:00
										 |  |  | 	actions: KeyboardUIActions, | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							| 
									
										
										
										
											2016-08-20 22:49:36 +03:00
										 |  |  | * vim:set ts=4 sw=4 :                               */ return module }) |