mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-04 05:12:30 +00:00 
			
		
		
		
	git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@8289 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			466 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			466 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/*
 | 
						|
    author: ApmeM (artem.votincev@gmail.com)
 | 
						|
    date: 9-June-2010
 | 
						|
    version: 1.4
 | 
						|
    download: http://code.google.com/p/jq-serverbrowse/
 | 
						|
 */
 | 
						|
 | 
						|
(function($) {
 | 
						|
	$.fn.serverBrowser = function(settings) {
 | 
						|
		this.each(function() {
 | 
						|
 | 
						|
			var config = {
 | 
						|
				// Event function
 | 
						|
				// Appear when user click 'Ok' button, or doubleclick on file
 | 
						|
				onSelect : function(file) {
 | 
						|
					alert('You select: ' + file);
 | 
						|
				},
 | 
						|
				onLoad : function() {
 | 
						|
					return config.basePath;
 | 
						|
				},
 | 
						|
				multiselect : false,
 | 
						|
				// Image parameters
 | 
						|
				// System images (loading.gif, unknown.png, folder.png and
 | 
						|
				// images from knownPaths) will be referenced to systemImageUrl
 | 
						|
				// if systemImageUrl is empty or not specified - imageUrl will
 | 
						|
				// be taken
 | 
						|
				// All other images (like images for extension) will be taken
 | 
						|
				// from imageUrl
 | 
						|
				imageUrl : 'img/',
 | 
						|
				systemImageUrl : '',
 | 
						|
				showUpInList : false,
 | 
						|
				// Path properties
 | 
						|
				// Base path, that links should start from.
 | 
						|
				// If opened path is not under this path, alert will be shown
 | 
						|
				// and nothing will be opened
 | 
						|
				// Path separator, that will be used to split specified paths
 | 
						|
				// and join paths to a string
 | 
						|
				basePath : 'C:',
 | 
						|
				separatorPath : '/',
 | 
						|
				// Paths, that will be displayed on the left side of the dialog
 | 
						|
				// This is a link to specified paths on the server
 | 
						|
				useKnownPaths : true,
 | 
						|
				knownPaths : [ {
 | 
						|
					text : 'Desktop',
 | 
						|
					image : 'desktop.png',
 | 
						|
					path : 'C:/Users/All Users/Desktop'
 | 
						|
				}, {
 | 
						|
					text : 'Documents',
 | 
						|
					image : 'documents.png',
 | 
						|
					path : 'C:/Users/All Users/Documents'
 | 
						|
				} ],
 | 
						|
				// Images for known extension (like 'png', 'exe', 'zip'), that
 | 
						|
				// will be displayed with its real names
 | 
						|
				// Images, that is not in this list will be referenced to
 | 
						|
				// 'unknown.png' image
 | 
						|
				// If list is empty - all images is known.
 | 
						|
				knownExt : [],
 | 
						|
				// Server path to this plugin handler
 | 
						|
				handlerUrl : 'browserDlg.txt',
 | 
						|
				// JQuery-ui dialog settings
 | 
						|
				title : 'Browse',
 | 
						|
				width : 300,
 | 
						|
				height : 300,
 | 
						|
				position : [ 'center', 'center' ],
 | 
						|
 | 
						|
				// Administrative parameters used to
 | 
						|
				// help programmer or system administrator
 | 
						|
				requestMethod : 'POST'
 | 
						|
			};
 | 
						|
 | 
						|
			if (settings)
 | 
						|
				$.extend(config, settings);
 | 
						|
			// Required configuration elements
 | 
						|
			// We need to set some configuration elements without user
 | 
						|
			// For example there should be 2 buttons on the bottom,
 | 
						|
			// And dialog should be opened after button is pressed, not when it
 | 
						|
			// created
 | 
						|
			// Also we need to know about dialog resizing
 | 
						|
			$.extend(config, {
 | 
						|
				autoOpen : false,
 | 
						|
				modal : true,
 | 
						|
				buttons : {
 | 
						|
					"Open" : function() {
 | 
						|
						doneOk();
 | 
						|
					},
 | 
						|
					"Cancel" : function() {
 | 
						|
						browserDlg.dialog("close");
 | 
						|
					}
 | 
						|
				},
 | 
						|
				resize : function(event, ui) {
 | 
						|
					recalculateSize(event, ui);
 | 
						|
				}
 | 
						|
			});
 | 
						|
 | 
						|
			function systemImageUrl() {
 | 
						|
				if (config.systemImageUrl.length == 0) {
 | 
						|
					return config.imageUrl;
 | 
						|
				} else {
 | 
						|
					return config.systemImageUrl;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			var privateConfig = {
 | 
						|
				// This stack array will store history navigation data
 | 
						|
				// When user open new directory, old directory will be added to
 | 
						|
				// this list
 | 
						|
				// If user want, he will be able to move back by this history
 | 
						|
				browserHistory : [],
 | 
						|
 | 
						|
				// This array contains all currently selected items
 | 
						|
				// When user select element, it will add associated path into
 | 
						|
				// this array
 | 
						|
				// When user deselect element - associated path will be removed
 | 
						|
				// Exception: if 'config.multiselect' is false, only one element
 | 
						|
				// will be stored in this array.
 | 
						|
				selectedItems : []
 | 
						|
			};
 | 
						|
 | 
						|
			// Main dialog div
 | 
						|
			// It will be converted into jQuery-ui dialog box using my
 | 
						|
			// configuration parameters
 | 
						|
			// It contains 3 divs
 | 
						|
			var browserDlg = $('<div title="' + config.title + '"></div>').css( {
 | 
						|
				'overflow' : 'hidden'
 | 
						|
			}).appendTo(document.body);
 | 
						|
			browserDlg.dialog(config);
 | 
						|
 | 
						|
			// First div on the top
 | 
						|
			// It contains textbox field and buttons
 | 
						|
			// User can enter any paths he want to open in this textbox and
 | 
						|
			// press enter
 | 
						|
			// There is 3 buttons on the panel:
 | 
						|
			var enterPathDiv = $('<div></div>').addClass('ui-widget-content').appendTo(browserDlg).css( {
 | 
						|
				'height' : '30px',
 | 
						|
				'width' : '100%',
 | 
						|
				'padding-top' : '7px'
 | 
						|
			});
 | 
						|
 | 
						|
			var enterButton = $('<div></div>').css( {
 | 
						|
				'float' : 'left',
 | 
						|
				'vertical-align' : 'middle',
 | 
						|
				'margin-left' : '6px'
 | 
						|
			}).addClass('ui-corner-all').hover(function() {
 | 
						|
				$(this).addClass('ui-state-hover');
 | 
						|
			}, function() {
 | 
						|
				$(this).removeClass('ui-state-hover');
 | 
						|
			});
 | 
						|
 | 
						|
			var enterLabel = $('<span></span>').text('Look in: ').appendTo(enterButton.clone(false).appendTo(enterPathDiv));
 | 
						|
 | 
						|
			var enterText = $('<input type="text">').keypress(function(e) {
 | 
						|
				if (e.keyCode == '13') {
 | 
						|
					e.preventDefault();
 | 
						|
					loadPath(enterText.val());
 | 
						|
				}
 | 
						|
			}).css('width', '200px').appendTo(enterButton.clone(false).appendTo(enterPathDiv));
 | 
						|
 | 
						|
			// Back button.
 | 
						|
			// When user click on it, 2 last elements of the history pop from
 | 
						|
			// the list, and reload second of them.
 | 
						|
			var enterBack = $('<div></div>').addClass('ui-corner-all ui-icon ui-icon-circle-arrow-w').click(function() {
 | 
						|
				privateConfig.browserHistory.pop(); // Remove current element.
 | 
						|
													// It is not required now.
 | 
						|
				var backPath = config.basePath;
 | 
						|
				if (privateConfig.browserHistory.length > 0) {
 | 
						|
					backPath = privateConfig.browserHistory.pop();
 | 
						|
				}
 | 
						|
				loadPath(backPath);
 | 
						|
			}).appendTo(enterButton.clone(true).appendTo(enterPathDiv));
 | 
						|
 | 
						|
			// Level Up Button
 | 
						|
			// When user click on it, last element of the history will be taken,
 | 
						|
			// and '..' will be applied to the end of the array.
 | 
						|
			var enterUp = $('<div></div>').addClass('ui-corner-all ui-icon ui-icon-arrowreturnthick-1-n').click(function() {
 | 
						|
				backPath = privateConfig.browserHistory[privateConfig.browserHistory.length - 1];
 | 
						|
				if (backPath != config.basePath) {
 | 
						|
					loadPath(backPath + config.separatorPath + '..');
 | 
						|
				}
 | 
						|
			}).appendTo(enterButton.clone(true).appendTo(enterPathDiv));
 | 
						|
 | 
						|
			// Second div is on the left
 | 
						|
			// It contains images and texts for pre-defined paths
 | 
						|
			// User just click on them and it will open pre-defined path
 | 
						|
			var knownPathDiv = $('<div></div>').addClass('ui-widget-content').css( {
 | 
						|
				'text-align' : 'center',
 | 
						|
				'overflow' : 'auto',
 | 
						|
				'float' : 'left',
 | 
						|
				'width' : '100px'
 | 
						|
			});
 | 
						|
			if (config.useKnownPaths) {
 | 
						|
				knownPathDiv.appendTo(browserDlg);
 | 
						|
				$.each(config.knownPaths, function(index, path) {
 | 
						|
					var knownDiv = $('<div></div>').css( {
 | 
						|
						'margin' : '10px'
 | 
						|
					}).hover(function() {
 | 
						|
						$(this).addClass('ui-state-hover');
 | 
						|
					}, function() {
 | 
						|
						$(this).removeClass('ui-state-hover');
 | 
						|
					}).click(function() {
 | 
						|
						loadPath(path.path);
 | 
						|
					}).appendTo(knownPathDiv);
 | 
						|
 | 
						|
					$('<img />').attr( {
 | 
						|
						src : systemImageUrl() + config.separatorPath + path.image
 | 
						|
					}).css( {
 | 
						|
						width : '32px',
 | 
						|
						margin : '5px 10px 5px 5px'
 | 
						|
					}).appendTo(knownDiv);
 | 
						|
					$('<br/>').appendTo(knownDiv);
 | 
						|
					$('<span></span>').text(path.text).appendTo(knownDiv);
 | 
						|
				});
 | 
						|
			}
 | 
						|
 | 
						|
			// Third div is everywhere :)
 | 
						|
			// It show files and folders in the current path
 | 
						|
			// User can click on path to select or deselect it
 | 
						|
			// Doubleclick on path will open it
 | 
						|
			// Also doubleclick on file will select this file and close dialog
 | 
						|
			var browserPathDiv = $('<div></div>').addClass('ui-widget-content').css( {
 | 
						|
				'float' : 'right',
 | 
						|
				'overflow' : 'auto'
 | 
						|
			}).appendTo(browserDlg);
 | 
						|
 | 
						|
			// Now everything is done
 | 
						|
			// When user will be ready - he just click on the area you select
 | 
						|
			// for this plugin and dialog will appear
 | 
						|
			$(this).click(function() {
 | 
						|
				privateConfig.browserHistory = [];
 | 
						|
				var startpath = removeBackPath(config.onLoad());
 | 
						|
 | 
						|
				startpath = startpath.split(config.separatorPath);
 | 
						|
				startpath.pop();
 | 
						|
				startpath = startpath.join(config.separatorPath);
 | 
						|
 | 
						|
				if (!checkBasePath(startpath)) {
 | 
						|
					startpath = config.basePath;
 | 
						|
				}
 | 
						|
				loadPath(startpath);
 | 
						|
				browserDlg.dialog('open');
 | 
						|
				recalculateSize();
 | 
						|
			});
 | 
						|
 | 
						|
			// Function check if specified path is a child path of a
 | 
						|
			// 'config.basePath'
 | 
						|
			// If it is not - user should see message, that path invalid, or
 | 
						|
			// path should be changed to valid.
 | 
						|
			function checkBasePath(path) {
 | 
						|
				if (config.basePath == '')
 | 
						|
					return true;
 | 
						|
				var confPath = config.basePath.split(config.separatorPath);
 | 
						|
				var curPath = path.split(config.separatorPath);
 | 
						|
				if (confPath.length > curPath.length)
 | 
						|
					return false;
 | 
						|
				var result = true;
 | 
						|
				$.each(confPath, function(index, partConfPath) {
 | 
						|
					if (partConfPath != curPath[index]) {
 | 
						|
						result = false;
 | 
						|
					}
 | 
						|
				});
 | 
						|
				return result;
 | 
						|
			}
 | 
						|
 | 
						|
			// Function remove '..' parts of the path
 | 
						|
			// Process depend on config.separatorPath option
 | 
						|
			// On the server side you need to check / or \ separators
 | 
						|
			function removeBackPath(path) {
 | 
						|
				var confPath = config.basePath.split(config.separatorPath);
 | 
						|
				var curPath = path.split(config.separatorPath);
 | 
						|
				var newcurPath = [];
 | 
						|
				$.each(curPath, function(index, partCurPath) {
 | 
						|
					if (partCurPath == "..") {
 | 
						|
						newcurPath.pop();
 | 
						|
					} else {
 | 
						|
						newcurPath.push(partCurPath);
 | 
						|
					}
 | 
						|
				});
 | 
						|
				return newcurPath.join(config.separatorPath);
 | 
						|
			}
 | 
						|
 | 
						|
			// This function will be called when user click 'Open'
 | 
						|
			// It check if any path is selected, and call config.onSelect
 | 
						|
			// function with path list
 | 
						|
			function doneOk() {
 | 
						|
				var newCurPath = [];
 | 
						|
				$.each(privateConfig.selectedItems, function(index, item) {
 | 
						|
					newCurPath.push($.data(item, 'path'));
 | 
						|
				});
 | 
						|
				if (newCurPath.length == 0) {
 | 
						|
					newCurPath.push(privateConfig.browserHistory.pop());
 | 
						|
				}
 | 
						|
 | 
						|
				if (config.multiselect)
 | 
						|
					config.onSelect(newCurPath);
 | 
						|
				else {
 | 
						|
					if (newCurPath.length == 1) {
 | 
						|
						config.onSelect(newCurPath[0]);
 | 
						|
					} else if (newCurPath.length > 1) {
 | 
						|
						alert('Plugin work incorrectly. If error repeat, please add issue into http://code.google.com/p/jq-serverbrowse/issues/list with steps to reproduce.');
 | 
						|
						return;
 | 
						|
					}
 | 
						|
				}
 | 
						|
				browserDlg.dialog("close");
 | 
						|
			}
 | 
						|
 | 
						|
			// Function recalculate and set new width and height for left and
 | 
						|
			// right div elements
 | 
						|
			// height have '-2' because of the borders
 | 
						|
			// width have '-4' because of a border an 2 pixels space between
 | 
						|
			// divs
 | 
						|
			function recalculateSize(event, ui) {
 | 
						|
				knownPathDiv.css( {
 | 
						|
					'height' : browserDlg.height() - enterPathDiv.outerHeight(true) - 2
 | 
						|
				});
 | 
						|
				browserPathDiv.css( {
 | 
						|
					'height' : browserDlg.height() - enterPathDiv.outerHeight(true) - 2,
 | 
						|
					'width' : browserDlg.width() - knownPathDiv.outerWidth(true) - 4
 | 
						|
				});
 | 
						|
			}
 | 
						|
 | 
						|
			// Function adds new element into browserPathDiv element depends on
 | 
						|
			// file parameters
 | 
						|
			// If file.isError is set, error message will be displayed instead
 | 
						|
			// of clickable area
 | 
						|
			// Clickable div contain image from extension and text from file
 | 
						|
			// parameter
 | 
						|
			function addElement(file) {
 | 
						|
				var itemDiv = $('<div></div>').css( {
 | 
						|
					margin : '2px'
 | 
						|
				}).appendTo(browserPathDiv);
 | 
						|
				if (file.isError) {
 | 
						|
					itemDiv.addClass('ui-state-error ui-corner-all').css( {
 | 
						|
						padding : '0pt 0.7em'
 | 
						|
					});
 | 
						|
					var p = $('<p></p>').appendTo(itemDiv);
 | 
						|
					$('<span></span>').addClass('ui-icon ui-icon-alert').css( {
 | 
						|
						'float' : 'left',
 | 
						|
						'margin-right' : '0.3em'
 | 
						|
					}).appendTo(p);
 | 
						|
					$('<span></span>').text(file.name).appendTo(p);
 | 
						|
				} else {
 | 
						|
					var fullPath = file.path + config.separatorPath + file.name;
 | 
						|
					itemDiv.hover(function() {
 | 
						|
						$(this).addClass('ui-state-hover');
 | 
						|
					}, function() {
 | 
						|
						$(this).removeClass('ui-state-hover');
 | 
						|
					});
 | 
						|
					var itemImage = $('<img />').css( {
 | 
						|
						width : '16px',
 | 
						|
						margin : '0 5px 0 0'
 | 
						|
					}).appendTo(itemDiv);
 | 
						|
					var itemText = $('<span></span>').text(file.name).appendTo(itemDiv);
 | 
						|
					if (file.isFolder)
 | 
						|
						itemImage.attr( {
 | 
						|
							src : systemImageUrl() + 'folder.png'
 | 
						|
						});
 | 
						|
					else {
 | 
						|
						ext = file.name.split('.').pop();
 | 
						|
						var res = '';
 | 
						|
						if (ext == '' || ext == file.name || (config.knownExt.length > 0 && $.inArray(ext, config.knownExt) < 0))
 | 
						|
							itemImage.attr( {
 | 
						|
								src : systemImageUrl() + 'unknown.png'
 | 
						|
							});
 | 
						|
						else
 | 
						|
							itemImage.attr( {
 | 
						|
								src : config.imageUrl + ext + '.png'
 | 
						|
							});
 | 
						|
					}
 | 
						|
					$.data(itemDiv, 'path', fullPath);
 | 
						|
					itemDiv.unbind('click').bind('click', function(e) {
 | 
						|
						if (!$(this).hasClass('ui-state-active')) {
 | 
						|
							if (!config.multiselect && privateConfig.selectedItems.length > 0) {
 | 
						|
								$(privateConfig.selectedItems[0]).click();
 | 
						|
							}
 | 
						|
							privateConfig.selectedItems.push(itemDiv);
 | 
						|
						} else {
 | 
						|
							var newCurPath = [];
 | 
						|
							$.each(privateConfig.selectedItems, function(index, item) {
 | 
						|
								if ($.data(item, 'path') != fullPath)
 | 
						|
									newCurPath.push(item);
 | 
						|
							});
 | 
						|
							privateConfig.selectedItems = newCurPath;
 | 
						|
						}
 | 
						|
						$(this).toggleClass('ui-state-active');
 | 
						|
					});
 | 
						|
 | 
						|
					itemDiv.unbind('dblclick').bind('dblclick', function(e) {
 | 
						|
						if (file.isFolder) {
 | 
						|
							loadPath(fullPath);
 | 
						|
						} else {
 | 
						|
							privateConfig.selectedItems = [ itemDiv ];
 | 
						|
							doneOk();
 | 
						|
						}
 | 
						|
					});
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			// Main plugin function
 | 
						|
			// When user enter path manually, select it from pre-defined path,
 | 
						|
			// or doubleclick in browser this function will call
 | 
						|
			// It send a request on the server to retrieve child directories and
 | 
						|
			// files of the specified path
 | 
						|
			// If path is not under 'config.basePath', alert will be shown and
 | 
						|
			// nothing will be opened
 | 
						|
			function loadPath(path) {
 | 
						|
				privateConfig.selectedItems = [];
 | 
						|
 | 
						|
				// First we need to remove all '..' parts of the path
 | 
						|
				path = removeBackPath(path);
 | 
						|
 | 
						|
				// Then we need to check, if path based on 'config.basePath'
 | 
						|
				if (!checkBasePath(path)) {
 | 
						|
					alert('Path should be based from ' + config.basePath);
 | 
						|
					return;
 | 
						|
				}
 | 
						|
 | 
						|
				// Then we can put this path into history
 | 
						|
				privateConfig.browserHistory.push(path);
 | 
						|
 | 
						|
				// Show it to user
 | 
						|
				enterText.val(path);
 | 
						|
 | 
						|
				// And load
 | 
						|
				$.ajax( {
 | 
						|
					url : config.handlerUrl,
 | 
						|
					type : config.requestMethod,
 | 
						|
					data : {
 | 
						|
						action : 'browse',
 | 
						|
						path : path,
 | 
						|
						time : new Date().getTime()
 | 
						|
					},
 | 
						|
					beforeSend : function() {
 | 
						|
						browserPathDiv.empty().css( {
 | 
						|
							'text-align' : 'center'
 | 
						|
						});
 | 
						|
						$('<img />').attr( {
 | 
						|
							src : systemImageUrl() + 'loading.gif'
 | 
						|
						}).css( {
 | 
						|
							width : '32px'
 | 
						|
						}).appendTo(browserPathDiv);
 | 
						|
					},
 | 
						|
					success : function(files) {
 | 
						|
						browserPathDiv.empty().css( {
 | 
						|
							'text-align' : 'left'
 | 
						|
						});
 | 
						|
						if (path != config.basePath && config.showUpInList) {
 | 
						|
							addElement( {
 | 
						|
								name : '..',
 | 
						|
								isFolder : true,
 | 
						|
								isError : false,
 | 
						|
								path : path
 | 
						|
							});
 | 
						|
						}
 | 
						|
						$.each(files, function(index, file) {
 | 
						|
							addElement($.extend(file, {
 | 
						|
								path : path
 | 
						|
							}));
 | 
						|
						});
 | 
						|
					},
 | 
						|
					dataType : 'json'
 | 
						|
				});
 | 
						|
			}
 | 
						|
		});
 | 
						|
		return this;
 | 
						|
	};
 | 
						|
})(jQuery);
 |