mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-11-04 05:10:07 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			407 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			407 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
/**********************************************************************
 | 
						|
* 
 | 
						|
*
 | 
						|
*
 | 
						|
**********************************************************************/
 | 
						|
 | 
						|
//var DEBUG = DEBUG != null ? DEBUG : true
 | 
						|
 | 
						|
var STEPS_TO_CHANGE_DIRECTION = 2
 | 
						|
var _STEPS_LEFT_TO_CHANGE_DIRECTION = STEPS_TO_CHANGE_DIRECTION
 | 
						|
// XXX code related to this needs testing...
 | 
						|
var DIRECTION = 'next'
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*********************************************************************/
 | 
						|
 | 
						|
var KEYBOARD_CONFIG = {
 | 
						|
	// info overlay...
 | 
						|
	//
 | 
						|
	// NOTE: this is here to prevent selecting images while trying to 
 | 
						|
	// 		select info text...
 | 
						|
	'.overlay-info:hover': {
 | 
						|
		title: 'Info overlay',
 | 
						|
		doc: 'NOTE: when the cursor is over the info overlay one can use '+
 | 
						|
			'Ctrl-A and Ctrl-D for info text selection, without affecting '+
 | 
						|
			'image selection/marks.',
 | 
						|
		ignore: [ 'A' ],
 | 
						|
		A: {
 | 
						|
			// NOTE: this is here only for documentation...
 | 
						|
			ctrl: doc('Select all'),
 | 
						|
		},
 | 
						|
		D: {
 | 
						|
			ctrl: doc('Clear selection', 
 | 
						|
				function(){
 | 
						|
					document.getSelection().empty()
 | 
						|
					return false
 | 
						|
				})
 | 
						|
		}
 | 
						|
	},
 | 
						|
 | 
						|
 | 
						|
	// help mode...
 | 
						|
	//
 | 
						|
	// NOTE: need to keep all info modes before the rest so as to give 
 | 
						|
	// 		their bindings priority...
 | 
						|
	'.help-mode': {
 | 
						|
		title: 'Help',
 | 
						|
		doc: 'NOTE: In this mode all other key bindings are disabled, except '+
 | 
						|
			'the ones explicitly defined here.',
 | 
						|
		ignore: '*',
 | 
						|
 | 
						|
		Esc: doc('Close help',
 | 
						|
			function(){ 
 | 
						|
				toggleKeyboardHelp('off') 
 | 
						|
				return false
 | 
						|
			}),
 | 
						|
		H: 'Esc',
 | 
						|
		Q: 'Esc',
 | 
						|
		'?': 'Esc',
 | 
						|
	},
 | 
						|
 | 
						|
 | 
						|
	// single image mode...
 | 
						|
	//
 | 
						|
	'.single-image-mode': {
 | 
						|
		title: 'Single image mode',
 | 
						|
 | 
						|
		// XXX this should only work on single image mode...
 | 
						|
		F: doc('Toggle view proportions', 
 | 
						|
			function(){ 
 | 
						|
				toggleImageProportions() 
 | 
						|
				centerRibbons()
 | 
						|
			}),
 | 
						|
		Esc: doc('Exit single image mode', 
 | 
						|
				function(){ 
 | 
						|
					toggleSingleImageMode('off') 
 | 
						|
					return false
 | 
						|
				}),
 | 
						|
		Q: 'Esc',
 | 
						|
	},
 | 
						|
 | 
						|
 | 
						|
	// marked only ribbon mode...
 | 
						|
	//
 | 
						|
	'.marked-only-view:not(.single-image-mode)': {
 | 
						|
		title: 'Marked only view',
 | 
						|
 | 
						|
		Esc: doc('Exit marked only view', 
 | 
						|
				function(){ 
 | 
						|
					toggleMarkedOnlyView('off') 
 | 
						|
					return false
 | 
						|
				}),
 | 
						|
		Q: 'Esc',
 | 
						|
	},
 | 
						|
 | 
						|
 | 
						|
	// general setup...
 | 
						|
	//
 | 
						|
	'.viewer:not(.overlay)': {
 | 
						|
		title: 'Global',
 | 
						|
		doc: 'These key bindings work in most other modes.',
 | 
						|
 | 
						|
		// Navigation...
 | 
						|
		// XXX need to cancel the animation of the prev action...
 | 
						|
		Left: {
 | 
						|
				default: doc('Previous image',
 | 
						|
					function(){ 
 | 
						|
						event.preventDefault()
 | 
						|
						// update direction...
 | 
						|
						if(DIRECTION != 'prev'){
 | 
						|
							_STEPS_LEFT_TO_CHANGE_DIRECTION--
 | 
						|
							if(_STEPS_LEFT_TO_CHANGE_DIRECTION == 0){
 | 
						|
								DIRECTION = 'prev'
 | 
						|
								_STEPS_LEFT_TO_CHANGE_DIRECTION = 2
 | 
						|
							}
 | 
						|
						} else {
 | 
						|
								_STEPS_LEFT_TO_CHANGE_DIRECTION = 2
 | 
						|
						}
 | 
						|
						prevImage() 
 | 
						|
						centerRibbons()
 | 
						|
					}),
 | 
						|
				ctrl: doc('Previous screen',
 | 
						|
					function(){ 
 | 
						|
						event.preventDefault()
 | 
						|
						prevScreenImages()
 | 
						|
						centerRibbons()
 | 
						|
					}),
 | 
						|
			},
 | 
						|
		Right: {
 | 
						|
				default: doc('Next image',
 | 
						|
					function(){ 
 | 
						|
						event.preventDefault()
 | 
						|
						// update direction...
 | 
						|
						if(DIRECTION != 'next'){
 | 
						|
							_STEPS_LEFT_TO_CHANGE_DIRECTION--
 | 
						|
							if(_STEPS_LEFT_TO_CHANGE_DIRECTION == 0){
 | 
						|
								DIRECTION = 'next'
 | 
						|
								_STEPS_LEFT_TO_CHANGE_DIRECTION = 2
 | 
						|
							}
 | 
						|
						} else {
 | 
						|
								_STEPS_LEFT_TO_CHANGE_DIRECTION = 2
 | 
						|
						}
 | 
						|
						nextImage() 
 | 
						|
						centerRibbons()
 | 
						|
					}),
 | 
						|
				ctrl: doc('Previous screen',
 | 
						|
					function(){ 
 | 
						|
						event.preventDefault()
 | 
						|
						nextScreenImages()
 | 
						|
						centerRibbons()
 | 
						|
					}),
 | 
						|
			},
 | 
						|
		Space: {
 | 
						|
				default: 'Right',
 | 
						|
				shift: 'Left',
 | 
						|
				// screen-oriented movement...
 | 
						|
				ctrl: 'Right',
 | 
						|
				'ctrl+shift': 'Left',
 | 
						|
			},
 | 
						|
		Backspace: {
 | 
						|
				default: 'Left',
 | 
						|
				shift: 'Right',
 | 
						|
			},
 | 
						|
		Home: doc('First image', 
 | 
						|
			function(){
 | 
						|
				event.preventDefault()
 | 
						|
				firstImage()
 | 
						|
				centerRibbons()
 | 
						|
			}),
 | 
						|
		End: doc('Last image',
 | 
						|
			function(){
 | 
						|
				event.preventDefault()
 | 
						|
				lastImage()
 | 
						|
				centerRibbons()
 | 
						|
			}),
 | 
						|
 | 
						|
 | 
						|
		// combined navigation and editor actions...
 | 
						|
		Up: {
 | 
						|
				default: doc('Go to ribbon above', 
 | 
						|
					function(){ 
 | 
						|
						event.preventDefault()
 | 
						|
						prevRibbon() 
 | 
						|
						centerRibbons()
 | 
						|
					}),
 | 
						|
				shift: doc('Shift image up',
 | 
						|
					function(){ 
 | 
						|
						event.preventDefault()
 | 
						|
						shiftImageUp(null, DIRECTION) 
 | 
						|
						centerRibbons()
 | 
						|
					}),
 | 
						|
				'ctrl+shift': doc('Shift image up to empty ribbon',
 | 
						|
					function(){
 | 
						|
						event.preventDefault()
 | 
						|
						shiftImageUpNewRibbon(null, DIRECTION) 
 | 
						|
						centerRibbons()
 | 
						|
					}),
 | 
						|
			},
 | 
						|
		Down: {
 | 
						|
				default: doc('Go to ribbon below', 
 | 
						|
					function(){
 | 
						|
						event.preventDefault()
 | 
						|
						nextRibbon() 
 | 
						|
						centerRibbons()
 | 
						|
					}),
 | 
						|
				shift: doc('Shift image down',
 | 
						|
					function(){ 
 | 
						|
						event.preventDefault()
 | 
						|
						shiftImageDown(null, DIRECTION) 
 | 
						|
						centerRibbons()
 | 
						|
					}),
 | 
						|
				'ctrl+shift': doc('Shift image down to empty ribbon',
 | 
						|
					function(){
 | 
						|
						event.preventDefault()
 | 
						|
						shiftImageDownNewRibbon(null, DIRECTION) 
 | 
						|
						centerRibbons()
 | 
						|
					}),
 | 
						|
			},
 | 
						|
 | 
						|
		L: doc('Rotate image left', function(){ rotateLeft() }),
 | 
						|
		R: doc('Rotate image right', function(){ rotateRight() }),
 | 
						|
 | 
						|
 | 
						|
		// zooming...
 | 
						|
		'#1': doc('Fit one image', function(){ fitNImages(1) }),
 | 
						|
		'#2': doc('Fit two images', function(){ fitNImages(2) }),
 | 
						|
		'#3': doc('Fit three images', function(){ fitNImages(3) }),
 | 
						|
		'#4': doc('Fit four images', function(){ fitNImages(4) }),
 | 
						|
		'#5': doc('Fit five images', function(){ fitNImages(5) }),
 | 
						|
		'#6': doc('Fit six images', function(){ fitNImages(6) }),
 | 
						|
		'#7': doc('Fit seven images', function(){ fitNImages(7) }),
 | 
						|
		'#8': doc('Fit eight images', function(){ fitNImages(8) }),
 | 
						|
		'#9': doc('Fit nine images', function(){ fitNImages(9) }),
 | 
						|
 | 
						|
		'-': doc('Zoom in', function(){ zoomOut() }),
 | 
						|
		'=': doc('Zoom out', function(){ zoomIn() }),
 | 
						|
 | 
						|
 | 
						|
		Enter: doc('Toggle single image view', 
 | 
						|
				function(){ toggleSingleImageMode() }),
 | 
						|
 | 
						|
		B: doc('Toggle theme', function(){ toggleTheme() }),
 | 
						|
 | 
						|
		S: {
 | 
						|
				ctrl: doc('Save current state', 
 | 
						|
					function(){
 | 
						|
						event.preventDefault()
 | 
						|
						//saveLocalStorage()
 | 
						|
						saveLocalStorageData()
 | 
						|
						saveLocalStorageMarks()
 | 
						|
 | 
						|
						saveLocalStorageSettings()
 | 
						|
 | 
						|
						saveFileState()
 | 
						|
					})
 | 
						|
			},
 | 
						|
		Z: {
 | 
						|
				ctrl: doc('Restore to last saved state', 
 | 
						|
					function(){
 | 
						|
						loadLocalStorage()
 | 
						|
						loadLocalStorageMarks()
 | 
						|
					})
 | 
						|
			},
 | 
						|
 | 
						|
 | 
						|
		// marking...
 | 
						|
		// XXX not final, think of a better way to do this...
 | 
						|
		// XXX need mark navigation...
 | 
						|
		// XXX need marked image shift up/down actions...
 | 
						|
		// XXX unmarking an image in marked-only mode results in nothing
 | 
						|
		// 		visible focused if we unmark the first or last image in 
 | 
						|
		// 		the ribbon...
 | 
						|
		M: {
 | 
						|
				// NOTE: marking moves in the same direction as the last
 | 
						|
				//		move...
 | 
						|
				//		i.e. marking can change direction depending on where
 | 
						|
				//		we moved last...
 | 
						|
				// NOTE: marking does not change move direction...
 | 
						|
				default: doc('Mark current image and advance',
 | 
						|
					function(){ 
 | 
						|
						toggleImageMark()
 | 
						|
						if(DIRECTION == 'next'){
 | 
						|
							nextImage()
 | 
						|
						} else {
 | 
						|
							prevImage()
 | 
						|
						}
 | 
						|
						if(getImage().filter(':visible').length == 0){
 | 
						|
							centerView(focusImage(getImageBefore()))
 | 
						|
						}
 | 
						|
						centerRibbons()
 | 
						|
					}),
 | 
						|
				// same as default but in reverse direction...
 | 
						|
				shift: doc('Mark current image and return',
 | 
						|
					function(){
 | 
						|
						toggleImageMark()
 | 
						|
						if(DIRECTION == 'prev'){
 | 
						|
							nextImage()
 | 
						|
						} else {
 | 
						|
							prevImage()
 | 
						|
						}
 | 
						|
						if(getImage().filter(':visible').length == 0){
 | 
						|
							centerView(focusImage(getImageBefore()))
 | 
						|
						} 
 | 
						|
						centerRibbons()
 | 
						|
					}),
 | 
						|
				ctrl: doc('Mark current image',
 | 
						|
					function(){ 
 | 
						|
						var action = toggleImageMark() 
 | 
						|
					}),
 | 
						|
			},
 | 
						|
		I: {
 | 
						|
				// XXX group this with other info stuff into a single on/off toggle...
 | 
						|
				default: doc('Toggle image info display',
 | 
						|
					function(){ toggleImageInfo() }),
 | 
						|
				// XXX STUB -- replace with a real info window...
 | 
						|
				shift: doc('Show current image info',
 | 
						|
					function(){
 | 
						|
						var gid = getImageGID(getImage())
 | 
						|
						var r = getRibbonIndex(getRibbon())
 | 
						|
						var data = IMAGES[gid]
 | 
						|
						var orientation = data.orientation
 | 
						|
						orientation = orientation == null ? 0 : orientation
 | 
						|
						var order = DATA.order.indexOf(gid)
 | 
						|
						var name = data.path.split('/').pop()
 | 
						|
						alert('"'+ name +'"\n'+
 | 
						|
								'Orientation: '+ orientation +'deg\n'+
 | 
						|
								'GID: '+ gid +'\n'+
 | 
						|
								'Path: "'+ data.path +'"\n'+
 | 
						|
								'Order: '+ order +'\n'+
 | 
						|
								'Position (ribbon): '+ DATA.ribbons[r].indexOf(gid) +
 | 
						|
									'/'+ DATA.ribbons[r].length +'\n'+
 | 
						|
								'Position (global): '+ order +'/'+ DATA.order.length +'\n'+
 | 
						|
								'')
 | 
						|
					}),
 | 
						|
				alt: doc('Toggle inline image info display',
 | 
						|
					function(){
 | 
						|
						toggleInlineImageInfo()
 | 
						|
					}),
 | 
						|
 | 
						|
				// marking...
 | 
						|
				ctrl: doc('Invert image marks', 
 | 
						|
					function(){ invertImageMarks() }),
 | 
						|
			},
 | 
						|
		A: {
 | 
						|
			  	// XXX does not yet work with DATA (???)
 | 
						|
				//shift: doc('Toggle marks in current contagious block', 
 | 
						|
				//	function(){ toggleImageMarkBlock() }),
 | 
						|
 | 
						|
				ctrl: doc('Mark current ribbon', 
 | 
						|
					function(){ markAll('ribbon') }),
 | 
						|
				'ctrl+shift': doc('Mark all images', 
 | 
						|
					function(){ markAll('all') }),
 | 
						|
			},
 | 
						|
		D: {
 | 
						|
				ctrl: doc('Unmark current ribbon', 
 | 
						|
					function(){ removeImageMarks('ribbon') }),
 | 
						|
				'ctrl+shift': doc('Unmark all images', 
 | 
						|
					function(){ removeImageMarks('all') }),
 | 
						|
			},
 | 
						|
		U: {
 | 
						|
				ctrl: doc('Unmark current ribbon', 
 | 
						|
					function(){ removeImageMarks('ribbon') }),
 | 
						|
				shift: doc('Unamrk all', 
 | 
						|
					function(){ removeImageMarks('all') }),
 | 
						|
			},
 | 
						|
		F2: {
 | 
						|
				default: doc('Toggle mark visibility', 
 | 
						|
					function(){ toggleMarkesView() }),
 | 
						|
				shift: doc('Toggle marked only images view', 
 | 
						|
					function(){
 | 
						|
						toggleMarkedOnlyView()
 | 
						|
					})
 | 
						|
			},
 | 
						|
 | 
						|
		F4: doc('Open image in external software', openImage),
 | 
						|
		E: 'F4',
 | 
						|
 | 
						|
		'?': doc('Show keyboard bindings',
 | 
						|
			function(){ toggleKeyboardHelp() }),
 | 
						|
		H: '?',
 | 
						|
 | 
						|
 | 
						|
		/* testing the shift-key feature...
 | 
						|
		'~': {
 | 
						|
			default: function(){ alert('~') },
 | 
						|
			// this is inaccessible...
 | 
						|
			shift: function(){ alert('shift-~') },
 | 
						|
			ctrl: function(){ alert('ctrl-~') },
 | 
						|
			'ctrl+alt': function(){ alert('ctrl-alt-~') },
 | 
						|
		},
 | 
						|
		'`': {
 | 
						|
			default: function(){ alert('`') },
 | 
						|
			// this is also not accessible as it is shadowed by '''...
 | 
						|
			shift: function(){ alert('shift-`') },
 | 
						|
			ctrl: function(){ alert('ctrl-`') },
 | 
						|
			'ctrl+alt': function(){ alert('ctrl-alt-`') },
 | 
						|
		},
 | 
						|
		*/
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
* vim:set ts=4 sw=4 :                                                */
 |