mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-11-03 04:40:10 +00:00 
			
		
		
		
	
		
			
	
	
		
			633 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			633 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								/**********************************************************************
							 | 
						||
| 
								 | 
							
								* 
							 | 
						||
| 
								 | 
							
								*
							 | 
						||
| 
								 | 
							
								*
							 | 
						||
| 
								 | 
							
								**********************************************************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//var DEBUG = DEBUG != null ? DEBUG : true
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**********************************************************************
							 | 
						||
| 
								 | 
							
								* Modal dialogs...
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/********************************************************* Helpers ***/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Set element text and tooltip
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// NOTE: when text is a list, we will only use the first and the last 
							 | 
						||
| 
								 | 
							
								// 		elements...
							 | 
						||
| 
								 | 
							
								// NOTE: if tip_elem is not given then both the text and tip will be set
							 | 
						||
| 
								 | 
							
								// 		on text_elem
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// XXX add support for quoted '|'...
							 | 
						||
| 
								 | 
							
								function setTextWithTooltip(text, text_elem, tip_elem){
							 | 
						||
| 
								 | 
							
									text_elem = $(text_elem)
							 | 
						||
| 
								 | 
							
									tip_elem = tip_elem == null ? text_elem : tip_elem
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if(typeof(text) != typeof('str')){
							 | 
						||
| 
								 | 
							
										tip = text
							 | 
						||
| 
								 | 
							
									} else {
							 | 
						||
| 
								 | 
							
										var tip = text.split(/\s*\|\s*/)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// set elemnt text...
							 | 
						||
| 
								 | 
							
									text_elem
							 | 
						||
| 
								 | 
							
										.html(tip[0])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// do the tooltip...
							 | 
						||
| 
								 | 
							
									tip = tip.slice(1)
							 | 
						||
| 
								 | 
							
									tip = tip[tip.length-1]
							 | 
						||
| 
								 | 
							
									if(tip != null && tip.trim().length > 0){
							 | 
						||
| 
								 | 
							
										$('<span class="tooltip-icon tooltip-right"> *</span>')
							 | 
						||
| 
								 | 
							
											.attr('tooltip', tip)
							 | 
						||
| 
								 | 
							
											.appendTo(tip_elem)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return text_elem
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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)
							 | 
						||
| 
								 | 
							
											.on('click', function(evt){ 
							 | 
						||
| 
								 | 
							
												evt.stopPropagation() 
							 | 
						||
| 
								 | 
							
											})
							 | 
						||
| 
								 | 
							
										overlay.find('.content')
							 | 
						||
| 
								 | 
							
											.on('click', function(){ 
							 | 
						||
| 
								 | 
							
												overlay.trigger('close')
							 | 
						||
| 
								 | 
							
												hideOverlay(root) 
							 | 
						||
| 
								 | 
							
											})
							 | 
						||
| 
								 | 
							
											.on('close accept', function(){
							 | 
						||
| 
								 | 
							
												//hideOverlay(root) 
							 | 
						||
| 
								 | 
							
											})
							 | 
						||
| 
								 | 
							
											.append(container)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									root.addClass('overlay')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return overlay
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function hideOverlay(root){
							 | 
						||
| 
								 | 
							
									root.removeClass('overlay')
							 | 
						||
| 
								 | 
							
									root.find('.overlay-block')
							 | 
						||
| 
								 | 
							
										.trigger('close')
							 | 
						||
| 
								 | 
							
										.remove()
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function isOverlayVisible(root){
							 | 
						||
| 
								 | 
							
									return getOverlay(root).css('display') != 'none'
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**********************************************************************
							 | 
						||
| 
								 | 
							
								* Field definitions...
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var FIELD_TYPES = {
							 | 
						||
| 
								 | 
							
									// a simple hr...
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									// format:
							 | 
						||
| 
								 | 
							
									// 		'---'
							 | 
						||
| 
								 | 
							
									// 		Three or more '-'s
							 | 
						||
| 
								 | 
							
									hr: {
							 | 
						||
| 
								 | 
							
										type: 'hr',
							 | 
						||
| 
								 | 
							
										text: null,
							 | 
						||
| 
								 | 
							
										default: false,
							 | 
						||
| 
								 | 
							
										html: '<hr>',
							 | 
						||
| 
								 | 
							
										test: function(val){
							 | 
						||
| 
								 | 
							
											return /\-\-\-+/.test(val)
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									// a simple br...
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									// format:
							 | 
						||
| 
								 | 
							
									// 		'   '
							 | 
						||
| 
								 | 
							
									// 		Three or more spaces
							 | 
						||
| 
								 | 
							
									br: {
							 | 
						||
| 
								 | 
							
										type: 'br',
							 | 
						||
| 
								 | 
							
										text: null,
							 | 
						||
| 
								 | 
							
										default: false,
							 | 
						||
| 
								 | 
							
										html: '<br>',
							 | 
						||
| 
								 | 
							
										test: function(val){
							 | 
						||
| 
								 | 
							
											return /\s\s\s+/.test(val)
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									// format:
							 | 
						||
| 
								 | 
							
									// 	{
							 | 
						||
| 
								 | 
							
									// 		html: <html-block>
							 | 
						||
| 
								 | 
							
									// 	}
							 | 
						||
| 
								 | 
							
									html: {
							 | 
						||
| 
								 | 
							
										type: 'html',
							 | 
						||
| 
								 | 
							
										text: null,
							 | 
						||
| 
								 | 
							
										default: false,
							 | 
						||
| 
								 | 
							
										html: '<div class="html-block"/>',
							 | 
						||
| 
								 | 
							
										test: function(val){
							 | 
						||
| 
								 | 
							
											return val.html != null
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										set: function(field, value){
							 | 
						||
| 
								 | 
							
											if(typeof(value.html) == typeof('str')){
							 | 
						||
| 
								 | 
							
												field.html(value.html)
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												field.append(value.html)
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// format: 
							 | 
						||
| 
								 | 
							
									// 		string
							 | 
						||
| 
								 | 
							
									// XXX add datalist option...
							 | 
						||
| 
								 | 
							
									// XXX make this textarea compatible...
							 | 
						||
| 
								 | 
							
									text: {
							 | 
						||
| 
								 | 
							
										type: 'text',
							 | 
						||
| 
								 | 
							
										text: null,
							 | 
						||
| 
								 | 
							
										default: '',
							 | 
						||
| 
								 | 
							
										html: '<div class="field string">'+
							 | 
						||
| 
								 | 
							
												'<span class="text"></span>'+
							 | 
						||
| 
								 | 
							
												'<input type="text" class="value">'+
							 | 
						||
| 
								 | 
							
											'</div>',
							 | 
						||
| 
								 | 
							
										test: function(val){
							 | 
						||
| 
								 | 
							
											return typeof(val) == typeof('abc')
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										set: function(field, value){
							 | 
						||
| 
								 | 
							
											$(field).find('.value').attr('value', value) 
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										get: function(field){ 
							 | 
						||
| 
								 | 
							
											return $(field).find('.value').attr('value') 
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									},	
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// format: 
							 | 
						||
| 
								 | 
							
									// 		true | false
							 | 
						||
| 
								 | 
							
									bool: {
							 | 
						||
| 
								 | 
							
										type: 'bool',
							 | 
						||
| 
								 | 
							
										text: null,
							 | 
						||
| 
								 | 
							
										default: false,
							 | 
						||
| 
								 | 
							
										html: '<div class="field checkbox">'+
							 | 
						||
| 
								 | 
							
												'<label><input type="checkbox" class="value">'+
							 | 
						||
| 
								 | 
							
												'<span class="text"></span></label>'+
							 | 
						||
| 
								 | 
							
											'</div>',
							 | 
						||
| 
								 | 
							
										test: function(val){
							 | 
						||
| 
								 | 
							
											return val === true || val === false
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										set: function(field, value){
							 | 
						||
| 
								 | 
							
											if(value){
							 | 
						||
| 
								 | 
							
												$(field).find('.value').attr('checked', '') 
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												$(field).find('.value').removeAttr('checked') 
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										get: function(field){ 
							 | 
						||
| 
								 | 
							
											return $(field).find('.value').attr('checked') == 'checked'
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// NOTE: this will not work without node-webkit...
							 | 
						||
| 
								 | 
							
									// format: 
							 | 
						||
| 
								 | 
							
									// 		{ dir: <default-path> }
							 | 
						||
| 
								 | 
							
									dir: {
							 | 
						||
| 
								 | 
							
										type: 'dir',
							 | 
						||
| 
								 | 
							
										text: null,
							 | 
						||
| 
								 | 
							
										default: false,
							 | 
						||
| 
								 | 
							
										html: '<div class="field checkbox">'+
							 | 
						||
| 
								 | 
							
												'<span class="text"></span>'+
							 | 
						||
| 
								 | 
							
												'<input type="file" class="value" nwdirectory />'+
							 | 
						||
| 
								 | 
							
											'</div>',
							 | 
						||
| 
								 | 
							
										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
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// NOTE: this will not work without node-webkit...
							 | 
						||
| 
								 | 
							
									// format: 
							 | 
						||
| 
								 | 
							
									// 		{ dir: <default-path> }
							 | 
						||
| 
								 | 
							
									// XXX add datalist option...
							 | 
						||
| 
								 | 
							
									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>',
							 | 
						||
| 
								 | 
							
										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()
							 | 
						||
| 
								 | 
							
													// focus+select the path field...
							 | 
						||
| 
								 | 
							
													// NOTE: this is here to enable fast select-open 
							 | 
						||
| 
								 | 
							
													// 		keyboard cycle (tab, enter, <select path>, 
							 | 
						||
| 
								 | 
							
													// 		enter, enter)...
							 | 
						||
| 
								 | 
							
													field.find('.path')
							 | 
						||
| 
								 | 
							
														.focus()
							 | 
						||
| 
								 | 
							
														.select()
							 | 
						||
| 
								 | 
							
												})
							 | 
						||
| 
								 | 
							
												.hide()
							 | 
						||
| 
								 | 
							
											field.find('.path').val(value.ndir)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											field.find('.browse').click(function(){
							 | 
						||
| 
								 | 
							
												file
							 | 
						||
| 
								 | 
							
													// load user input path...
							 | 
						||
| 
								 | 
							
													.attr('nwworkingdir', field.find('.path').val())
							 | 
						||
| 
								 | 
							
													.appendTo($('body'))
							 | 
						||
| 
								 | 
							
													.click()
							 | 
						||
| 
								 | 
							
											})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										get: function(field){ 
							 | 
						||
| 
								 | 
							
											return field.find('.path').val()
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// format: 
							 | 
						||
| 
								 | 
							
									// 		['a', 'b', 'c', ...]
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									// an item can be of the folowing format:
							 | 
						||
| 
								 | 
							
									// 		<text> ['|' 'default' | 'disabled' ] [ '|' <tool-tip> ]
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									// NOTE: only one 'default' item should be present.
							 | 
						||
| 
								 | 
							
									// NOTE: if no defaults are set, then the first item is checked.
							 | 
						||
| 
								 | 
							
									choice: {
							 | 
						||
| 
								 | 
							
										type: 'choice',
							 | 
						||
| 
								 | 
							
										text: null,
							 | 
						||
| 
								 | 
							
										default: false,
							 | 
						||
| 
								 | 
							
										html: '<div class="field choice">'+
							 | 
						||
| 
								 | 
							
												'<span class="text"></span>'+
							 | 
						||
| 
								 | 
							
												'<div class="item"><label>'+
							 | 
						||
| 
								 | 
							
													'<input type="radio" class="value"/>'+
							 | 
						||
| 
								 | 
							
													'<span class="item-text"></span>'+
							 | 
						||
| 
								 | 
							
												'</label></div>'+
							 | 
						||
| 
								 | 
							
											'</div>',
							 | 
						||
| 
								 | 
							
										test: function(val){
							 | 
						||
| 
								 | 
							
											return typeof(val) == typeof([]) && val.constructor.name == 'Array'
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										set: function(field, value){
							 | 
						||
| 
								 | 
							
											var t = field.find('.text').html()
							 | 
						||
| 
								 | 
							
											t = t == '' ? Math.random()+'' : t
							 | 
						||
| 
								 | 
							
											var item = field.find('.item').last()
							 | 
						||
| 
								 | 
							
											for(var i=0; i < value.length; i++){
							 | 
						||
| 
								 | 
							
												// get options...
							 | 
						||
| 
								 | 
							
												var opts = value[i]
							 | 
						||
| 
								 | 
							
													.split(/\|/g)
							 | 
						||
| 
								 | 
							
													.map(function(e){ return e.trim() })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												var val = item.find('.value')
							 | 
						||
| 
								 | 
							
												val.val(opts[0])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// set checked state...
							 | 
						||
| 
								 | 
							
												if(opts.slice(1).indexOf('default') >= 0){
							 | 
						||
| 
								 | 
							
													val.prop('checked', true)
							 | 
						||
| 
								 | 
							
													opts.splice(opts.indexOf('default'), 1)
							 | 
						||
| 
								 | 
							
												} else {
							 | 
						||
| 
								 | 
							
													val.prop('checked', false)
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// set disabled state...
							 | 
						||
| 
								 | 
							
												if(opts.slice(1).indexOf('disabled') >= 0){
							 | 
						||
| 
								 | 
							
													val.prop('disabled', true)
							 | 
						||
| 
								 | 
							
													opts.splice(opts.indexOf('disabled'), 1)
							 | 
						||
| 
								 | 
							
													item.addClass('disabled')
							 | 
						||
| 
								 | 
							
												} else {
							 | 
						||
| 
								 | 
							
													val.prop('disabled', false)
							 | 
						||
| 
								 | 
							
													item.removeClass('disabled')
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												setTextWithTooltip(opts, item.find('.item-text'))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												item.appendTo(field)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												item = item.clone()
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											var values = field.find('.value')
							 | 
						||
| 
								 | 
							
												.attr('name', t)
							 | 
						||
| 
								 | 
							
											// set the default...
							 | 
						||
| 
								 | 
							
											if(values.filter(':checked:not([disabled])').length == 0){
							 | 
						||
| 
								 | 
							
												values.filter(':not([disabled])').first()
							 | 
						||
| 
								 | 
							
													.prop('checked', true)
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										get: function(field){ 
							 | 
						||
| 
								 | 
							
											return $(field).find('.value:checked').val()
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// format: 
							 | 
						||
| 
								 | 
							
									// 	{ 
							 | 
						||
| 
								 | 
							
									// 		select: ['a', 'b', 'c', ...] 
							 | 
						||
| 
								 | 
							
									// 		// default option (optional)...
							 | 
						||
| 
								 | 
							
									// 		default: <number> | <text>
							 | 
						||
| 
								 | 
							
									// 	}
							 | 
						||
| 
								 | 
							
									select: {
							 | 
						||
| 
								 | 
							
										type: 'select',
							 | 
						||
| 
								 | 
							
										text: null,
							 | 
						||
| 
								 | 
							
										default: false,
							 | 
						||
| 
								 | 
							
										html: '<div class="field choice">'+
							 | 
						||
| 
								 | 
							
												'<span class="text"></span>'+
							 | 
						||
| 
								 | 
							
												'<select>'+
							 | 
						||
| 
								 | 
							
													'<option class="option"></option>'+
							 | 
						||
| 
								 | 
							
												'</select>'+
							 | 
						||
| 
								 | 
							
											'</div>',
							 | 
						||
| 
								 | 
							
										test: function(val){
							 | 
						||
| 
								 | 
							
											return 'select' in val
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										set: function(field, value){
							 | 
						||
| 
								 | 
							
											var t = field.find('.text').text()
							 | 
						||
| 
								 | 
							
											var item = field.find('.option').last()
							 | 
						||
| 
								 | 
							
											var select = field.find('select')
							 | 
						||
| 
								 | 
							
											for(var i=0; i < value.select.length; i++){
							 | 
						||
| 
								 | 
							
												item
							 | 
						||
| 
								 | 
							
													.html(value.select[i])
							 | 
						||
| 
								 | 
							
													.val(value.select[i])
							 | 
						||
| 
								 | 
							
												item.appendTo(select)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												item = item.clone()
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											if(value.default != null){
							 | 
						||
| 
								 | 
							
												if(typeof(value.default) == typeof(123)){
							 | 
						||
| 
								 | 
							
													field.find('.option')
							 | 
						||
| 
								 | 
							
														.eq(value.default)
							 | 
						||
| 
								 | 
							
															.attr('selected', '')
							 | 
						||
| 
								 | 
							
												} else {
							 | 
						||
| 
								 | 
							
													field.find('.option[value="'+ value.default +'"]')
							 | 
						||
| 
								 | 
							
														.attr('selected', '')
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										get: function(field){ 
							 | 
						||
| 
								 | 
							
											return $(field).find('.option:selected').val()
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// NOTE: a button can have state...
							 | 
						||
| 
								 | 
							
									// format: 
							 | 
						||
| 
								 | 
							
									// 	{ 
							 | 
						||
| 
								 | 
							
									// 		// click event handler...
							 | 
						||
| 
								 | 
							
									// 		button: <function>, 
							 | 
						||
| 
								 | 
							
									// 		// optional, button text (default 'OK')...
							 | 
						||
| 
								 | 
							
									// 		text: <button-label>,
							 | 
						||
| 
								 | 
							
									// 		// optional, initial state setup...
							 | 
						||
| 
								 | 
							
									// 		default: <function>,
							 | 
						||
| 
								 | 
							
									// 	}
							 | 
						||
| 
								 | 
							
									button: {
							 | 
						||
| 
								 | 
							
										type: 'button',
							 | 
						||
| 
								 | 
							
										text: null,
							 | 
						||
| 
								 | 
							
										default: false,
							 | 
						||
| 
								 | 
							
										html: '<div class="field button">'+
							 | 
						||
| 
								 | 
							
												'<span class="text"></span>'+
							 | 
						||
| 
								 | 
							
												'<button class="button"></button>'+
							 | 
						||
| 
								 | 
							
											'</div>',
							 | 
						||
| 
								 | 
							
										test: function(val){
							 | 
						||
| 
								 | 
							
											return 'button' in val
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										set: function(field, value){
							 | 
						||
| 
								 | 
							
											var btn = $(field).find('button')
							 | 
						||
| 
								 | 
							
												.click(value.button)
							 | 
						||
| 
								 | 
							
												.html(value.text == null ? 'OK' : value.text)
							 | 
						||
| 
								 | 
							
											if('default' in value){
							 | 
						||
| 
								 | 
							
												value.default(btn)
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										get: function(field){ 
							 | 
						||
| 
								 | 
							
											return $(field).attr('state')
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**********************************************************************
							 | 
						||
| 
								 | 
							
								* Constructors...
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Show a complex form dialog
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// This will build a form and collect it's data on "accept" specified by
							 | 
						||
| 
								 | 
							
								// the config object...
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// config format:
							 | 
						||
| 
								 | 
							
								//	{
							 | 
						||
| 
								 | 
							
								//		// simple field...
							 | 
						||
| 
								 | 
							
								//		<field-description>: <default-value>,
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								//		...
							 | 
						||
| 
								 | 
							
								//	}	
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// <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..."
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// field's default value determines it's type:
							 | 
						||
| 
								 | 
							
								// 	bool		- checkbox
							 | 
						||
| 
								 | 
							
								// 	string		- textarea
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// see FIELD_TYPES for supported field types.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// NOTE: if btn is set to false explicitly then no button will be 
							 | 
						||
| 
								 | 
							
								// 		rendered in the form dialog.
							 | 
						||
| 
								 | 
							
								// NOTE: to include a literal "|" in <field-description> just escape it
							 | 
						||
| 
								 | 
							
								// 		like this: "\|"
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// XXX add form testing...
							 | 
						||
| 
								 | 
							
								// XXX add undefined field handling/reporting...
							 | 
						||
| 
								 | 
							
								function formDialog(root, message, config, btn, cls){
							 | 
						||
| 
								 | 
							
									cls = cls == null ? '' : cls
							 | 
						||
| 
								 | 
							
									btn = btn == null ? 'OK' : btn
							 | 
						||
| 
								 | 
							
									root = root == null ? $('.viewer') : root
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var form = $('<div class="form"/>')
							 | 
						||
| 
								 | 
							
									var data = {}
							 | 
						||
| 
								 | 
							
									var res = $.Deferred()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// handle message and btn...
							 | 
						||
| 
								 | 
							
									if(message.trim().length > 0){
							 | 
						||
| 
								 | 
							
										setTextWithTooltip(message, $('<div class="text"/>'))
							 | 
						||
| 
								 | 
							
											.appendTo(form)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// 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)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// setup text and data...
							 | 
						||
| 
								 | 
							
												setTextWithTooltip(t, html.find('.text'), html)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if(field.set != null){
							 | 
						||
| 
								 | 
							
													field.set(html, config[t])
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if(field.get != null){
							 | 
						||
| 
								 | 
							
													// 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)
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												form.append(html)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												did_handling = true
							 | 
						||
| 
								 | 
							
												break
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// handle unresolved fields...
							 | 
						||
| 
								 | 
							
										if(!did_handling){
							 | 
						||
| 
								 | 
							
											console.warn('formDialog: not all fields understood.')
							 | 
						||
| 
								 | 
							
											// XXX skipping field...
							 | 
						||
| 
								 | 
							
											// XXX
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// add button...
							 | 
						||
| 
								 | 
							
									if(btn !== false){
							 | 
						||
| 
								 | 
							
										var button = $('<button class="accept">'+btn+'</button>')
							 | 
						||
| 
								 | 
							
										form.append(button)
							 | 
						||
| 
								 | 
							
									} else {
							 | 
						||
| 
								 | 
							
										var button = null
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var overlay = showInOverlay(root, form)
							 | 
						||
| 
								 | 
							
										.addClass('dialog ' + cls)
							 | 
						||
| 
								 | 
							
										.on('accept', function(){
							 | 
						||
| 
								 | 
							
											form.find('.field').each(function(_, e){
							 | 
						||
| 
								 | 
							
												$(e).trigger('resolve', [$(e)])
							 | 
						||
| 
								 | 
							
											})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// XXX test if all required stuff is filled...
							 | 
						||
| 
								 | 
							
											res.resolve(data, form)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											hideOverlay(root)
							 | 
						||
| 
								 | 
							
										})
							 | 
						||
| 
								 | 
							
										.on('close', function(){
							 | 
						||
| 
								 | 
							
											res.reject()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if(button != null){
							 | 
						||
| 
								 | 
							
										button.click(function(){
							 | 
						||
| 
								 | 
							
											overlay.trigger('accept')
							 | 
						||
| 
								 | 
							
										})
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// focus an element...
							 | 
						||
| 
								 | 
							
									// NOTE: if first element is a radio button set, focus the checked
							 | 
						||
| 
								 | 
							
									//		element, else focus the first input...
							 | 
						||
| 
								 | 
							
									form.ready(function(){ 
							 | 
						||
| 
								 | 
							
										// NOTE: we are using a timeout to avoid the user input that opened
							 | 
						||
| 
								 | 
							
										// 		the dialog to end up in the first field...
							 | 
						||
| 
								 | 
							
										setTimeout(function(){
							 | 
						||
| 
								 | 
							
											var elem = form.find('.field input').first()
							 | 
						||
| 
								 | 
							
											if(elem.attr('type') == 'radio'){
							 | 
						||
| 
								 | 
							
												form.find('.field input:checked')
							 | 
						||
| 
								 | 
							
													.focus()
							 | 
						||
| 
								 | 
							
													.select()
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												elem
							 | 
						||
| 
								 | 
							
													.focus()
							 | 
						||
| 
								 | 
							
													.select()
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}, 100)
							 | 
						||
| 
								 | 
							
									})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return res
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/************************************************ Standard dialogs ***/
							 | 
						||
| 
								 | 
							
								// NOTE: these return a deferred that will reflect the state of the 
							 | 
						||
| 
								 | 
							
								// 		dialog, and the progress of the operations that it riggers...
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// XXX might be a good idea to be able to block the ui (overlay + progress
							 | 
						||
| 
								 | 
							
								// 		bar?) until some long/critical operations finish, to prevent the
							 | 
						||
| 
								 | 
							
								// 		user from breaking things while the ui is inconsistent...
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function alertDialog(){
							 | 
						||
| 
								 | 
							
									var message = $.makeArray(arguments).join(' ')
							 | 
						||
| 
								 | 
							
									return formDialog(null, String(message), {}, false, 'alert')
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function promptDialog(message, dfl, btn){
							 | 
						||
| 
								 | 
							
									btn = btn == null ? 'OK' : btn
							 | 
						||
| 
								 | 
							
									var res = $.Deferred()
							 | 
						||
| 
								 | 
							
									formDialog(null, message, {'': ''+(dfl == null ? '' : dfl)}, btn, 'prompt')
							 | 
						||
| 
								 | 
							
										.done(function(data){ res.resolve(data['']) })
							 | 
						||
| 
								 | 
							
										.fail(function(){ res.reject() })
							 | 
						||
| 
								 | 
							
									return res
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								function confirmDialog(){
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**********************************************************************
							 | 
						||
| 
								 | 
							
								* vim:set ts=4 sw=4 :                                                */
							 |