| 
									
										
										
										
											2013-05-14 18:10:33 +04:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | **********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //var DEBUG = DEBUG != null ? DEBUG : true
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-01 21:44:49 +04:00
										 |  |  | var CURSOR_SHOW_THRESHOLD = 20 | 
					
						
							| 
									
										
										
										
											2013-06-01 21:33:59 +04:00
										 |  |  | var CURSOR_HIDE_TIMEOUT = 1000 | 
					
						
							| 
									
										
										
										
											2013-06-01 18:26:06 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-08 01:48:22 +04:00
										 |  |  | var STATUS_QUEUE = [] | 
					
						
							|  |  |  | var STATUS_QUEUE_TIME = 200 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-01 18:26:06 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-24 14:40:15 +04:00
										 |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-01 18:26:06 +04:00
										 |  |  | // XXX revise...
 | 
					
						
							| 
									
										
										
										
											2013-06-01 18:43:14 +04:00
										 |  |  | // NOTE: to catch the click event correctly while the cursor is hidden
 | 
					
						
							|  |  |  | //		this must be the first to get the event...
 | 
					
						
							| 
									
										
										
										
											2013-06-08 20:04:27 +04:00
										 |  |  | // NOTE: this uses element.data to store the timer and cursor position...
 | 
					
						
							| 
									
										
										
										
											2013-06-01 18:26:06 +04:00
										 |  |  | function autoHideCursor(elem){ | 
					
						
							|  |  |  | 	elem = $(elem) | 
					
						
							| 
									
										
										
										
											2013-06-08 20:04:27 +04:00
										 |  |  | 	var data = elem.data() | 
					
						
							| 
									
										
										
										
											2013-06-01 18:26:06 +04:00
										 |  |  | 	elem | 
					
						
							|  |  |  | 		.on('mousemove', function(evt){ | 
					
						
							| 
									
										
										
										
											2013-06-01 21:33:59 +04:00
										 |  |  | 			var cursor = elem.css('cursor') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-08 20:04:27 +04:00
										 |  |  | 			data._cursor_pos = data._cursor_pos == null || cursor != 'none' ? | 
					
						
							| 
									
										
										
										
											2013-06-01 18:26:06 +04:00
										 |  |  | 						[evt.clientX, evt.clientY]  | 
					
						
							| 
									
										
										
										
											2013-06-08 20:04:27 +04:00
										 |  |  | 					: data._cursor_pos | 
					
						
							| 
									
										
										
										
											2013-06-01 18:26:06 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-01 21:33:59 +04:00
										 |  |  | 			// cursor visible -- extend visibility...
 | 
					
						
							|  |  |  | 			if(cursor != 'none'){ | 
					
						
							| 
									
										
										
										
											2013-06-01 18:26:06 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-08 20:04:27 +04:00
										 |  |  | 				if(data._cursor_timeout != null){ | 
					
						
							|  |  |  | 					clearTimeout(data._cursor_timeout) | 
					
						
							| 
									
										
										
										
											2013-06-01 18:26:06 +04:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2013-06-08 20:04:27 +04:00
										 |  |  | 				data._cursor_timeout = setTimeout(function(){ | 
					
						
							|  |  |  | 						if(Math.abs(evt.clientX - data._cursor_pos[0]) < CURSOR_SHOW_THRESHOLD  | 
					
						
							|  |  |  | 								|| Math.abs(evt.clientY - data._cursor_pos[1]) < CURSOR_SHOW_THRESHOLD){ | 
					
						
							| 
									
										
										
										
											2013-06-01 18:26:06 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-01 21:33:59 +04:00
										 |  |  | 							elem.css('cursor', 'none') | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}, CURSOR_HIDE_TIMEOUT) | 
					
						
							| 
									
										
										
										
											2013-06-01 18:26:06 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-01 21:33:59 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// cursor hidden -- if outside the threshold, show...
 | 
					
						
							| 
									
										
										
										
											2013-06-08 20:04:27 +04:00
										 |  |  | 			} else if(Math.abs(evt.clientX - data._cursor_pos[0]) > CURSOR_SHOW_THRESHOLD  | 
					
						
							|  |  |  | 				|| Math.abs(evt.clientY - data._cursor_pos[1]) > CURSOR_SHOW_THRESHOLD){ | 
					
						
							| 
									
										
										
										
											2013-06-01 21:33:59 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				elem.css('cursor', '') | 
					
						
							| 
									
										
										
										
											2013-06-01 18:26:06 +04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2013-06-01 18:43:14 +04:00
										 |  |  | 		.click(function(evt){ | 
					
						
							|  |  |  | 			if(elem.css('cursor') == 'none'){ | 
					
						
							|  |  |  | 				//event.stopImmediatePropagation()
 | 
					
						
							|  |  |  | 				//event.preventDefault()
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-08 20:04:27 +04:00
										 |  |  | 				if(data._cursor_timeout != null){ | 
					
						
							|  |  |  | 					clearTimeout(data._cursor_timeout) | 
					
						
							|  |  |  | 					data._cursor_timeout = null | 
					
						
							| 
									
										
										
										
											2013-06-01 18:43:14 +04:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				elem.css('cursor', '') | 
					
						
							|  |  |  | 				//return false
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2013-06-01 18:26:06 +04:00
										 |  |  | 	return elem | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-08 20:04:27 +04:00
										 |  |  | /* | 
					
						
							|  |  |  | // XXX does not work...
 | 
					
						
							|  |  |  | // 		...does not show the cursor without moving it...
 | 
					
						
							|  |  |  | function showCursor(elem){ | 
					
						
							|  |  |  | 	elem = $(elem) | 
					
						
							|  |  |  | 	var data = elem.data() | 
					
						
							|  |  |  | 	if(data._cursor_timeout != null){ | 
					
						
							|  |  |  | 		clearTimeout(data._cursor_timeout) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	elem.css('cursor', '') | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-04 09:29:38 +04:00
										 |  |  | function flashIndicator(direction){ | 
					
						
							|  |  |  | 	var cls = { | 
					
						
							| 
									
										
										
										
											2013-06-08 02:29:14 +04:00
										 |  |  | 		// shift up/down...
 | 
					
						
							| 
									
										
										
										
											2013-06-04 09:29:38 +04:00
										 |  |  | 		prev: '.up-indicator', | 
					
						
							|  |  |  | 		next: '.down-indicator', | 
					
						
							| 
									
										
										
										
											2013-06-08 05:46:57 +04:00
										 |  |  | 		// hit start/end/top/bottom of view...
 | 
					
						
							| 
									
										
										
										
											2013-06-04 09:29:38 +04:00
										 |  |  | 		start: '.start-indicator', | 
					
						
							|  |  |  | 		end: '.end-indicator', | 
					
						
							| 
									
										
										
										
											2013-06-08 02:29:14 +04:00
										 |  |  | 		top: '.top-indicator', | 
					
						
							|  |  |  | 		bottom: '.bottom-indicator', | 
					
						
							| 
									
										
										
										
											2013-06-04 09:29:38 +04:00
										 |  |  | 	}[direction] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var indicator = $(cls) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(indicator.length == 0){ | 
					
						
							|  |  |  | 		indicator = $('<div>') | 
					
						
							|  |  |  | 			.addClass(cls.replace('.', '')) | 
					
						
							|  |  |  | 			.appendTo($('.viewer')) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return indicator | 
					
						
							|  |  |  | 		// NOTE: this needs to be visible in all cases and key press 
 | 
					
						
							|  |  |  | 		// 		rhythms... 
 | 
					
						
							|  |  |  | 		.show() | 
					
						
							|  |  |  | 		.delay(100) | 
					
						
							|  |  |  | 		.fadeOut(300) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Update an info element
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // align can be:
 | 
					
						
							|  |  |  | // 	- top
 | 
					
						
							|  |  |  | // 	- bottom
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // If target is an existing info container (class: overlay-info) then 
 | 
					
						
							|  |  |  | // just fill that.
 | 
					
						
							|  |  |  | function updateInfo(elem, data, target){ | 
					
						
							|  |  |  | 	var viewer = $('.viewer') | 
					
						
							|  |  |  | 	target = target == null ? viewer : $(target) | 
					
						
							|  |  |  | 	elem = elem == null ? $('.overlay-info') : $(elem) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(elem.length == 0){ | 
					
						
							|  |  |  | 		elem = $('<div/>') | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	elem | 
					
						
							|  |  |  | 		.addClass('overlay-info') | 
					
						
							|  |  |  | 		.html('') | 
					
						
							|  |  |  | 		.off() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(typeof(data) == typeof('abc')){ | 
					
						
							|  |  |  | 		elem.html(data) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		elem.append(data) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return elem  | 
					
						
							|  |  |  | 		.appendTo(target) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function showInfo(elem, data, target){ | 
					
						
							|  |  |  | 	elem = elem == null ? $('.overlay-info') : elem | 
					
						
							|  |  |  | 	elem = data == null ? elem : updateInfo(elem, data, traget) | 
					
						
							|  |  |  | 	return elem.fadeIn() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function hideInfo(elem){ | 
					
						
							|  |  |  | 	elem = elem == null ? $('.overlay-info') : elem | 
					
						
							|  |  |  | 	return elem.fadeOut() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Update status message
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: this will update message content and return it as-is, things 
 | 
					
						
							|  |  |  | // 		like showing the message are to be done manually...
 | 
					
						
							|  |  |  | // 		see: showStatus(...) and showErrorStatus(...) for a higher level
 | 
					
						
							|  |  |  | // 		API...
 | 
					
						
							|  |  |  | // NOTE: in addition to showing user status, this will also log the 
 | 
					
						
							|  |  |  | // 		satus to browser console...
 | 
					
						
							|  |  |  | // NOTE: the message will be logged to console via either console.log(...)
 | 
					
						
							|  |  |  | // 		or console.error(...), if the message starts with "Error".
 | 
					
						
							|  |  |  | // NOTE: if message is null, then just return the status element...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // XXX add abbility to append and clear status...
 | 
					
						
							|  |  |  | function updateStatus(message){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var elem = $('.global-status') | 
					
						
							|  |  |  | 	if(elem.length == 0){ | 
					
						
							|  |  |  | 		elem = $('<div class="global-status"/>') | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(message == null){ | 
					
						
							|  |  |  | 		return elem | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(typeof(message) == typeof('s') && /^error.*/i.test(message)){ | 
					
						
							|  |  |  | 		console.error.apply(console, arguments) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		console.log.apply(console, arguments) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(arguments.length > 1){ | 
					
						
							|  |  |  | 		message = Array.apply(Array, arguments).join(' ') | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return updateInfo(elem, message) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Same as updateInfo(...) but will aslo show and animate-close the message
 | 
					
						
							| 
									
										
										
										
											2013-06-04 16:32:33 +04:00
										 |  |  | //
 | 
					
						
							|  |  |  | // XXX the next call will not reset the animation of the previous, rather 
 | 
					
						
							|  |  |  | // 		it will pause it and rezume...
 | 
					
						
							|  |  |  | // 		...not sure if this is correct.
 | 
					
						
							| 
									
										
										
										
											2013-06-04 09:29:38 +04:00
										 |  |  | function showStatus(message){ | 
					
						
							|  |  |  | 	return updateStatus.apply(null, arguments) | 
					
						
							| 
									
										
										
										
											2013-06-04 16:32:33 +04:00
										 |  |  | 		//.stop()
 | 
					
						
							|  |  |  | 		.stop(true, false) | 
					
						
							|  |  |  | 		//.finish()
 | 
					
						
							| 
									
										
										
										
											2013-06-04 09:29:38 +04:00
										 |  |  | 		.show() | 
					
						
							|  |  |  | 		.delay(500) | 
					
						
							|  |  |  | 		.fadeOut(800) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-08 01:48:22 +04:00
										 |  |  | // Same as showStatus(...) but queue the message so as to display it for
 | 
					
						
							|  |  |  | // a meaningful amount of time...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	- This will print the first message right away.
 | 
					
						
							|  |  |  | //	- Each consecutive message if STATUS_QUEUE_TIME has not passed yet 
 | 
					
						
							|  |  |  | //		will get queued.
 | 
					
						
							|  |  |  | //	- Once the STATUS_QUEUE_TIME has passed the next message is reported 
 | 
					
						
							|  |  |  | // 		and so on until the queue is empty.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: for very a fast and large sequence of messages the reporting 
 | 
					
						
							|  |  |  | // 		may (will) take longer (significantly) than the actual "job"...
 | 
					
						
							|  |  |  | // NOTE: this will delay the logging also...
 | 
					
						
							|  |  |  | function showStatusQ(message){ | 
					
						
							|  |  |  | 	if(STATUS_QUEUE.length == 0){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// end marker...
 | 
					
						
							|  |  |  | 		STATUS_QUEUE.push(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		showStatus.apply(null, arguments) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		function _printer(){ | 
					
						
							|  |  |  | 			// if queue is empty we have nothing to do...
 | 
					
						
							|  |  |  | 			if(STATUS_QUEUE.length == 1){ | 
					
						
							|  |  |  | 				STATUS_QUEUE.pop() | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// if not empty show a status and repeat...
 | 
					
						
							|  |  |  | 			showStatus.apply(null, STATUS_QUEUE.pop()) | 
					
						
							|  |  |  | 			setTimeout(_printer, STATUS_QUEUE_TIME) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		setTimeout(_printer, STATUS_QUEUE_TIME) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// queue not empty...
 | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		STATUS_QUEUE.splice(1, 0, Array.apply(Array, arguments)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-04 09:29:38 +04:00
										 |  |  | // Same as showStatus(...) but will always add 'Error: ' to the start 
 | 
					
						
							|  |  |  | // of the message
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: this will show the message but will not hide it.
 | 
					
						
							|  |  |  | function showErrorStatus(message){ | 
					
						
							|  |  |  | 	message = Array.apply(Array, arguments) | 
					
						
							|  |  |  | 	message.splice(0, 0, 'Error:') | 
					
						
							|  |  |  | 	return updateStatus.apply(null, message) | 
					
						
							|  |  |  | 		.one('click', function(){ $(this).fadeOut() }) | 
					
						
							| 
									
										
										
										
											2013-06-04 16:32:33 +04:00
										 |  |  | 		//.stop()
 | 
					
						
							|  |  |  | 		.stop(true, false) | 
					
						
							|  |  |  | 		//.finish()
 | 
					
						
							| 
									
										
										
										
											2013-06-04 09:29:38 +04:00
										 |  |  | 		.show() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // shorthand methods...
 | 
					
						
							|  |  |  | function hideStatus(){ | 
					
						
							|  |  |  | 	// yes, this indeed looks funny -- to hide a status you need to show
 | 
					
						
							|  |  |  | 	// it without any arguments... ;)
 | 
					
						
							|  |  |  | 	return showStatus() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | function getStatus(){ | 
					
						
							|  |  |  | 	return updateStatus() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // XXX move to ui.js?
 | 
					
						
							|  |  |  | function makeIndicator(text){ | 
					
						
							| 
									
										
										
										
											2013-06-08 02:29:14 +04:00
										 |  |  | 	return $('<span class="indicator expanding-text">'+ | 
					
						
							| 
									
										
										
										
											2013-06-04 09:29:38 +04:00
										 |  |  | 				'<span class="hidden">'+ text +'</span>'+ | 
					
						
							|  |  |  | 				'<span class="shown">'+ text[0] +'</span>'+ | 
					
						
							|  |  |  | 			'</span>') | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function showGlobalIndicator(cls, text){ | 
					
						
							|  |  |  | 	var c = $('.global-mode-indicators') | 
					
						
							|  |  |  | 	if(c.length == 0){ | 
					
						
							|  |  |  | 		c = $('<div>') | 
					
						
							|  |  |  | 			.addClass('global-mode-indicators') | 
					
						
							| 
									
										
										
										
											2013-06-08 02:29:14 +04:00
										 |  |  | 			.append('<span class="mode-tip">Global status</span>') | 
					
						
							| 
									
										
										
										
											2013-06-04 09:29:38 +04:00
										 |  |  | 			.appendTo($('.viewer')) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return makeIndicator(text) | 
					
						
							|  |  |  | 			.addClass(cls) | 
					
						
							|  |  |  | 			.appendTo(c) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | function showContextIndicator(cls, text){ | 
					
						
							|  |  |  | 	var c = $('.context-mode-indicators') | 
					
						
							|  |  |  | 	if(c.length == 0){ | 
					
						
							|  |  |  | 		c = $('<div>') | 
					
						
							|  |  |  | 			.addClass('context-mode-indicators') | 
					
						
							| 
									
										
										
										
											2013-06-08 02:29:14 +04:00
										 |  |  | 			.append('<span class="mode-tip">Context status</span>') | 
					
						
							| 
									
										
										
										
											2013-06-04 09:29:38 +04:00
										 |  |  | 			.appendTo($('.viewer')) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return makeIndicator(text) | 
					
						
							|  |  |  | 			.addClass(cls) | 
					
						
							|  |  |  | 			.appendTo(c) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-10 19:20:35 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							|  |  |  | * Modal dialogs... | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-10 17:28:32 +04:00
										 |  |  | function getOverlay(root){ | 
					
						
							|  |  |  | 	root = $(root) | 
					
						
							|  |  |  | 	var overlay = root.find('.overlay-block') | 
					
						
							|  |  |  | 	if(overlay.length == 0){ | 
					
						
							|  |  |  | 		return $('<div class="overlay-block">'+ | 
					
						
							|  |  |  | 					'<div class="background"/>'+ | 
					
						
							|  |  |  | 					'<div class="content"/>'+ | 
					
						
							|  |  |  | 				'</div>').appendTo(root) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return overlay | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function showInOverlay(root, data){ | 
					
						
							|  |  |  | 	root = $(root) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var overlay = getOverlay(root) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(data != null){ | 
					
						
							|  |  |  | 		var container = $('<table width="100%" height="100%"><tr><td align="center" valign="center">'+ | 
					
						
							|  |  |  | 								'<div class="dialog"/>'+ | 
					
						
							|  |  |  | 							'</td></tr></table>') | 
					
						
							|  |  |  | 		var dialog = container.find('.dialog') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		//overlay.find('.background')
 | 
					
						
							|  |  |  | 		//	.click(function(){ hideOverlay(root) })
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		dialog | 
					
						
							|  |  |  | 			.append(data) | 
					
						
							| 
									
										
										
										
											2013-06-11 03:10:01 +04:00
										 |  |  | 			.on('click', function(){  | 
					
						
							| 
									
										
										
										
											2013-06-10 19:20:35 +04:00
										 |  |  | 				event.stopPropagation()  | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2013-06-10 17:28:32 +04:00
										 |  |  | 		overlay.find('.content') | 
					
						
							| 
									
										
										
										
											2013-06-10 19:20:35 +04:00
										 |  |  | 			.on('click', function(){  | 
					
						
							|  |  |  | 				overlay.trigger('close') | 
					
						
							|  |  |  | 				hideOverlay(root)  | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2013-06-11 03:10:01 +04:00
										 |  |  | 			.on('close accept', function(){ | 
					
						
							|  |  |  | 				//hideOverlay(root) 
 | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2013-06-10 17:28:32 +04:00
										 |  |  | 			.append(container) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	root.addClass('overlay') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return overlay | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function hideOverlay(root){ | 
					
						
							|  |  |  | 	root.removeClass('overlay') | 
					
						
							| 
									
										
										
										
											2013-06-10 19:20:35 +04:00
										 |  |  | 	root.find('.overlay-block') | 
					
						
							|  |  |  | 		.trigger('close') | 
					
						
							|  |  |  | 		.remove() | 
					
						
							| 
									
										
										
										
											2013-06-10 17:28:32 +04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-12 14:45:48 +04:00
										 |  |  | var FIELD_TYPES = { | 
					
						
							|  |  |  | 	text: { | 
					
						
							|  |  |  | 		type: 'text', | 
					
						
							|  |  |  | 		text: null, | 
					
						
							|  |  |  | 		default: '', | 
					
						
							| 
									
										
										
										
											2013-06-13 02:02:24 +04:00
										 |  |  | 		html: '<div class="field string">'+ | 
					
						
							| 
									
										
										
										
											2013-06-12 14:45:48 +04:00
										 |  |  | 				'<span class="text"></span>'+ | 
					
						
							|  |  |  | 				'<input type="text" class="value">'+ | 
					
						
							|  |  |  | 			'</div>', | 
					
						
							| 
									
										
										
										
											2013-06-12 16:11:19 +04:00
										 |  |  | 		test: function(val){ | 
					
						
							|  |  |  | 			return typeof(val) == typeof('abc') | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2013-06-12 17:25:13 +04:00
										 |  |  | 		set: function(field, value){ | 
					
						
							|  |  |  | 			$(field).find('.value').attr('value', value)  | 
					
						
							| 
									
										
										
										
											2013-06-12 14:45:48 +04:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2013-06-12 16:11:19 +04:00
										 |  |  | 		get: function(field){  | 
					
						
							| 
									
										
										
										
											2013-06-12 14:45:48 +04:00
										 |  |  | 			return $(field).find('.value').attr('value')  | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	},	 | 
					
						
							|  |  |  | 	bool: { | 
					
						
							| 
									
										
										
										
											2013-06-12 16:11:19 +04:00
										 |  |  | 		type: 'bool', | 
					
						
							| 
									
										
										
										
											2013-06-12 14:45:48 +04:00
										 |  |  | 		text: null, | 
					
						
							|  |  |  | 		default: false, | 
					
						
							| 
									
										
										
										
											2013-06-13 02:02:24 +04:00
										 |  |  | 		html: '<div class="field checkbox">'+ | 
					
						
							| 
									
										
										
										
											2013-06-22 19:30:56 +04:00
										 |  |  | 				'<label><input type="checkbox" class="value">'+ | 
					
						
							|  |  |  | 				'<span class="text"></span></label>'+ | 
					
						
							| 
									
										
										
										
											2013-06-12 14:45:48 +04:00
										 |  |  | 			'</div>', | 
					
						
							| 
									
										
										
										
											2013-06-12 16:11:19 +04:00
										 |  |  | 		test: function(val){ | 
					
						
							|  |  |  | 			return val === true || val === false | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		set: function(field, value){ | 
					
						
							|  |  |  | 			if(value){ | 
					
						
							| 
									
										
										
										
											2013-06-12 14:45:48 +04:00
										 |  |  | 				$(field).find('.value').attr('checked', '')  | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				$(field).find('.value').removeAttr('checked')  | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2013-06-12 16:11:19 +04:00
										 |  |  | 		get: function(field){  | 
					
						
							| 
									
										
										
										
											2013-06-12 17:25:13 +04:00
										 |  |  | 			return $(field).find('.value').attr('checked') == 'checked' | 
					
						
							| 
									
										
										
										
											2013-06-12 14:45:48 +04:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2013-06-13 17:25:38 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-13 19:42:42 +04:00
										 |  |  | 	// NOTE: this will not work without node-webkit...
 | 
					
						
							| 
									
										
										
										
											2013-06-13 17:25:38 +04:00
										 |  |  | 	dir: { | 
					
						
							|  |  |  | 		type: 'dir', | 
					
						
							|  |  |  | 		text: null, | 
					
						
							|  |  |  | 		default: false, | 
					
						
							|  |  |  | 		html: '<div class="field checkbox">'+ | 
					
						
							|  |  |  | 				'<span class="text"></span>'+ | 
					
						
							|  |  |  | 				'<input type="file" class="value" nwdirectory />'+ | 
					
						
							|  |  |  | 			'</div>', | 
					
						
							|  |  |  | 		// format: {dir: <default-path>}
 | 
					
						
							|  |  |  | 		test: function(val){ | 
					
						
							|  |  |  | 			return typeof(val) == typeof({}) && 'dir' in val | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		set: function(field, value){ | 
					
						
							|  |  |  | 			field.find('.value').attr('nwworkingdir', value.dir) | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		get: function(field){  | 
					
						
							|  |  |  | 			var f = $(field).find('.value')[0].files | 
					
						
							|  |  |  | 			if(f.length == 0){ | 
					
						
							|  |  |  | 				return '' | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return f[0].path | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2013-06-13 19:42:42 +04:00
										 |  |  | 	// NOTE: this will not work without node-webkit...
 | 
					
						
							| 
									
										
										
										
											2013-06-13 17:25:38 +04:00
										 |  |  | 	ndir: { | 
					
						
							|  |  |  | 		type: 'ndir', | 
					
						
							|  |  |  | 		text: null, | 
					
						
							|  |  |  | 		default: false, | 
					
						
							|  |  |  | 		html: '<div class="field dir">'+ | 
					
						
							|  |  |  | 				'<span class="text"></span>'+ | 
					
						
							|  |  |  | 				'<input type="text" class="path"/>'+ | 
					
						
							|  |  |  | 				'<button class="browse">Browse</button>'+ | 
					
						
							|  |  |  | 			'</div>', | 
					
						
							|  |  |  | 		// format: {dir: <default-path>}
 | 
					
						
							|  |  |  | 		test: function(val){ | 
					
						
							|  |  |  | 			return typeof(val) == typeof({}) && 'ndir' in val | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		set: function(field, value){ | 
					
						
							|  |  |  | 			var that = this | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// NOTE: we are attaching the file browser to body to avoid 
 | 
					
						
							|  |  |  | 			// 		click events on it closing the dialog...
 | 
					
						
							|  |  |  | 			// 		...for some reason stopPropagation(...) does not do 
 | 
					
						
							|  |  |  | 			// 		the job...
 | 
					
						
							|  |  |  | 			var file = $('<input type="file" class="value" nwdirectory/>') | 
					
						
							|  |  |  | 				.attr('nwworkingdir', value.ndir) | 
					
						
							|  |  |  | 				.change(function(){ | 
					
						
							|  |  |  | 					var p = file[0].files | 
					
						
							|  |  |  | 					if(p.length != 0){ | 
					
						
							|  |  |  | 						field.find('.path').val(p[0].path) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					file.detach() | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 				.hide() | 
					
						
							|  |  |  | 			field.find('.path').val(value.ndir) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			field.find('.browse').click(function(){ | 
					
						
							|  |  |  | 				file | 
					
						
							| 
									
										
										
										
											2013-06-15 03:04:06 +04:00
										 |  |  | 					// load user input path...
 | 
					
						
							|  |  |  | 					.attr('nwworkingdir', field.find('.path').val()) | 
					
						
							| 
									
										
										
										
											2013-06-13 17:25:38 +04:00
										 |  |  | 					.appendTo($('body')) | 
					
						
							|  |  |  | 					.click() | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		get: function(field){  | 
					
						
							|  |  |  | 			return field.find('.path').val() | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2013-06-22 17:54:15 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	choice: { | 
					
						
							|  |  |  | 		type: 'choice', | 
					
						
							|  |  |  | 		text: null, | 
					
						
							|  |  |  | 		default: false, | 
					
						
							|  |  |  | 		html: '<div class="field choice">'+ | 
					
						
							|  |  |  | 				'<span class="text"></span>'+ | 
					
						
							| 
									
										
										
										
											2013-06-22 19:30:56 +04:00
										 |  |  | 				'<div class="item"><label>'+ | 
					
						
							| 
									
										
										
										
											2013-06-22 17:54:15 +04:00
										 |  |  | 					'<input type="radio" class="value"/>'+ | 
					
						
							|  |  |  | 					'<span class="item-text"></span>'+ | 
					
						
							| 
									
										
										
										
											2013-06-22 19:30:56 +04:00
										 |  |  | 				'</label></div>'+ | 
					
						
							| 
									
										
										
										
											2013-06-22 17:54:15 +04:00
										 |  |  | 			'</div>', | 
					
						
							|  |  |  | 		// format: ['a', 'b', 'c', ...]
 | 
					
						
							|  |  |  | 		test: function(val){ | 
					
						
							|  |  |  | 			return typeof(val) == typeof([]) && val.constructor.name == 'Array' | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		set: function(field, value){ | 
					
						
							|  |  |  | 			var t = field.find('.text').text() | 
					
						
							| 
									
										
										
										
											2013-06-22 19:30:56 +04:00
										 |  |  | 			t = t == '' ? Math.random()+'' : t | 
					
						
							| 
									
										
										
										
											2013-06-22 17:54:15 +04:00
										 |  |  | 			var item = field.find('.item').last() | 
					
						
							|  |  |  | 			for(var i=0; i < value.length; i++){ | 
					
						
							|  |  |  | 				item.find('.value') | 
					
						
							|  |  |  | 					.val(value[i]) | 
					
						
							|  |  |  | 				item.find('.item-text') | 
					
						
							|  |  |  | 					.text(value[i]) | 
					
						
							|  |  |  | 				item.appendTo(field) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				item = item.clone() | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			field.find('.value') | 
					
						
							|  |  |  | 				.attr('name', t) | 
					
						
							|  |  |  | 				.first() | 
					
						
							|  |  |  | 					.attr('checked', '') | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		get: function(field){  | 
					
						
							|  |  |  | 			return $(field).find('.value:checked').val() | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2013-06-12 14:45:48 +04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-13 19:42:42 +04:00
										 |  |  | // Show a complex form dialog
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This will build a form and collect it's data on "accept" specified by
 | 
					
						
							|  |  |  | // the config object...
 | 
					
						
							| 
									
										
										
										
											2013-06-12 14:45:48 +04:00
										 |  |  | //
 | 
					
						
							|  |  |  | // config format:
 | 
					
						
							|  |  |  | //	{
 | 
					
						
							|  |  |  | //		// simple field...
 | 
					
						
							|  |  |  | //		<field-description>: <default-value>,
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //		...
 | 
					
						
							|  |  |  | //	}	
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2013-07-01 17:16:12 +04:00
										 |  |  | // <field-description> and split in two with a "|" the section before will
 | 
					
						
							|  |  |  | // show as the field text and the text after as the tooltip.
 | 
					
						
							|  |  |  | // Example:
 | 
					
						
							|  |  |  | // 		"field text | field tooltip..."
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2013-06-12 14:45:48 +04:00
										 |  |  | // field's default value determines it's type:
 | 
					
						
							|  |  |  | // 	bool		- checkbox
 | 
					
						
							|  |  |  | // 	string		- textarea
 | 
					
						
							| 
									
										
										
										
											2013-06-13 19:42:42 +04:00
										 |  |  | //
 | 
					
						
							|  |  |  | // see FIELD_TYPES for supported field types.
 | 
					
						
							| 
									
										
										
										
											2013-06-12 14:45:48 +04:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2013-06-20 02:41:29 +04:00
										 |  |  | // NOTE: if btn is set to false explicitly then no button will be 
 | 
					
						
							|  |  |  | // 		rendered in the form dialog.
 | 
					
						
							| 
									
										
										
										
											2013-07-01 17:16:12 +04:00
										 |  |  | // NOTE: to include a literal "|" in <field-description> just escape it
 | 
					
						
							|  |  |  | // 		like this: "\|"
 | 
					
						
							| 
									
										
										
										
											2013-06-20 02:41:29 +04:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2013-06-12 17:25:13 +04:00
										 |  |  | // XXX add form testing...
 | 
					
						
							|  |  |  | // XXX add undefined field handling/reporting...
 | 
					
						
							| 
									
										
										
										
											2013-06-13 01:37:30 +04:00
										 |  |  | // XXX revise...
 | 
					
						
							|  |  |  | function formDialog(root, message, config, btn, cls){ | 
					
						
							| 
									
										
										
										
											2013-06-12 17:25:13 +04:00
										 |  |  | 	cls = cls == null ? '' : cls | 
					
						
							| 
									
										
										
										
											2013-06-13 17:25:38 +04:00
										 |  |  | 	btn = btn == null ? 'OK' : btn | 
					
						
							| 
									
										
										
										
											2013-06-13 01:37:30 +04:00
										 |  |  | 	root = root == null ? $('.viewer') : root | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-12 16:11:19 +04:00
										 |  |  | 	var form = $('<div class="form"/>') | 
					
						
							|  |  |  | 	var data = {} | 
					
						
							|  |  |  | 	var res = $.Deferred() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-12 17:25:13 +04:00
										 |  |  | 	// handle message and btn...
 | 
					
						
							|  |  |  | 	form.append($('<div class="text">'+message+'</div>')) | 
					
						
							| 
									
										
										
										
											2013-06-12 16:11:19 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// build the form...
 | 
					
						
							|  |  |  | 	for(var t in config){ | 
					
						
							|  |  |  | 		var did_handling = false | 
					
						
							|  |  |  | 		for(var f in FIELD_TYPES){ | 
					
						
							|  |  |  | 			if(FIELD_TYPES[f].test(config[t])){ | 
					
						
							|  |  |  | 				var field = FIELD_TYPES[f] | 
					
						
							|  |  |  | 				var html = $(field.html) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-01 17:16:12 +04:00
										 |  |  | 				// get the tooltip...
 | 
					
						
							|  |  |  | 				if(/[^\\]\|/.test(t)){ | 
					
						
							|  |  |  | 					var tip = t.split(/\s*\|\s*/) | 
					
						
							|  |  |  | 					text = tip[0] | 
					
						
							|  |  |  | 					tip = tip[1] | 
					
						
							|  |  |  | 					$('<span class="tooltip-icon tooltip-right">?</span>') | 
					
						
							|  |  |  | 						.attr('tooltip', tip) | 
					
						
							|  |  |  | 						.appendTo(html) | 
					
						
							|  |  |  | 				// cleanup...
 | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					text = t.replace(/\\\|/g, '|') | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				// setup text and data...
 | 
					
						
							|  |  |  | 				html.find('.text').text(text) | 
					
						
							| 
									
										
										
										
											2013-06-12 16:11:19 +04:00
										 |  |  | 				field.set(html, config[t]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-12 17:25:13 +04:00
										 |  |  | 				// NOTE: this is here to isolate t and field.get values...
 | 
					
						
							|  |  |  | 				// 		...is there a better way???
 | 
					
						
							|  |  |  | 				var _ = (function(title, getter){ | 
					
						
							|  |  |  | 					html.on('resolve', function(evt, e){ | 
					
						
							|  |  |  | 						data[title] = getter(e) | 
					
						
							|  |  |  | 					}) | 
					
						
							|  |  |  | 				})(t, field.get) | 
					
						
							| 
									
										
										
										
											2013-06-12 16:11:19 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				form.append(html) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				did_handling = true | 
					
						
							| 
									
										
										
										
											2013-06-12 17:25:13 +04:00
										 |  |  | 				break | 
					
						
							| 
									
										
										
										
											2013-06-12 16:11:19 +04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// handle unresolved fields...
 | 
					
						
							|  |  |  | 		if(!did_handling){ | 
					
						
							| 
									
										
										
										
											2013-06-13 01:37:30 +04:00
										 |  |  | 			console.warn('formDialog: not all fields understood.') | 
					
						
							| 
									
										
										
										
											2013-06-12 16:11:19 +04:00
										 |  |  | 			// XXX skipping field...
 | 
					
						
							|  |  |  | 			// XXX
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-12 17:25:13 +04:00
										 |  |  | 	// add button...
 | 
					
						
							| 
									
										
										
										
											2013-06-20 02:41:29 +04:00
										 |  |  | 	if(btn !== false){ | 
					
						
							|  |  |  | 		var button = $('<button class="accept">'+btn+'</button>') | 
					
						
							|  |  |  | 		form.append(button) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-06-12 17:25:13 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	var overlay = showInOverlay(root, form) | 
					
						
							|  |  |  | 		.addClass('dialog ' + cls) | 
					
						
							| 
									
										
										
										
											2013-06-12 16:11:19 +04:00
										 |  |  | 		.on('accept', function(){ | 
					
						
							|  |  |  | 			form.find('.field').each(function(_, e){ | 
					
						
							| 
									
										
										
										
											2013-06-12 17:25:13 +04:00
										 |  |  | 				$(e).trigger('resolve', [$(e)]) | 
					
						
							| 
									
										
										
										
											2013-06-12 16:11:19 +04:00
										 |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// XXX test if all required stuff is filled...
 | 
					
						
							|  |  |  | 			res.resolve(data) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			hideOverlay(root) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		.on('close', function(){ | 
					
						
							|  |  |  | 			res.reject() | 
					
						
							| 
									
										
										
										
											2013-06-12 17:25:13 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-12 16:11:19 +04:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-12 17:25:13 +04:00
										 |  |  | 	button.click(function(){ | 
					
						
							|  |  |  | 		overlay.trigger('accept') | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-13 01:37:30 +04:00
										 |  |  | 	setTimeout(function(){  | 
					
						
							| 
									
										
										
										
											2013-06-13 02:02:24 +04:00
										 |  |  | 		form.find('.field input').first() | 
					
						
							| 
									
										
										
										
											2013-06-13 01:37:30 +04:00
										 |  |  | 			.focus() | 
					
						
							|  |  |  | 			.select() | 
					
						
							|  |  |  | 	}, 100) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return res | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-13 19:42:42 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-13 01:37:30 +04:00
										 |  |  | /************************************************ Standard dialogs ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var _alert = alert | 
					
						
							|  |  |  | function alert(){ | 
					
						
							|  |  |  | 	var message = Array.apply(null, arguments).join(' ') | 
					
						
							| 
									
										
										
										
											2013-06-20 02:41:29 +04:00
										 |  |  | 	//return formDialog(null, String(message), {}, 'OK', 'alert')
 | 
					
						
							|  |  |  | 	return formDialog(null, String(message), {}, false, 'alert') | 
					
						
							| 
									
										
										
										
											2013-06-13 01:37:30 +04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var _prompt = prompt | 
					
						
							|  |  |  | function prompt(message, dfl, btn){ | 
					
						
							|  |  |  | 	btn = btn == null ? 'OK' : btn | 
					
						
							|  |  |  | 	var res = $.Deferred() | 
					
						
							| 
									
										
										
										
											2013-06-13 17:25:38 +04:00
										 |  |  | 	formDialog(null, message, {'': ''+(dfl == null ? '' : dfl)}, btn, 'prompt') | 
					
						
							| 
									
										
										
										
											2013-06-13 01:37:30 +04:00
										 |  |  | 		.done(function(data){ res.resolve(data['']) }) | 
					
						
							|  |  |  | 		.fail(function(){ res.reject() }) | 
					
						
							| 
									
										
										
										
											2013-06-12 16:11:19 +04:00
										 |  |  | 	return res | 
					
						
							| 
									
										
										
										
											2013-06-12 14:45:48 +04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-13 01:37:30 +04:00
										 |  |  | /* | 
					
						
							|  |  |  | function confirm(){ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-13 19:42:42 +04:00
										 |  |  | // NOTE: this will not work without node-webkit...
 | 
					
						
							| 
									
										
										
										
											2013-06-13 17:25:38 +04:00
										 |  |  | function getDir(message, dfl, btn){ | 
					
						
							|  |  |  | 	btn = btn == null ? 'OK' : btn | 
					
						
							|  |  |  | 	dfl = dfl == null ? '' : dfl | 
					
						
							|  |  |  | 	var res = $.Deferred() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	formDialog(null, message, {'': {ndir: dfl}}, btn, 'getDir') | 
					
						
							|  |  |  | 		.done(function(data){ res.resolve(data['']) }) | 
					
						
							|  |  |  | 		.fail(function(){ res.reject() }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return res | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-22 17:54:15 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | /***************************************** Domain-specific dialogs ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-21 17:47:44 +04:00
										 |  |  | // XXX do reporting...
 | 
					
						
							| 
									
										
										
										
											2013-06-27 17:29:53 +04:00
										 |  |  | function exportPreviewsDialog(state, dfl){ | 
					
						
							| 
									
										
										
										
											2013-06-21 17:47:44 +04:00
										 |  |  | 	dfl = dfl == null ? BASE_URL : dfl | 
					
						
							| 
									
										
										
										
											2013-06-27 17:29:53 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// XXX make this more generic...
 | 
					
						
							| 
									
										
										
										
											2013-07-03 07:03:46 +04:00
										 |  |  | 	// tell the user what state are we exporting...
 | 
					
						
							| 
									
										
										
										
											2013-06-27 17:29:53 +04:00
										 |  |  | 	if(state == null){ | 
					
						
							|  |  |  | 		state = toggleMarkedOnlyView('?') == 'on' ? 'marked images' : state | 
					
						
							|  |  |  | 		state = toggleSingleRibbonMode('?') == 'on' ? 'current ribbon' : state | 
					
						
							|  |  |  | 		state = state == null ? 'all images' : state | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-21 17:47:44 +04:00
										 |  |  | 	var res = $.Deferred() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-21 20:02:54 +04:00
										 |  |  | 	updateStatus('Export...').show() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-01 18:05:50 +04:00
										 |  |  | 	// NOTE: we are not defining the object in-place here because some 
 | 
					
						
							|  |  |  | 	// 		keys become unreadable with JS syntax preventing us from 
 | 
					
						
							|  |  |  | 	// 		splitting the key into several lines...
 | 
					
						
							|  |  |  | 	var cfg = {} | 
					
						
							|  |  |  | 	cfg['Image name pattern | '+ | 
					
						
							|  |  |  | 			'%f - full filename\n'+ | 
					
						
							|  |  |  | 			'%n - filename\n'+ | 
					
						
							|  |  |  | 			'%e - extension\n'+ | 
					
						
							|  |  |  | 			'%gid - log gid\n'+ | 
					
						
							|  |  |  | 			'%g - short gid\n'+ | 
					
						
							| 
									
										
										
										
											2013-07-01 18:25:33 +04:00
										 |  |  | 			'%I - global order\n'+ | 
					
						
							|  |  |  | 			'%i - current selection order'] = '%f' | 
					
						
							| 
									
										
										
										
											2013-07-01 18:05:50 +04:00
										 |  |  | 	cfg['Fav directory name'] = 'fav' | 
					
						
							|  |  |  | 	cfg['Destination'] = {ndir: dfl} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var keys = Object.keys(cfg) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-03 07:03:46 +04:00
										 |  |  | 	formDialog(null, '<b>Export:</b> '+ state +'.', cfg, 'OK', 'exportPreviewsDialog') | 
					
						
							| 
									
										
										
										
											2013-06-21 17:47:44 +04:00
										 |  |  | 		.done(function(data){ | 
					
						
							| 
									
										
										
										
											2013-06-21 19:10:12 +04:00
										 |  |  | 			exportTo( | 
					
						
							| 
									
										
										
										
											2013-07-01 18:05:50 +04:00
										 |  |  | 				normalizePath(data[keys[2]]),  | 
					
						
							|  |  |  | 				data[keys[0]],  | 
					
						
							|  |  |  | 				data[keys[1]]) | 
					
						
							| 
									
										
										
										
											2013-06-21 17:47:44 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-21 20:02:54 +04:00
										 |  |  | 			// XXX do real reporting...
 | 
					
						
							|  |  |  | 			showStatusQ('Copying data...') | 
					
						
							| 
									
										
										
										
											2013-06-21 19:48:58 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-21 17:47:44 +04:00
										 |  |  | 			res.resolve(data['']) | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2013-06-21 20:02:54 +04:00
										 |  |  | 		.fail(function(){  | 
					
						
							|  |  |  | 			showStatusQ('Export: canceled.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			res.reject()  | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2013-06-21 17:47:44 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return res | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-22 17:54:15 +04:00
										 |  |  | function loadDirectoryDialog(dfl){ | 
					
						
							| 
									
										
										
										
											2013-06-21 20:02:54 +04:00
										 |  |  | 	dfl = dfl == null ? BASE_URL : dfl | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	updateStatus('Open...').show() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-03 06:42:14 +04:00
										 |  |  | 	formDialog(null, 'Path to open', { | 
					
						
							|  |  |  | 		'': {ndir: dfl}, | 
					
						
							|  |  |  | 		'Precess previews': false, | 
					
						
							| 
									
										
										
										
											2013-07-03 06:58:28 +04:00
										 |  |  | 	}, 'OK', 'loadDirectoryDialog') | 
					
						
							| 
									
										
										
										
											2013-07-03 06:42:14 +04:00
										 |  |  | 		.done(function(data){ | 
					
						
							| 
									
										
										
										
											2013-07-03 06:58:28 +04:00
										 |  |  | 			var path = normalizePath(data[''].trim()) | 
					
						
							| 
									
										
										
										
											2013-07-03 06:42:14 +04:00
										 |  |  | 			var process_previews = data['Precess previews'] | 
					
						
							| 
									
										
										
										
											2013-07-03 06:58:28 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-21 22:57:16 +04:00
										 |  |  | 			// reset the modes...
 | 
					
						
							|  |  |  | 			toggleSingleImageMode('off') | 
					
						
							|  |  |  | 			toggleSingleRibbonMode('off') | 
					
						
							| 
									
										
										
										
											2013-06-23 03:14:04 +04:00
										 |  |  | 			toggleMarkedOnlyView('off') | 
					
						
							| 
									
										
										
										
											2013-06-21 22:57:16 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-03 06:58:28 +04:00
										 |  |  | 			// do the loading...
 | 
					
						
							| 
									
										
										
										
											2013-06-21 20:02:54 +04:00
										 |  |  | 			statusNotify(loadDir(path)) | 
					
						
							| 
									
										
										
										
											2013-07-03 06:42:14 +04:00
										 |  |  | 				.done(function(){ | 
					
						
							|  |  |  | 					if(!process_previews){  | 
					
						
							|  |  |  | 						showStatusQ('Previews: processing started...') | 
					
						
							| 
									
										
										
										
											2013-07-03 06:58:28 +04:00
										 |  |  | 						// generate/attach previews...
 | 
					
						
							| 
									
										
										
										
											2013-07-03 06:42:14 +04:00
										 |  |  | 						makeImagesPreviewsQ(DATA.order)  | 
					
						
							|  |  |  | 							.done(function(){  | 
					
						
							|  |  |  | 								showStatusQ('Previews: processing done.') | 
					
						
							|  |  |  | 							}) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2013-06-21 20:02:54 +04:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 		.fail(function(){ | 
					
						
							|  |  |  | 			showStatusQ('Open: canceled.') | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-22 17:54:15 +04:00
										 |  |  | function sortImagesDialog(message){ | 
					
						
							| 
									
										
										
										
											2013-06-22 19:30:56 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-22 17:54:15 +04:00
										 |  |  | 	updateStatus('Sort...').show() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	message = message == null ? 'Sort images by:' : message | 
					
						
							| 
									
										
										
										
											2013-06-22 19:30:56 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-22 17:54:15 +04:00
										 |  |  | 	cfg = {} | 
					
						
							|  |  |  | 	cfg[message] = [ | 
					
						
							|  |  |  | 		'Date (ascending)',  | 
					
						
							|  |  |  | 		'Name (ascending)',  | 
					
						
							|  |  |  | 		'Date (decending)',  | 
					
						
							| 
									
										
										
										
											2013-06-22 19:30:56 +04:00
										 |  |  | 		'Name (decending)' | 
					
						
							| 
									
										
										
										
											2013-06-22 17:54:15 +04:00
										 |  |  | 	] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	formDialog(null, '',  | 
					
						
							|  |  |  | 			cfg, | 
					
						
							|  |  |  | 			'OK',  | 
					
						
							|  |  |  | 			'sortImagesDialog') | 
					
						
							|  |  |  | 		.done(function(res){ | 
					
						
							|  |  |  | 			res = res[message] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(/Date/.test(res)){ | 
					
						
							|  |  |  | 				var method = sortImagesByDate | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				var method = sortImagesByName | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(/\(ascending\)/.test(res)){ | 
					
						
							|  |  |  | 				var reverse = null | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				var reverse = true | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			showStatusQ('Sorting by: '+res+'...') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			method(reverse) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		.fail(function(){ | 
					
						
							|  |  |  | 			showStatusQ('Sort: canceled.') | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-06-13 01:37:30 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-11 03:10:01 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | function showImageInfo(){ | 
					
						
							|  |  |  | 	var gid = getImageGID(getImage()) | 
					
						
							|  |  |  | 	var r = getRibbonIndex(getRibbon()) | 
					
						
							|  |  |  | 	var data = IMAGES[gid] | 
					
						
							|  |  |  | 	var orientation = data.orientation | 
					
						
							|  |  |  | 	orientation = orientation == null ? 0 : orientation | 
					
						
							|  |  |  | 	var flipped = data.flipped | 
					
						
							|  |  |  | 	flipped = flipped == null ? '' : ', flipped '+flipped+'ly' | 
					
						
							|  |  |  | 	var order = DATA.order.indexOf(gid) | 
					
						
							|  |  |  | 	var name = data.path.split('/').pop() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	alert('<div>'+ | 
					
						
							|  |  |  | 			'<h2>"'+ name +'"</h2>'+ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			'<table>'+ | 
					
						
							|  |  |  | 				'<tr><td>GID: </td><td>'+ gid +'</td></tr>'+ | 
					
						
							|  |  |  | 				'<tr><td>Path: </td><td>"'+ data.path +'"</td></tr>'+ | 
					
						
							|  |  |  | 				'<tr><td>Orientation: </td><td>'+ orientation +'°'+flipped+'</td></tr>'+ | 
					
						
							|  |  |  | 				'<tr><td>Order: </td><td>'+ order +'</td></tr>'+ | 
					
						
							|  |  |  | 				'<tr><td>Position (ribbon): </td><td>'+ (DATA.ribbons[r].indexOf(gid)+1) + | 
					
						
							|  |  |  | 					'/'+ DATA.ribbons[r].length +'</td></tr>'+ | 
					
						
							|  |  |  | 				'<tr><td>Position (global): </td><td>'+ (order+1) +'/'+ DATA.order.length +'</td></tr>'+ | 
					
						
							|  |  |  | 			'</table>'+ | 
					
						
							|  |  |  | 		'</div>') | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-10 19:20:35 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-11 03:10:01 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							|  |  |  | * vim:set ts=4 sw=4 nowrap :										 */ |