| 
									
										
										
										
											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') | 
					
						
							|  |  |  | var keyboard = require('lib/keyboard') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 widget = require('lib/widget/widget') | 
					
						
							|  |  |  | var browse = require('lib/widget/browse') | 
					
						
							|  |  |  | var overlay = require('lib/widget/overlay') | 
					
						
							|  |  |  | var drawer = require('lib/widget/drawer') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 02:10:26 +03:00
										 |  |  | // helper...
 | 
					
						
							|  |  |  | function customScale(n){ | 
					
						
							|  |  |  | 	return { | 
					
						
							| 
									
										
										
										
											2016-06-21 02:45:45 +03:00
										 |  |  | 		default: 'fitCustom: '+n+' -- Set cutom image size', | 
					
						
							|  |  |  | 		'alt': 'setCustomSize: '+n+' -- Set current image size as custom', | 
					
						
							|  |  |  | 		'ctrl+shift': 'setCustomSize: '+n+' null -- Clear custom image size', | 
					
						
							| 
									
										
										
										
											2016-06-21 02:10:26 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-28 17:50:55 +03:00
										 |  |  | // XXX might be a good idea to be able ignore actions rather than keys...
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | // XXX add this to the global doc...
 | 
					
						
							|  |  |  | var GLOBAL_KEYBOARD = | 
					
						
							|  |  |  | module.GLOBAL_KEYBOARD = { | 
					
						
							| 
									
										
										
										
											2016-04-03 20:57:03 +03:00
										 |  |  | 	'Global':{ | 
					
						
							|  |  |  | 		doc: 'Global bindings that take priority over other sections.', | 
					
						
							|  |  |  | 		pattern: '*', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 	'Slideshow': { | 
					
						
							|  |  |  | 		pattern: '.slideshow-running', | 
					
						
							|  |  |  | 		ignore: [ | 
					
						
							| 
									
										
										
										
											2016-04-03 00:58:49 +03:00
										 |  |  | 			'Esc', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 			'Up', 'Down', 'Enter', | 
					
						
							| 
									
										
										
										
											2017-01-06 02:18:21 +03:00
										 |  |  | 			'R', 'L', 'G', 'T', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		], | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-03 22:04:38 +03:00
										 |  |  | 		Esc: 'toggleSlideshow: "off" -- Exit slideshow', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		Enter: 'slideshowDialog', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Left: 'resetSlideshowTimer', | 
					
						
							|  |  |  | 		Right: 'resetSlideshowTimer', | 
					
						
							|  |  |  | 		Home: 'resetSlideshowTimer', | 
					
						
							|  |  |  | 		End: 'resetSlideshowTimer', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-16 01:36:55 +03:00
										 |  |  | 		T: 'slideshowIntervalDialog', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		R: 'toggleSlideshowDirection', | 
					
						
							|  |  |  | 		L: 'toggleSlideshowLooping', | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-28 17:50:55 +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???
 | 
					
						
							| 
									
										
										
										
											2016-04-03 00:58:49 +03:00
										 |  |  | 	'Single Image': { | 
					
						
							|  |  |  | 		pattern: '.single-image-mode', | 
					
						
							|  |  |  | 		ignore: [ | 
					
						
							|  |  |  | 			'Esc', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// do not crop in single image mode...
 | 
					
						
							|  |  |  | 			'C', 'F2', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-24 01:13:12 +03:00
										 |  |  | 			// zooming...
 | 
					
						
							|  |  |  | 			'#0', '#1', '#2', '#3', '#4', '#5', '#6', '#7', '#8', '#9', | 
					
						
							| 
									
										
										
										
											2016-04-03 00:58:49 +03:00
										 |  |  | 		], | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 02:45:45 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 04:16:54 +03:00
										 |  |  | 		// NOTE: these are here so as to enable handling via the next 
 | 
					
						
							|  |  |  | 		// 		block, i.e. the Viewer
 | 
					
						
							|  |  |  | 		// 		...if not given, then the ignore above will shadow the 
 | 
					
						
							|  |  |  | 		// 		keys...
 | 
					
						
							|  |  |  | 		// NOTE: the 'nop' action does not exist, this it will get ignored
 | 
					
						
							|  |  |  | 		'(': 'nop', | 
					
						
							|  |  |  | 		')': 'nop', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 02:45:45 +03:00
										 |  |  | 		// zooming...
 | 
					
						
							| 
									
										
										
										
											2016-04-28 18:01:00 +03:00
										 |  |  | 		'#1': 'fitScreen', | 
					
						
							| 
									
										
										
										
											2016-06-21 05:43:14 +03:00
										 |  |  | 		// XXX should these also be implemented in the same way as 4-9???
 | 
					
						
							| 
									
										
										
										
											2016-06-21 02:10:26 +03:00
										 |  |  | 		'#2': { | 
					
						
							|  |  |  | 			default: 'fitNormal', | 
					
						
							| 
									
										
										
										
											2016-06-21 05:43:14 +03:00
										 |  |  | 			'alt': 'setNormalScale -- Set current image size as normal', | 
					
						
							| 
									
										
										
										
											2016-06-21 06:06:34 +03:00
										 |  |  | 			'ctrl+shift': 'setNormalScale: null -- Reset normal image size to default', | 
					
						
							| 
									
										
										
										
											2016-06-21 02:10:26 +03:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		'#3': { | 
					
						
							|  |  |  | 			default: 'fitSmall', | 
					
						
							| 
									
										
										
										
											2016-06-21 05:43:14 +03:00
										 |  |  | 			'alt': 'setSmallScale -- Set current image size as small', | 
					
						
							| 
									
										
										
										
											2016-06-21 06:06:34 +03:00
										 |  |  | 			'ctrl+shift': 'setSmallScale: null -- Reset small image size to default', | 
					
						
							| 
									
										
										
										
											2016-06-21 02:10:26 +03:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		'#4': customScale(4), | 
					
						
							|  |  |  | 		'#5': customScale(5), | 
					
						
							|  |  |  | 		'#6': customScale(6), | 
					
						
							|  |  |  | 		'#7': customScale(7), | 
					
						
							|  |  |  | 		'#8': customScale(8), | 
					
						
							|  |  |  | 		'#9': customScale(9), | 
					
						
							|  |  |  | 		'#0': customScale(0), | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-24 01:13:12 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-03 22:04:38 +03:00
										 |  |  | 		Esc: 'toggleSingleImage: "off" -- Exit single image view', | 
					
						
							| 
									
										
										
										
											2016-04-28 16:11:55 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// ignore sorting and reversing...
 | 
					
						
							| 
									
										
										
										
											2016-04-28 17:50:55 +03:00
										 |  |  | 		// XXX not sure about these yet, especially reversing...
 | 
					
						
							| 
									
										
										
										
											2016-04-28 16:11:55 +03:00
										 |  |  | 		R: { | 
					
						
							|  |  |  | 			shift: 'IGNORE', | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		S: { | 
					
						
							|  |  |  | 			shift: 'IGNORE', | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-04-03 00:58:49 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-05 18:54:09 +03:00
										 |  |  | 	// XXX add "save as collection..."
 | 
					
						
							| 
									
										
										
										
											2016-04-03 20:57:03 +03:00
										 |  |  | 	'Cropped': { | 
					
						
							| 
									
										
										
										
											2016-04-04 19:36:50 +03:00
										 |  |  | 		pattern: '.crop-mode', | 
					
						
							| 
									
										
										
										
											2016-04-05 18:54:09 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		Esc: { | 
					
						
							|  |  |  | 			default: 'uncrop', | 
					
						
							|  |  |  | 			ctrl: 'uncropAll', | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-04-03 20:57:03 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-29 23:23:05 +03:00
										 |  |  | 	'Range': { | 
					
						
							|  |  |  | 		doc: 'Range editing', | 
					
						
							|  |  |  | 		pattern: '.brace', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// XXX add:
 | 
					
						
							|  |  |  | 		// 		- range navigation
 | 
					
						
							|  |  |  | 		// 		- range manipulation
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Esc: 'clearRange', | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-05 18:54:09 +03:00
										 |  |  | 	// XXX add "save as collection..." (???)
 | 
					
						
							| 
									
										
										
										
											2016-04-03 20:57:03 +03:00
										 |  |  | 	// XXX cleanup...
 | 
					
						
							|  |  |  | 	'Viewer': { | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		doc: 'NOTE: binding priority is the same as the order of sections '+ | 
					
						
							|  |  |  | 			'on this page.', | 
					
						
							|  |  |  | 		pattern: '*', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-07 04:58:22 +03:00
										 |  |  | 		X: { | 
					
						
							|  |  |  | 			alt: 'close', | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		F4: { | 
					
						
							|  |  |  | 			alt: 'close', | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		Q: { | 
					
						
							|  |  |  | 			meta: 'close', | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-04-03 20:57:03 +03:00
										 |  |  | 		// XXX
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		F5: keyboard.doc('Full reload viewer',  | 
					
						
							|  |  |  | 			function(){  | 
					
						
							|  |  |  | 				//a.stop()
 | 
					
						
							|  |  |  | 				/* | 
					
						
							|  |  |  | 				killAllWorkers() | 
					
						
							|  |  |  | 					.done(function(){ | 
					
						
							|  |  |  | 						reload()  | 
					
						
							|  |  |  | 					}) | 
					
						
							|  |  |  | 				*/ | 
					
						
							|  |  |  | 				location.reload() | 
					
						
							|  |  |  | 				return false | 
					
						
							|  |  |  | 			}), | 
					
						
							|  |  |  | 		F12: 'showDevTools', | 
					
						
							|  |  |  | 		// NOTE: these are for systems where F** keys are not available 
 | 
					
						
							|  |  |  | 		// 		or do other stuff...
 | 
					
						
							|  |  |  | 		R: { | 
					
						
							|  |  |  | 			default: 'rotateCW', | 
					
						
							|  |  |  | 			shift: 'reverseImages', | 
					
						
							| 
									
										
										
										
											2016-06-09 00:10:11 +03:00
										 |  |  | 			ctrl: 'loadNewImages!', | 
					
						
							| 
									
										
										
										
											2016-08-07 02:42:25 +03:00
										 |  |  | 			alt: 'browseActions: "/Ribbon/" -- Open ribbon menu', | 
					
						
							| 
									
										
										
										
											2016-06-09 00:10:11 +03:00
										 |  |  | 			'ctrl+alt': 'reload!', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 			'ctrl+shift': 'F5', | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		L: 'rotateCCW', | 
					
						
							|  |  |  | 		H: { | 
					
						
							|  |  |  | 			default: 'flipHorizontal', | 
					
						
							|  |  |  | 			ctrl: 'listURLHistory', | 
					
						
							| 
									
										
										
										
											2016-05-04 21:28:46 +03:00
										 |  |  | 			'ctrl+shift': 'listSaveHistory', | 
					
						
							| 
									
										
										
										
											2016-04-03 21:33:36 +03:00
										 |  |  | 			alt: 'browseActions: "/History/" -- Open history menu', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		V: 'flipVertical', | 
					
						
							| 
									
										
										
										
											2016-11-23 16:14:38 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// tilt...
 | 
					
						
							|  |  |  | 		// XXX experimental, not sure if wee need this with a keyboard...
 | 
					
						
							|  |  |  | 		T: { | 
					
						
							|  |  |  | 			default: 'rotateRibbonCCW -- Tilt ribbons counter clock wise', | 
					
						
							|  |  |  | 			shift: 'rotateRibbonCW -- Tilt ribbons clock wise', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			alt: 'resetRibbonRotation -- Reset ribbon tilt', | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		P: { | 
					
						
							|  |  |  | 			'ctrl+shift': 'F12', | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// NOTE: this is handled by the wrapper at this point, so we do 
 | 
					
						
							|  |  |  | 		// 		not have to do anything here...
 | 
					
						
							|  |  |  | 		F11: 'toggleFullScreen',  | 
					
						
							|  |  |  | 		F: { | 
					
						
							|  |  |  | 			ctrl: 'F11', | 
					
						
							|  |  |  | 			meta: 'F11', | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// XXX testing...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Enter: 'toggleSingleImage', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Home: { | 
					
						
							|  |  |  | 			default: 'firstImage', | 
					
						
							|  |  |  | 			ctrl: 'firstGlobalImage', | 
					
						
							|  |  |  | 			shift: 'firstRibbon', | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		End: { | 
					
						
							|  |  |  | 			default: 'lastImage', | 
					
						
							|  |  |  | 			ctrl: 'lastGlobalImage', | 
					
						
							|  |  |  | 			shift: 'lastRibbon', | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		Left: { | 
					
						
							|  |  |  | 			default: 'prevImage', | 
					
						
							|  |  |  | 			alt: 'shiftImageLeft!', | 
					
						
							|  |  |  | 			ctrl: 'prevScreen', | 
					
						
							|  |  |  | 			// XXX need to prevent default on mac + browser...
 | 
					
						
							|  |  |  | 			meta: 'prevScreen', | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		PgUp: 'prevScreen', | 
					
						
							|  |  |  | 		PgDown: 'nextScreen', | 
					
						
							|  |  |  | 		Right: { | 
					
						
							|  |  |  | 			default: 'nextImage', | 
					
						
							|  |  |  | 			alt: 'shiftImageRight!', | 
					
						
							|  |  |  | 			ctrl: 'nextScreen', | 
					
						
							|  |  |  | 			// XXX need to prevent default on mac + browser...
 | 
					
						
							|  |  |  | 			meta: 'nextScreen', | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-04-23 00:07:04 +03:00
										 |  |  | 		Space: 'Right', | 
					
						
							|  |  |  | 		Backspace: 'Left', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		'(': 'prevImageInOrder', | 
					
						
							|  |  |  | 		')': 'nextImageInOrder', | 
					
						
							|  |  |  | 		',': 'prevMarked', | 
					
						
							|  |  |  | 		'.': 'nextMarked', | 
					
						
							| 
									
										
										
										
											2016-12-28 20:11:42 +03:00
										 |  |  | 		'[': { | 
					
						
							|  |  |  | 			default: 'prevBookmarked', | 
					
						
							|  |  |  | 			// XXX experimental
 | 
					
						
							|  |  |  | 			shift: 'openRange', | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		']': { | 
					
						
							|  |  |  | 			default: 'nextBookmarked', | 
					
						
							|  |  |  | 			// XXX experimental
 | 
					
						
							|  |  |  | 			shift: 'closeRange', | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		Up: { | 
					
						
							|  |  |  | 			default: 'prevRibbon', | 
					
						
							|  |  |  | 			shift: 'shiftImageUp', | 
					
						
							|  |  |  | 			'alt+shift': 'travelImageUp', | 
					
						
							|  |  |  | 			'ctrl+shift': 'shiftImageUpNewRibbon', | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		Down: { | 
					
						
							|  |  |  | 			default: 'nextRibbon', | 
					
						
							|  |  |  | 			shift: 'shiftImageDown', | 
					
						
							|  |  |  | 			'alt+shift': 'travelImageDown', | 
					
						
							|  |  |  | 			'ctrl+shift': 'shiftImageDownNewRibbon', | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		'#0': 'fitMax', | 
					
						
							|  |  |  | 		'#1': { | 
					
						
							|  |  |  | 			default: 'fitImage', | 
					
						
							|  |  |  | 			shift: 'fitRibbon', | 
					
						
							|  |  |  | 			ctrl: 'fitOrig!', | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-04-03 22:04:38 +03:00
										 |  |  | 		'#2': 'fitImage: 2 -- Fit 2 Images', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		'#3': { | 
					
						
							| 
									
										
										
										
											2016-04-03 22:04:38 +03:00
										 |  |  | 			default: 'fitImage: 3 -- Fit 3 images', | 
					
						
							|  |  |  | 			shift: 'fitRibbon: 3.5 -- Fit 3.5 ribbons', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-04-07 05:41:06 +03:00
										 |  |  | 		'#4': 'fitImage: 4 -- Fit 4 images', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		'#5': { | 
					
						
							| 
									
										
										
										
											2016-04-03 22:04:38 +03:00
										 |  |  | 			default: 'fitImage: 5 -- Fit 5 images', | 
					
						
							|  |  |  | 			shift: 'fitRibbon: 5.5 -- Fit 5.5 ribbons', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-04-03 22:04:38 +03:00
										 |  |  | 		'#6': 'fitImage: 6 -- Fit 6 images', | 
					
						
							|  |  |  | 		'#7': 'fitImage: 7 -- Fit 7 images', | 
					
						
							|  |  |  | 		'#8':'fitImage: 8 -- Fit 8 images', | 
					
						
							|  |  |  | 		'#9': 'fitImage: 9 -- Fit 9 images', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2016-11-09 04:53:42 +03:00
										 |  |  | 		'+': { | 
					
						
							|  |  |  | 			default: 'zoomIn', | 
					
						
							|  |  |  | 			ctrl: 'lighterTheme!', | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		'=': '+', | 
					
						
							| 
									
										
										
										
											2016-11-09 04:53:42 +03:00
										 |  |  | 		'-': { | 
					
						
							|  |  |  | 			default: 'zoomOut', | 
					
						
							|  |  |  | 			ctrl: 'darkerTheme!', | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		F2: { | 
					
						
							|  |  |  | 			default: 'cropRibbon', | 
					
						
							|  |  |  | 			shift: 'cropRibbonAndAbove', | 
					
						
							|  |  |  | 			ctrl: 'cropMarked', | 
					
						
							|  |  |  | 			alt: 'cropBookmarked', | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// marking...
 | 
					
						
							|  |  |  | 		M: { | 
					
						
							|  |  |  | 			default: 'toggleMark', | 
					
						
							| 
									
										
										
										
											2016-04-03 22:04:38 +03:00
										 |  |  | 			alt: 'browseActions: "/Mark/" -- Show mark menu', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		A: { | 
					
						
							|  |  |  | 			alt: 'browseActions', | 
					
						
							|  |  |  | 			'alt+shift': 'listActions', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-03 22:04:38 +03:00
										 |  |  | 			ctrl: 'toggleMark!: "ribbon" "on" -- Mark all images in ribbon', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		D: { | 
					
						
							| 
									
										
										
										
											2016-04-03 22:04:38 +03:00
										 |  |  | 			ctrl: 'toggleMark!: "ribbon" "off" -- Unmark all images in ribbon', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		I: { | 
					
						
							|  |  |  | 			default: 'showMetadata', | 
					
						
							| 
									
										
										
										
											2016-06-23 01:00:24 +03:00
										 |  |  | 			alt: 'browseActions: "/Image/" -- Show image menu', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 			shift: 'toggleStatusBar', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-03 22:04:38 +03:00
										 |  |  | 			ctrl: 'toggleMark!: "ribbon" -- Invert marks in ribbon', | 
					
						
							|  |  |  | 			'ctrl+shift': 'showMetadata: "current" "full" -- Show full metadata', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			'meta+alt': 'showDevTools', | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-12-28 20:11:42 +03:00
										 |  |  | 		// XXX experimental...
 | 
					
						
							|  |  |  | 		'*': 'setRangeBorder', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		B: { | 
					
						
							|  |  |  | 			default: 'toggleBookmark', | 
					
						
							|  |  |  | 			ctrl: 'toggleTheme!', | 
					
						
							| 
									
										
										
										
											2016-11-09 04:53:42 +03:00
										 |  |  | 			'ctrl+shift': 'toggleTheme!: "prev"', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-03 22:04:38 +03:00
										 |  |  | 			alt: 'browseActions: "/Bookmark/" -- Show bookmark menu', | 
					
						
							| 
									
										
										
										
											2016-06-29 19:58:10 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// XXX not sure if this is the right way to go...
 | 
					
						
							|  |  |  | 			shift: 'setBaseRibbon', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		E: { | 
					
						
							|  |  |  | 			default: 'openInExtenalEditor', | 
					
						
							| 
									
										
										
										
											2016-04-03 22:04:38 +03:00
										 |  |  | 			shift: 'openInExtenalEditor: 1 -- Open in alternative editor', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 			alt: 'listExtenalEditors', | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-04-12 19:01:40 +03:00
										 |  |  | 		C: { | 
					
						
							|  |  |  | 			default: 'browseActions: "/Crop/" -- Show crop menu', | 
					
						
							|  |  |  | 			// do the default copy thing...
 | 
					
						
							|  |  |  | 			// NOTE: this stops the default: handler from getting the ctrl:
 | 
					
						
							|  |  |  | 			// 		key case...
 | 
					
						
							|  |  |  | 			ctrl: '', | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		O: 'browsePath', | 
					
						
							|  |  |  | 		S: { | 
					
						
							|  |  |  | 			default: 'slideshowDialog', | 
					
						
							| 
									
										
										
										
											2016-04-22 18:11:22 +03:00
										 |  |  | 			//shift: 'sortImages: "Date" -- Sort images by date',
 | 
					
						
							|  |  |  | 			shift: 'sortImages -- Sort images', | 
					
						
							| 
									
										
										
										
											2016-04-28 17:50:55 +03:00
										 |  |  | 			//alt: 'browseActions: "/Sort/"',
 | 
					
						
							|  |  |  | 			alt: 'sortDialog', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 			// XXX need to make this save to base_path if it exists and
 | 
					
						
							|  |  |  | 			// 		ask the user if it does not... now it always asks.
 | 
					
						
							|  |  |  | 			ctrl: 'saveIndexHere', | 
					
						
							| 
									
										
										
										
											2016-04-16 05:19:31 +03:00
										 |  |  | 			'ctrl+shift': 'exportDialog', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// XXX still experimental...
 | 
					
						
							|  |  |  | 		U: { | 
					
						
							| 
									
										
										
										
											2016-12-31 19:51:16 +03:00
										 |  |  | 			default: 'undo', | 
					
						
							|  |  |  | 			shift: 'redo', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		Z: { | 
					
						
							| 
									
										
										
										
											2016-12-31 19:51:16 +03:00
										 |  |  | 			ctrl: 'undo', | 
					
						
							|  |  |  | 			'ctrl+shift': 'redo', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		G: { | 
					
						
							|  |  |  | 			default: 'editStatusBarIndex!', | 
					
						
							|  |  |  | 			shift: 'toggleStatusBarIndexMode!', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// XXX for debug...
 | 
					
						
							| 
									
										
										
										
											2016-11-17 04:21:20 +03:00
										 |  |  | 			//ctrl: function(){ $('.viewer').toggleClass('visible-gid') },
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-04-07 05:41:06 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		'?': 'showKeyboardBindings', | 
					
						
							| 
									
										
										
										
											2017-01-09 03:51:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		W: 'testAction', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | }	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-03 00:58:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | /*********************************************************************/ | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | // + simpler to group bindings
 | 
					
						
							|  |  |  | // - harder to automate binding creation (e.g. via customScale(..))
 | 
					
						
							| 
									
										
										
										
											2017-01-09 03:51:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | var keyboard2 = require('lib/keyboard2') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // XXX do we want to add sub-sections to better organize keys for 
 | 
					
						
							|  |  |  | // 		documentation???
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | var GLOBAL_KEYBOARD2 = | 
					
						
							|  |  |  | module.GLOBAL_KEYBOARD2 = { | 
					
						
							|  |  |  | 	'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: [ | 
					
						
							|  |  |  | 			'Esc', | 
					
						
							|  |  |  | 			'Up', 'Down', 'Enter', | 
					
						
							|  |  |  | 			'R', 'L', 'G', 'T', | 
					
						
							|  |  |  | 		], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Esc: 'toggleSlideshow: "off" -- Exit slideshow', | 
					
						
							|  |  |  | 		Enter: 'slideshowDialog', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Left: 'resetSlideshowTimer', | 
					
						
							|  |  |  | 		Right: 'resetSlideshowTimer', | 
					
						
							|  |  |  | 		Home: 'resetSlideshowTimer', | 
					
						
							|  |  |  | 		End: 'resetSlideshowTimer', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		T: 'slideshowIntervalDialog', | 
					
						
							|  |  |  | 		R: 'toggleSlideshowDirection', | 
					
						
							|  |  |  | 		L: 'toggleSlideshowLooping', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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', | 
					
						
							|  |  |  | 		], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// NOTE: these are here so as to enable handling via the next 
 | 
					
						
							|  |  |  | 		// 		block, i.e. the Viewer
 | 
					
						
							|  |  |  | 		// 		...if not given, then the ignore above will shadow the 
 | 
					
						
							|  |  |  | 		// 		keys...
 | 
					
						
							|  |  |  | 		// NOTE: the 'nop' action does not exist, this it will get ignored
 | 
					
						
							|  |  |  | 		'(': 'nop', | 
					
						
							|  |  |  | 		')': 'nop', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// 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', | 
					
						
							|  |  |  | 		/*/ XXX | 
					
						
							|  |  |  | 		'#4': customScale(4), | 
					
						
							|  |  |  | 		'#5': customScale(5), | 
					
						
							|  |  |  | 		'#6': customScale(6), | 
					
						
							|  |  |  | 		'#7': customScale(7), | 
					
						
							|  |  |  | 		'#8': customScale(8), | 
					
						
							|  |  |  | 		'#9': customScale(9), | 
					
						
							|  |  |  | 		'#0': customScale(0), | 
					
						
							|  |  |  | 		*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Esc: 'toggleSingleImage: "off" -- Exit single image view', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// ignore sorting and reversing...
 | 
					
						
							|  |  |  | 		// XXX not sure about these yet, especially reversing...
 | 
					
						
							|  |  |  | 		shift_R: 'IGNORE', | 
					
						
							|  |  |  | 		shift_S: 'IGNORE', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 	// XXX add "save as collection..."
 | 
					
						
							|  |  |  | 	'Cropped': { | 
					
						
							|  |  |  | 		pattern: '.crop-mode', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		Esc: 'uncrop', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		ctrl_Esc: 'uncropAll', | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +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-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
 | 
					
						
							|  |  |  | 		F5: keyboard.doc('Full reload viewer',  | 
					
						
							|  |  |  | 			function(){  | 
					
						
							|  |  |  | 				//a.stop()
 | 
					
						
							|  |  |  | 				/* | 
					
						
							|  |  |  | 				killAllWorkers() | 
					
						
							|  |  |  | 					.done(function(){ | 
					
						
							|  |  |  | 						reload()  | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 					}) | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 				*/ | 
					
						
							|  |  |  | 				location.reload() | 
					
						
							|  |  |  | 				return false | 
					
						
							|  |  |  | 			}), | 
					
						
							| 
									
										
										
										
											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', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		//alt_S: 'browseActions: "/Sort/"',
 | 
					
						
							|  |  |  | 		alt_shift_A: 'listActions', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// 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', | 
					
						
							|  |  |  | 		alt_E: 'listExtenalEditors', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// history...
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		ctrl_H: 'listURLHistory', | 
					
						
							|  |  |  | 		ctrl_shift_H: 'listSaveHistory', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		U: 'undo', | 
					
						
							|  |  |  | 		ctrl_Z: 'undo', | 
					
						
							|  |  |  | 		shift_U: 'redo', | 
					
						
							|  |  |  | 		ctrl_shift_Z: 'redo', | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		alt_H: 'browseActions: "/History/" -- Open 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...
 | 
					
						
							|  |  |  | 		T: 'rotateRibbonCCW -- Tilt ribbons counter clock wise', | 
					
						
							|  |  |  | 		shift_T: 'rotateRibbonCW -- Tilt ribbons clock wise', | 
					
						
							|  |  |  | 		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...
 | 
					
						
							|  |  |  | 		F11: 'toggleFullScreen',  | 
					
						
							|  |  |  | 		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... 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		Enter: '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...
 | 
					
						
							|  |  |  | 		ctrl_R: 'toggleTheme!', | 
					
						
							|  |  |  | 		ctrl_shift_R: 'toggleTheme!: "prev"', | 
					
						
							|  |  |  | 		'ctrl+-': 'darkerTheme!', | 
					
						
							|  |  |  | 		'ctrl++': 'lighterTheme!', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// navigation...
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		Left: 'prevImage', | 
					
						
							| 
									
										
										
										
											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-01-08 03:32:49 +03:00
										 |  |  | 		Up: 'prevRibbon', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		Down: 'nextRibbon', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// shifting...
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		shift_Up: 'shiftImageUp', | 
					
						
							|  |  |  | 		alt_shift_Up: 'travelImageUp', | 
					
						
							|  |  |  | 		ctrl_shift_Up: 'shiftImageUpNewRibbon', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		shift_Down: 'shiftImageDown', | 
					
						
							|  |  |  | 		alt_shift_Down: 'travelImageDown', | 
					
						
							|  |  |  | 		ctrl_shift_Down: 'shiftImageDownNewRibbon', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		alt_Left: 'shiftImageLeft!', | 
					
						
							|  |  |  | 		alt_Right: 'shiftImageRight!', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		shift_R: 'setBaseRibbon', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// editing...
 | 
					
						
							|  |  |  | 		R: 'rotateCW', | 
					
						
							|  |  |  | 		L: 'rotateCCW', | 
					
						
							|  |  |  | 		H: 'flipHorizontal', | 
					
						
							|  |  |  | 		V: 'flipVertical', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// ribbon image stuff...
 | 
					
						
							|  |  |  | 		alt_I: 'browseActions: "/Image/" -- Show image menu', | 
					
						
							|  |  |  | 		alt_R: 'browseActions: "/Ribbon/" -- Open ribbon menu', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// 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', | 
					
						
							|  |  |  | 		'#8':'fitImage: 8 -- Fit 8 images', | 
					
						
							|  |  |  | 		'#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', | 
					
						
							|  |  |  | 		shift_F2: 'cropRibbonAndAbove', | 
					
						
							|  |  |  | 		ctrl_F2: 'cropMarked', | 
					
						
							|  |  |  | 		alt_F2: 'cropBookmarked', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		C: 'browseActions: "/Crop/" -- Show crop menu', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// metadata...
 | 
					
						
							|  |  |  | 		I: 'showMetadata', | 
					
						
							|  |  |  | 		ctrl_shift_I: 'showMetadata: "current" "full" -- Show full metadata', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// marking...
 | 
					
						
							|  |  |  | 		M: 'toggleMark', | 
					
						
							|  |  |  | 		ctrl_A: 'toggleMark!: "ribbon" "on" -- Mark all images in ribbon', | 
					
						
							|  |  |  | 		ctrl_D: 'toggleMark!: "ribbon" "off" -- Unmark all images in ribbon', | 
					
						
							|  |  |  | 		ctrl_I: 'toggleMark!: "ribbon" -- Invert marks in ribbon', | 
					
						
							| 
									
										
										
										
											2017-01-08 04:58:32 +03:00
										 |  |  | 		',': 'prevMarked', | 
					
						
							|  |  |  | 		'.': 'nextMarked', | 
					
						
							|  |  |  | 		alt_M: 'browseActions: "/Mark/" -- Show 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', | 
					
						
							|  |  |  | 		alt_B: 'browseActions: "/Bookmark/" -- Show bookmark menu', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// 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-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
										 |  |  | 
 | 
					
						
							|  |  |  | 		// doc...
 | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 		// XXX for debug...
 | 
					
						
							|  |  |  | 		//ctrl_G: function(){ $('.viewer').toggleClass('visible-gid') },
 | 
					
						
							|  |  |  | 		'?': 'showKeyboardBindings', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-09 03:51:32 +03:00
										 |  |  | 		W: 'testAction', | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-09 03:51:32 +03:00
										 |  |  | //keyboard = keyboard2
 | 
					
						
							|  |  |  | //GLOBAL_KEYBOARD = GLOBAL_KEYBOARD2
 | 
					
						
							| 
									
										
										
										
											2017-01-08 04:21:22 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-09 03:51:32 +03:00
										 |  |  | window.kb = keyboard2.Keyboard(GLOBAL_KEYBOARD2, keyboard2.checkGlobalMode) | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | /*********************************************************************/ | 
					
						
							| 
									
										
										
										
											2016-04-03 06:30:30 +03:00
										 |  |  | // XXX add a key binding list UI...
 | 
					
						
							|  |  |  | // XXX add loading/storing of kb bindings...
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-03 00:58:49 +03:00
										 |  |  | // XXX add introspection and doc actions...
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | var KeyboardActions = actions.Actions({ | 
					
						
							|  |  |  | 	config: { | 
					
						
							|  |  |  | 		// limit key repeat to one per N milliseconds.
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// Set this to -1 or null to run keys without any limitations.
 | 
					
						
							|  |  |  | 		'max-key-repeat-rate': 0, | 
					
						
							| 
									
										
										
										
											2016-12-03 14:39:04 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		'keyboard-repeat-pause-check': 100, | 
					
						
							| 
									
										
										
										
											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', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	get keyboard(){ | 
					
						
							| 
									
										
										
										
											2017-01-03 02:55:25 +03:00
										 |  |  | 		return this.__keyboard_config }, | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-03 14:39:04 +03:00
										 |  |  | 	pauseKeyboardRepeat: ['- Interface/', | 
					
						
							| 
									
										
										
										
											2016-12-03 17:28:58 +03:00
										 |  |  | 		function(){  | 
					
						
							|  |  |  | 			this.__keyboard_repeat_paused = true }], | 
					
						
							| 
									
										
										
										
											2016-12-03 14:39:04 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 03:06:06 +03:00
										 |  |  | 	toggleKeyboardHandling: ['- Interface/Keyboard handling', | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 		toggler.Toggler(null, function(_, state){  | 
					
						
							|  |  |  | 			if(state == null){ | 
					
						
							|  |  |  | 				return this.__keyboard_handler ? 'on' : 'off' | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-03 14:39:04 +03:00
										 |  |  | 			// repeat stop checker...
 | 
					
						
							|  |  |  | 			var check = (function(){ | 
					
						
							|  |  |  | 				if(this.config['keyboard-repeat-pause-check'] > 0 | 
					
						
							|  |  |  | 						&& this.__keyboard_repeat_paused){ | 
					
						
							|  |  |  | 					var that = this | 
					
						
							|  |  |  | 					this.__keyboard_repeat_pause_timeout  | 
					
						
							|  |  |  | 						&& clearTimeout(this.__keyboard_repeat_pause_timeout) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					this.__keyboard_repeat_pause_timeout = setTimeout(function(){ | 
					
						
							|  |  |  | 						delete that.__keyboard_repeat_paused | 
					
						
							|  |  |  | 						delete that.__keyboard_repeat_pause_timeout  | 
					
						
							|  |  |  | 					}, this.config['keyboard-repeat-pause-check'] || 100) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					return false | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return true | 
					
						
							|  |  |  | 			}).bind(this) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 			// start/reset keyboard handling...
 | 
					
						
							|  |  |  | 			if(state == 'on'){ | 
					
						
							|  |  |  | 				var that = this | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-03 17:28:58 +03:00
										 |  |  | 				// NOTE: the target element must be focusable...
 | 
					
						
							|  |  |  | 				var target = | 
					
						
							|  |  |  | 				this.__keyboard_event_source = | 
					
						
							|  |  |  | 					this.config['keyboard-event-source'] == null  | 
					
						
							|  |  |  | 						|| this.config['keyboard-event-source'] == 'viewer' ? this.ribbons.viewer | 
					
						
							|  |  |  | 					: this.config['keyboard-event-source'] == 'window' ? $(window) | 
					
						
							|  |  |  | 					: this.config['keyboard-event-source'] == 'document' ? $(document) | 
					
						
							|  |  |  | 					: $(this.config['keyboard-event-source']) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 				// need to reset...
 | 
					
						
							|  |  |  | 				if(this.__keyboard_handler != null){ | 
					
						
							|  |  |  | 					target.off('keydown', this.__keyboard_handler) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// setup base keyboard for devel, in case something breaks...
 | 
					
						
							|  |  |  | 				// This branch does not drop keys...
 | 
					
						
							|  |  |  | 				if(this.config['max-key-repeat-rate'] < 0  | 
					
						
							|  |  |  | 						|| this.config['max-key-repeat-rate'] == null){ | 
					
						
							|  |  |  | 					//this.ribbons.viewer
 | 
					
						
							|  |  |  | 					var handler =  | 
					
						
							|  |  |  | 					this.__keyboard_handler = | 
					
						
							| 
									
										
										
										
											2016-12-12 15:29:37 +03:00
										 |  |  | 						keyboard.stoppableKeyboardRepeat( | 
					
						
							| 
									
										
										
										
											2016-12-03 14:39:04 +03:00
										 |  |  | 							keyboard.makeKeyboardHandler( | 
					
						
							|  |  |  | 								function(){ return that.__keyboard_config }, | 
					
						
							|  |  |  | 								function(k){ window.DEBUG && console.log('KEY:', k) },  | 
					
						
							|  |  |  | 								this), | 
					
						
							|  |  |  | 							check) | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// drop keys if repeating too fast...
 | 
					
						
							|  |  |  | 				// NOTE: this is done for smoother animations...
 | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					var handler =  | 
					
						
							|  |  |  | 					this.__keyboard_handler = | 
					
						
							| 
									
										
										
										
											2016-12-12 15:29:37 +03:00
										 |  |  | 						keyboard.stoppableKeyboardRepeat( | 
					
						
							| 
									
										
										
										
											2016-12-03 14:39:04 +03:00
										 |  |  | 							keyboard.dropRepeatingkeys( | 
					
						
							|  |  |  | 								keyboard.makeKeyboardHandler( | 
					
						
							|  |  |  | 									function(){ return that.__keyboard_config }, | 
					
						
							|  |  |  | 									function(k){ window.DEBUG && console.log(k) }, | 
					
						
							|  |  |  | 									this),  | 
					
						
							|  |  |  | 								function(){  | 
					
						
							|  |  |  | 									return that.config['max-key-repeat-rate'] | 
					
						
							|  |  |  | 								}), | 
					
						
							|  |  |  | 							check) | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-03 02:55:25 +03:00
										 |  |  | 	// Format:
 | 
					
						
							|  |  |  | 	// 	{
 | 
					
						
							| 
									
										
										
										
											2017-01-05 03:06:06 +03:00
										 |  |  | 	// 		<action>: [
 | 
					
						
							|  |  |  | 	// 			<key>,
 | 
					
						
							| 
									
										
										
										
											2017-01-03 02:55:25 +03:00
										 |  |  | 	// 			...
 | 
					
						
							| 
									
										
										
										
											2017-01-05 03:06:06 +03:00
										 |  |  | 	// 		],
 | 
					
						
							| 
									
										
										
										
											2017-01-03 02:55:25 +03:00
										 |  |  | 	// 		...
 | 
					
						
							|  |  |  | 	// 	}
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2017-01-05 03:06:06 +03:00
										 |  |  | 	// XXX this does not check overloading between modes...
 | 
					
						
							| 
									
										
										
										
											2017-01-03 02:55:25 +03:00
										 |  |  | 	getKeysForAction: ['- Interface/', | 
					
						
							| 
									
										
										
										
											2017-01-05 03:06:06 +03:00
										 |  |  | 		function(actions, modes){ | 
					
						
							|  |  |  | 			actions = actions == '*' ? null : actions | 
					
						
							|  |  |  | 			actions = !actions || actions instanceof Array ? actions : [actions] | 
					
						
							| 
									
										
										
										
											2017-01-03 02:55:25 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 03:06:06 +03:00
										 |  |  | 			modes = modes || null | 
					
						
							|  |  |  | 			modes = !modes || modes instanceof Array ? modes : [modes] | 
					
						
							|  |  |  | 			modes = modes || this.getKeyboardModes() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// XXX does this handle overloading???
 | 
					
						
							| 
									
										
										
										
											2017-01-04 20:27:47 +03:00
										 |  |  | 			var help = keyboard.buildKeybindingsHelp( | 
					
						
							|  |  |  | 				this.keyboard,  | 
					
						
							|  |  |  | 				null,  | 
					
						
							|  |  |  | 				this, | 
					
						
							| 
									
										
										
										
											2017-01-05 03:06:06 +03:00
										 |  |  | 				// get full doc compatible with get path...
 | 
					
						
							|  |  |  | 				function(action, args){ | 
					
						
							|  |  |  | 					// NOTE: we do not care about the actual args 
 | 
					
						
							|  |  |  | 					// 		here, all we need is for this to mismatch
 | 
					
						
							|  |  |  | 					// 		if args exist...
 | 
					
						
							|  |  |  | 					//return args.length == 0 ? Object.keys(this.getPath(action))[0] : '--' })
 | 
					
						
							|  |  |  | 					return args.length == 0 ? action : '--' }) | 
					
						
							| 
									
										
										
										
											2017-01-03 02:55:25 +03:00
										 |  |  | 			var res = {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 03:06:06 +03:00
										 |  |  | 			// build the result...
 | 
					
						
							|  |  |  | 			Object.keys(help) | 
					
						
							|  |  |  | 				// filter modes...
 | 
					
						
							|  |  |  | 				.filter(function(mode){ return modes.indexOf(mode) >= 0 }) | 
					
						
							|  |  |  | 				.forEach(function(mode){ | 
					
						
							|  |  |  | 					Object.keys(help[mode]) | 
					
						
							|  |  |  | 						// keep only the actions given...
 | 
					
						
							|  |  |  | 						.filter(function(action){ | 
					
						
							|  |  |  | 							return action != '--'  | 
					
						
							|  |  |  | 								&& action != 'doc'  | 
					
						
							|  |  |  | 								&& (!actions  | 
					
						
							|  |  |  | 									|| actions.indexOf(action) >= 0) | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 						.forEach(function(action){ | 
					
						
							|  |  |  | 							res[action] = (res[action] || []).concat(help[mode][action]) | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2017-01-03 02:55:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			return res | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// XXX argument #3 is not yet used (see: lib/keyboard.js)...
 | 
					
						
							|  |  |  | 	getKeyboardModes: ['- Interface/', | 
					
						
							|  |  |  | 		function(){ | 
					
						
							| 
									
										
										
										
											2017-01-03 02:59:56 +03:00
										 |  |  | 			return this.__keyboard_event_source ? | 
					
						
							|  |  |  | 				keyboard.getApplicableModes(this.keyboard, null, this.__keyboard_event_source) | 
					
						
							|  |  |  | 	   			: [] }], | 
					
						
							| 
									
										
										
										
											2017-01-03 02:55:25 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-07 04:58:22 +03:00
										 |  |  | 	// XXX need to pre-process the docs...
 | 
					
						
							|  |  |  | 	// 		- remove the path component...
 | 
					
						
							|  |  |  | 	// 		- insert the action name where not doc present...
 | 
					
						
							|  |  |  | 	// XXX cleanup CSS
 | 
					
						
							| 
									
										
										
										
											2016-05-08 19:03:04 +03:00
										 |  |  | 	showKeyboardBindings: ['Interface/Show keyboard bindings...', | 
					
						
							| 
									
										
										
										
											2016-04-30 18:39:14 +03:00
										 |  |  | 		widgets.makeUIDialog('Drawer',  | 
					
						
							|  |  |  | 			function(){ | 
					
						
							| 
									
										
										
										
											2017-01-04 20:27:47 +03:00
										 |  |  | 				return keyboard.buildKeybindingsHelpHTML( | 
					
						
							|  |  |  | 					this.__keyboard_config,  | 
					
						
							|  |  |  | 					this,  | 
					
						
							|  |  |  | 					function(action){ | 
					
						
							|  |  |  | 						return Object.keys(this.getPath(action))[0] }) | 
					
						
							| 
									
										
										
										
											2016-04-30 18:39:14 +03:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				background: 'white', | 
					
						
							|  |  |  | 				focusable: true, | 
					
						
							|  |  |  | 			})], | 
					
						
							| 
									
										
										
										
											2017-01-05 03:06:06 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 05:23:29 +03:00
										 |  |  | 	// XXX Things not to forget: 
 | 
					
						
							|  |  |  | 	// 		* sort modes
 | 
					
						
							|  |  |  | 	// 		* sort actions
 | 
					
						
							|  |  |  | 	// 		* action editor dialog
 | 
					
						
							|  |  |  | 	// 		* mode editor dialog
 | 
					
						
							|  |  |  | 	// 		* add ability to disable key (???)
 | 
					
						
							| 
									
										
										
										
											2017-01-05 23:00:49 +03:00
										 |  |  | 	// 		* ignore flag/list...
 | 
					
						
							| 
									
										
										
										
											2017-01-05 05:40:48 +03:00
										 |  |  | 	// XXX key editor:
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2017-01-05 06:03:46 +03:00
										 |  |  | 	// 		[ mode ]
 | 
					
						
							| 
									
										
										
										
											2017-01-05 05:40:48 +03:00
										 |  |  | 	// 		[  action (text with dataset)  ] [  args (text field)  ] no default: [_]
 | 
					
						
							|  |  |  | 	//		---
 | 
					
						
							|  |  |  | 	//		<list of keys>
 | 
					
						
							|  |  |  | 	//		new
 | 
					
						
							| 
									
										
										
										
											2017-01-05 07:38:56 +03:00
										 |  |  | 	// XXX add view mode (read only)...
 | 
					
						
							|  |  |  | 	// XXX BUG sections with doc do not show up in title...
 | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 	// XXX BUG:
 | 
					
						
							|  |  |  | 	// 		ig.bindKey('Global', 'X', 'editKeyboardBindings')
 | 
					
						
							|  |  |  | 	// 		ig.editKeyboardBindings()
 | 
					
						
							|  |  |  | 	// 			-> shows alt-X instead of X
 | 
					
						
							|  |  |  | 	// 		ig.bindKey('Global', 'X', 'editKeyboardBindings')
 | 
					
						
							|  |  |  | 	// 		ig.editKeyboardBindings()
 | 
					
						
							|  |  |  | 	// 			-> shows two keys ctrl-Z and ctrl-shift-Z instead of Z
 | 
					
						
							| 
									
										
										
										
											2017-01-05 23:00:49 +03:00
										 |  |  | 	browseKeyboardBindings: ['Interface/Keyboard bindings...', | 
					
						
							|  |  |  | 		widgets.makeUIDialog(function(path, edit){ | 
					
						
							| 
									
										
										
										
											2017-01-05 04:53:46 +03:00
										 |  |  | 			var actions = this | 
					
						
							| 
									
										
										
										
											2017-01-05 03:06:06 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// Format:
 | 
					
						
							|  |  |  | 			// 	{
 | 
					
						
							|  |  |  | 			// 		<mode>: {
 | 
					
						
							|  |  |  | 			// 			<action-code>: [ <key>, ... ],
 | 
					
						
							|  |  |  | 			// 			...
 | 
					
						
							|  |  |  | 			// 		},
 | 
					
						
							|  |  |  | 			// 		...
 | 
					
						
							|  |  |  | 			// 	}
 | 
					
						
							|  |  |  | 			var keys = keyboard.buildKeybindingsHelp( | 
					
						
							|  |  |  | 				this.keyboard,  | 
					
						
							|  |  |  | 				null,  | 
					
						
							|  |  |  | 				this, | 
					
						
							|  |  |  | 				// get full doc compatible with get path...
 | 
					
						
							|  |  |  | 				function(action, args, no_default, doc){ | 
					
						
							|  |  |  | 					return action | 
					
						
							|  |  |  | 						+ (no_default ? '!' : '') | 
					
						
							|  |  |  | 						+ (args.length > 0 ? | 
					
						
							|  |  |  | 							': '+ args.map(JSON.stringify).join(' ') | 
					
						
							|  |  |  | 							: '')  | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 04:53:46 +03:00
										 |  |  | 			var dialog = browse.makeLister(null,  | 
					
						
							|  |  |  | 				function(path, make){ | 
					
						
							|  |  |  | 					Object.keys(keys) | 
					
						
							|  |  |  | 						.forEach(function(mode){ | 
					
						
							| 
									
										
										
										
											2017-01-05 23:00:49 +03:00
										 |  |  | 							var ignored = actions.keyboard[mode].ignore || [] | 
					
						
							| 
									
										
										
										
											2017-01-06 02:18:21 +03:00
										 |  |  | 							var bound_ignored = [] | 
					
						
							| 
									
										
										
										
											2017-01-05 23:00:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 04:53:46 +03:00
										 |  |  | 							// section heading...
 | 
					
						
							|  |  |  | 							make(keys[mode].doc ?  | 
					
						
							|  |  |  | 									$('<span>') | 
					
						
							|  |  |  | 										// NOTE: at this time adding a br
 | 
					
						
							|  |  |  | 										// 		is faster and simpler than
 | 
					
						
							|  |  |  | 										// 		doing this in CSS...
 | 
					
						
							|  |  |  | 										// XXX revise...
 | 
					
						
							|  |  |  | 										.html(mode + '<br>') | 
					
						
							|  |  |  | 										.append($('<span>') | 
					
						
							|  |  |  | 											.addClass('doc') | 
					
						
							|  |  |  | 											.html(keys[mode].doc)) | 
					
						
							| 
									
										
										
										
											2017-01-06 02:18:21 +03:00
										 |  |  | 									: mode,  | 
					
						
							|  |  |  | 									{  | 
					
						
							|  |  |  | 										not_filtered_out: true, | 
					
						
							|  |  |  | 										// XXX should sections be searchable???
 | 
					
						
							|  |  |  | 										//not_searchable: true,
 | 
					
						
							|  |  |  | 									}) | 
					
						
							|  |  |  | 								.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 | 
					
						
							|  |  |  | 							Object.keys(keys[mode]).forEach(function(action){ | 
					
						
							|  |  |  | 								action != 'doc'  | 
					
						
							|  |  |  | 									// NOTE: wee need the button spec to be
 | 
					
						
							|  |  |  | 									// 		searchable, thus we are not using 
 | 
					
						
							|  |  |  | 									// 		the keys attr as in .browseActions(..)
 | 
					
						
							|  |  |  | 									&& make([action, ' ', '$BUTTONS'] | 
					
						
							|  |  |  | 											.concat($('<span>') | 
					
						
							|  |  |  | 												.addClass('text') | 
					
						
							|  |  |  | 												.html(keys[mode][action] | 
					
						
							| 
									
										
										
										
											2017-01-05 23:00:49 +03:00
										 |  |  | 													// mark key if it is in ignored...
 | 
					
						
							|  |  |  | 													.map(function(s){  | 
					
						
							|  |  |  | 														s = s.split('+') | 
					
						
							|  |  |  | 														var k = s.pop()  | 
					
						
							| 
									
										
										
										
											2017-01-06 02:18:21 +03:00
										 |  |  | 														var i = ignored.indexOf(k) | 
					
						
							|  |  |  | 														i >= 0  | 
					
						
							|  |  |  | 															&& bound_ignored | 
					
						
							|  |  |  | 																.push(ignored[i]) | 
					
						
							| 
									
										
										
										
											2017-01-05 23:00:49 +03:00
										 |  |  | 														s.push(k  | 
					
						
							| 
									
										
										
										
											2017-01-06 02:18:21 +03:00
										 |  |  | 															+ (i >= 0 ?  '<sup>*</sup>' : '')) | 
					
						
							|  |  |  | 														return s.join('+') }) | 
					
						
							|  |  |  | 													.join(' / ')))) | 
					
						
							|  |  |  | 										.addClass('key ' | 
					
						
							|  |  |  | 											+ (action == 'IGNORE' ? 'ignored' : '')) | 
					
						
							|  |  |  | 									&& c++ | 
					
						
							|  |  |  | 							}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							// no keys in view mode...
 | 
					
						
							|  |  |  | 							// XXX is adding info stuff like this a correct 
 | 
					
						
							|  |  |  | 							// 		thing to do in code?
 | 
					
						
							|  |  |  | 							c == 0 && !edit  | 
					
						
							|  |  |  | 								&& make('No bindings...',  | 
					
						
							|  |  |  | 									{ | 
					
						
							|  |  |  | 										disabled: true, | 
					
						
							|  |  |  | 										hide_on_search: true, | 
					
						
							|  |  |  | 									}) | 
					
						
							|  |  |  | 									.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', | 
					
						
							|  |  |  | 									ignored | 
					
						
							|  |  |  | 										.filter(function(k){  | 
					
						
							|  |  |  | 											return bound_ignored.indexOf(k) == -1 }) | 
					
						
							|  |  |  | 										.join(' / ')]) | 
					
						
							|  |  |  | 								.addClass('ignore-list') | 
					
						
							| 
									
										
										
										
											2017-01-05 04:53:46 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 23:00:49 +03:00
										 |  |  | 							// controls...
 | 
					
						
							|  |  |  | 							if(edit){ | 
					
						
							|  |  |  | 								var elem = make('new', { | 
					
						
							|  |  |  | 									buttons: [ | 
					
						
							|  |  |  | 										// XXX
 | 
					
						
							|  |  |  | 										['key',  | 
					
						
							|  |  |  | 											function(){ | 
					
						
							|  |  |  | 												//elem.before( XXX )
 | 
					
						
							|  |  |  | 											}], | 
					
						
							|  |  |  | 										// XXX
 | 
					
						
							|  |  |  | 										['mode',  | 
					
						
							|  |  |  | 											function(){ | 
					
						
							|  |  |  | 												//elem.after( XXX )
 | 
					
						
							|  |  |  | 											}], | 
					
						
							|  |  |  | 									]}) | 
					
						
							|  |  |  | 									.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-05 04:53:46 +03:00
										 |  |  | 				}, { | 
					
						
							| 
									
										
										
										
											2017-01-05 23:00:49 +03:00
										 |  |  | 					cls: [ | 
					
						
							|  |  |  | 						'key-bindings', | 
					
						
							|  |  |  | 						'no-item-numbers', | 
					
						
							|  |  |  | 						(edit ? 'edit' : 'browse'), | 
					
						
							|  |  |  | 					].join(' '), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					itemButtons: edit ? | 
					
						
							|  |  |  | 					   	[ | 
					
						
							|  |  |  | 							// NOTE: ordering within one section is purely 
 | 
					
						
							|  |  |  | 							// 		aesthetic and has no function...
 | 
					
						
							|  |  |  | 							// XXX do wee actually need ordering???
 | 
					
						
							|  |  |  | 							// XXX up
 | 
					
						
							|  |  |  | 							//['⏶', function(){}],
 | 
					
						
							|  |  |  | 							// XXX down
 | 
					
						
							|  |  |  | 							//['⏷', function(){}],
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							// XXX edit -- launch the editor...
 | 
					
						
							|  |  |  | 							['⋯', function(){}], | 
					
						
							|  |  |  | 							//['edit', function(){}],
 | 
					
						
							|  |  |  | 							//['🖉', function(){}],
 | 
					
						
							|  |  |  | 						] | 
					
						
							|  |  |  | 						: [], | 
					
						
							| 
									
										
										
										
											2017-01-05 04:53:46 +03:00
										 |  |  | 				}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return dialog | 
					
						
							| 
									
										
										
										
											2017-01-05 03:06:06 +03:00
										 |  |  | 		})], | 
					
						
							| 
									
										
										
										
											2017-01-05 23:00:49 +03:00
										 |  |  | 	// XXX place this in /Doc/.. (???)
 | 
					
						
							|  |  |  | 	editKeyboardBindings: ['Interface/Keyboard bindings editor...', | 
					
						
							|  |  |  | 		widgets.uiDialog(function(path){  | 
					
						
							|  |  |  | 			return this.browseKeyboardBindings(path, true) })], | 
					
						
							| 
									
										
										
										
											2017-01-05 05:23:29 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// XXX
 | 
					
						
							|  |  |  | 	resetKeyBindings: ['Interface/Restore default key bindings', | 
					
						
							| 
									
										
										
										
											2017-01-05 23:00:49 +03:00
										 |  |  | 		function(){  | 
					
						
							| 
									
										
										
										
											2017-01-09 03:51:32 +03:00
										 |  |  | 			thiis.__keyboard_config = GLOBAL_KEYBOARD }], | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// XXX do we look for aliases in this mode only or in all modes?
 | 
					
						
							|  |  |  | 	getKeyHandler: ['- Interface/', | 
					
						
							|  |  |  | 		function(modes, key, action){ | 
					
						
							| 
									
										
										
										
											2017-01-08 03:32:49 +03:00
										 |  |  | 			var that = this | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// XXX normalize key...
 | 
					
						
							|  |  |  | 			var full_key = key | 
					
						
							|  |  |  | 			var modifiers = key.split('+') | 
					
						
							|  |  |  | 			key = modifiers.pop() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var code = keyboard.toKeyCode(key) | 
					
						
							|  |  |  | 			var args = [].slice.call(arguments).slice(3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// set handler...
 | 
					
						
							|  |  |  | 			if(action){ | 
					
						
							|  |  |  | 				modes = modes instanceof Array ? modes : [modes] | 
					
						
							|  |  |  | 				// ignore all but the first mode...
 | 
					
						
							|  |  |  | 				modes = modes.slice(0, 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// get handler...
 | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				var shift_key = (modifiers.indexOf('shift') >= 0 ?  | 
					
						
							|  |  |  | 						keyboard._SHIFT_KEYS[key] | 
					
						
							|  |  |  | 						: keyboard._UNSHIFT_KEYS[key]) | 
					
						
							|  |  |  | 					|| ''  | 
					
						
							|  |  |  | 				var shift_modifiers = shift_key != ''  | 
					
						
							|  |  |  | 					&& (((modifiers.indexOf('shift') >= 0 ? | 
					
						
							|  |  |  | 						modifiers.filter(function(k){ return k != 'shift' }) | 
					
						
							|  |  |  | 						: modifiers.concat(['shift']))) | 
					
						
							|  |  |  | 					|| modifiers).join('+') | 
					
						
							|  |  |  | 				var full_shift_key = shift_modifiers == '' ?  | 
					
						
							|  |  |  | 					shift_key  | 
					
						
							|  |  |  | 					: shift_modifiers +'+'+ shift_key | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				var any = modes == 'any' | 
					
						
							|  |  |  | 				modes = any ? this.getKeyboardModes() | 
					
						
							|  |  |  | 					: modes == '*' ? Object.keys(this.keyboard)  | 
					
						
							|  |  |  | 					: modes | 
					
						
							|  |  |  | 				modes = modes instanceof Array ? modes : [modes] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// filter modes...
 | 
					
						
							|  |  |  | 				var ignore = false | 
					
						
							|  |  |  | 				modes = any ?  | 
					
						
							|  |  |  | 					modes | 
					
						
							|  |  |  | 						.filter(function(mode){ | 
					
						
							|  |  |  | 							if(ignore){ | 
					
						
							|  |  |  | 								return false | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							var i = that.keyboard[mode].ignore || [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							ignore = i.indexOf(full_key) >= 0 | 
					
						
							|  |  |  | 								|| i.indexOf(key) >= 0 | 
					
						
							|  |  |  | 								|| i.indexOf(shift_key) >= 0 | 
					
						
							|  |  |  | 								|| i.indexOf(full_shift_key) >= 0 | 
					
						
							|  |  |  | 								|| i.indexOf(code) >= 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							return true | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 					: modes | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			modifiers = modifiers.join('+') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// search modes...
 | 
					
						
							|  |  |  | 			var res = {} | 
					
						
							|  |  |  | 			ignore = false | 
					
						
							|  |  |  | 			modes | 
					
						
							|  |  |  | 				.forEach(function(mode){ | 
					
						
							|  |  |  | 					if(ignore){ | 
					
						
							|  |  |  | 						return false | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					var bindings = that.keyboard[mode] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if(action){ | 
					
						
							|  |  |  | 						var match = 'direct' | 
					
						
							|  |  |  | 						var alias = code in bindings ? code : key | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						// direct match...
 | 
					
						
							|  |  |  | 						var match = 'direct' | 
					
						
							|  |  |  | 						var alias = full_key in bindings ? full_key  | 
					
						
							|  |  |  | 							: key in bindings ? key  | 
					
						
							|  |  |  | 							: null | 
					
						
							|  |  |  | 						// shift key match...
 | 
					
						
							|  |  |  | 						match = alias == null ? 'shifted' : match | 
					
						
							|  |  |  | 						alias = alias == null ?  | 
					
						
							|  |  |  | 							(full_shift_key in bindings ? full_shift_key  | 
					
						
							|  |  |  | 								: shift_key in bindings ? shift_key  | 
					
						
							|  |  |  | 								: null) | 
					
						
							|  |  |  | 							: alias | 
					
						
							|  |  |  | 						// code match...
 | 
					
						
							|  |  |  | 						match = alias == null ? 'code' : match | 
					
						
							|  |  |  | 						alias = alias == null ?  | 
					
						
							|  |  |  | 							(code in bindings ? code : null) | 
					
						
							|  |  |  | 							: alias | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					var mod = (match == 'code' || match == 'direct') ?  | 
					
						
							|  |  |  | 						modifiers  | 
					
						
							|  |  |  | 						: shift_modifiers | 
					
						
							|  |  |  | 					mod = mod == '' ? 'default' : mod | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					var handler = alias | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// spin through aliases...
 | 
					
						
							|  |  |  | 					// XXX do we look for aliases in this mode only or in all modes?
 | 
					
						
							|  |  |  | 					var seen = [] | 
					
						
							|  |  |  | 					while(handler in bindings){ | 
					
						
							|  |  |  | 						// handler loop...
 | 
					
						
							|  |  |  | 						if(seen.indexOf(handler) >= 0){ | 
					
						
							|  |  |  | 							return null | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						 | 
					
						
							|  |  |  | 						alias = handler | 
					
						
							|  |  |  | 						handler = bindings[alias] | 
					
						
							|  |  |  | 						seen.push(alias) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						// go into the map structure...
 | 
					
						
							|  |  |  | 						if(!action && typeof(handler) != typeof('str')){ | 
					
						
							|  |  |  | 							handler = handler[mod] | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// set the action...
 | 
					
						
							|  |  |  | 					if(action){ | 
					
						
							|  |  |  | 						if(handler == null || typeof(handler) == typeof('str')){ | 
					
						
							|  |  |  | 							bindings[alias] = modifiers.length == 0 ? | 
					
						
							|  |  |  | 								action | 
					
						
							|  |  |  | 								: { modifiers : action } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						} else if(modifiers.length == 0){ | 
					
						
							|  |  |  | 							handler['default'] = action | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							handler[modifiers] = action | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// get the action...
 | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						if(handler){ | 
					
						
							|  |  |  | 							res[mode] = handler | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						ignore = any && handler == 'IGNORE' | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return !action ?  | 
					
						
							|  |  |  | 				(modes.length == 1 ? res[modes[0]] : res) || null | 
					
						
							|  |  |  | 				: undefined | 
					
						
							| 
									
										
										
										
											2017-01-07 04:22:53 +03:00
										 |  |  | 		}], | 
					
						
							|  |  |  | 	// XXX move this to lib/keyboard.js
 | 
					
						
							|  |  |  | 	// XXX not done yet...
 | 
					
						
							|  |  |  | 	bindKey: ['- Interface/', | 
					
						
							|  |  |  | 		function(mode, key, action){ | 
					
						
							|  |  |  | 			var modifiers = key.split('+') | 
					
						
							|  |  |  | 			key = modifiers.pop() | 
					
						
							|  |  |  | 			modifiers = modifiers.join('+') | 
					
						
							|  |  |  | 			var code = keyboard.toKeyCode(key) | 
					
						
							|  |  |  | 			var args = [].slice.call(arguments).slice(3) | 
					
						
							|  |  |  | 			action = action  | 
					
						
							|  |  |  | 					+ (args.length > 0 ?  | 
					
						
							|  |  |  | 						': '+ args.map(JSON.stringify).join(' ') | 
					
						
							|  |  |  | 						: '') | 
					
						
							|  |  |  | 			var bindings = this.keyboard[mode] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var alias = code in bindings ? code : key | 
					
						
							|  |  |  | 			var handler = bindings[key] || bindings[code] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// spin through aliases...
 | 
					
						
							|  |  |  | 			var seen = [] | 
					
						
							|  |  |  | 			while(handler in bindings){ | 
					
						
							|  |  |  | 				// handler loop...
 | 
					
						
							|  |  |  | 				if(seen.indexOf(handler) >= 0){ | 
					
						
							|  |  |  | 					return null | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				alias = handler | 
					
						
							|  |  |  | 				handler = bindings[alias] | 
					
						
							|  |  |  | 				seen.push(alias) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(handler == null || typeof(handler) == typeof('str')){ | 
					
						
							|  |  |  | 				bindings[alias] = modifiers.length == 0 ? | 
					
						
							|  |  |  | 					action | 
					
						
							|  |  |  | 					: { modifiers : action } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			} else if(modifiers.length == 0){ | 
					
						
							|  |  |  | 				handler['default'] = action | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				handler[modifiers] = action | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}], | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var Keyboard =  | 
					
						
							|  |  |  | module.Keyboard = core.ImageGridFeatures.Feature({ | 
					
						
							|  |  |  | 	title: '', | 
					
						
							|  |  |  | 	doc: '', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tag: 'keyboard', | 
					
						
							|  |  |  | 	depends: [ | 
					
						
							|  |  |  | 		'ui' | 
					
						
							|  |  |  | 	], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	actions: KeyboardActions,  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	handlers: [ | 
					
						
							|  |  |  | 		['start', | 
					
						
							|  |  |  | 			function(){ | 
					
						
							|  |  |  | 				var that = this | 
					
						
							|  |  |  | 				this.__keyboard_config = this.keyboard || GLOBAL_KEYBOARD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				this.toggleKeyboardHandling('on') | 
					
						
							| 
									
										
										
										
											2016-12-03 14:39:04 +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() | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}], | 
					
						
							| 
									
										
										
										
											2016-04-02 17:34:25 +03:00
										 |  |  | 	], | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							| 
									
										
										
										
											2016-08-20 22:49:36 +03:00
										 |  |  | * vim:set ts=4 sw=4 :                               */ return module }) |