text: /*
   * This file is part of the TYPO3 CMS project.
   *
   * It is free software; you can redistribute it and/or modify it under
   * the terms of the GNU General Public License, either version 2
   * of the License, or any later version.
   *
   * For the full copyright and license information, please read the
   * LICENSE.txt file that was distributed with this source code.
   *
   * The TYPO3 project - inspiring people to share!
   */
  /**
   * Module: TYPO3/CMS/Extensionmanager/Main
   * main logic holding everything together, consists of multiple parts
   * ExtensionManager => Various functions for displaying the extension list / sorting
   * Repository => Various AJAX functions for TER downloads
   * ExtensionManager.Update => Various AJAX functions to display updates
   * ExtensionManager.uploadForm => helper to show the upload form
   */
  define([
  	'jquery',
  	'nprogress',
  	'TYPO3/CMS/Backend/Modal',
  	'TYPO3/CMS/Backend/SplitButtons',
  	'TYPO3/CMS/Backend/Tooltip',
  	'TYPO3/CMS/Backend/Notification',
  	'TYPO3/CMS/Backend/Severity',
  	'datatables',
  	'TYPO3/CMS/Backend/jquery.clearable'
  ], function($, NProgress, Modal, SplitButtons, Tooltip, Notification, Severity) {
  
  	/**
  	 *
  	 * @type {{identifier: {extensionlist: string, searchField: string, extensionManager: string}}}
  	 * @exports TYPO3/CMS/Extensionmanager/Main
  	 */
  	var ExtensionManager = {
  		identifier: {
  			extensionlist: '#typo3-extension-list',
  			searchField: '#Tx_Extensionmanager_extensionkey'
  		}
  	};
  
  	/**
  	 *
  	 * @returns {Object}
  	 */
  	ExtensionManager.manageExtensionListing = function() {
  		var $searchField = $(this.identifier.searchField),
  			dataTable = $(this.identifier.extensionlist).DataTable({
  				paging: false,
  				dom: 'lrtip',
  				lengthChange: false,
  				pageLength: 15,
  				stateSave: true,
  				drawCallback: this.bindExtensionListActions,
  				columns: [
  					null,
  					null,
  					{
  						type: 'extension'
  					},
  					null,
  					{
  						type: 'version'
  					}, {
  						orderable: false
  					},
  					null,
  					null
  				]
  			});
  
  		$searchField.parents('form').on('submit', function() {
  			return false;
  		});
  
  		var getVars = ExtensionManager.getUrlVars();
  
  		// restore filter
  		var currentSearch = (getVars['search'] ? getVars['search'] : dataTable.search());
  		$searchField.val(currentSearch);
  
  		$searchField.on('input', function(e) {
  			dataTable.search($(this).val()).draw();
  		});
  
  		return dataTable;
  	};
  
  	/**
  	 *
  	 */
  	ExtensionManager.bindExtensionListActions = function() {
  		$('.removeExtension').not('.transformed').each(function() {
  			var $me = $(this);
  			$me.data('href', $me.attr('href'));
  			$me.attr('href', '#');
  			$me.addClass('transformed');
  			$me.click(function() {
  				Modal.confirm(
  					TYPO3.lang['extensionList.removalConfirmation.title'],
  					TYPO3.lang['extensionList.removalConfirmation.question'],
  					Severity.error,
  					[
  						{
  							text: TYPO3.lang['button.cancel'],
  							active: true,
  							btnClass: 'btn-default',
  							trigger: function() {
  								Modal.dismiss();
  							}
  						}, {
  							text: TYPO3.lang['button.remove'],
  							btnClass: 'btn-danger',
  							trigger: function() {
  								ExtensionManager.removeExtensionFromDisk($me);
  								Modal.dismiss();
  							}
  						}
  					]
  				);
  			});
  		});
  	};
  
  	/**
  	 *
  	 * @param {Object} $extension
  	 */
  	ExtensionManager.removeExtensionFromDisk = function($extension) {
  		$.ajax({
  			url: $extension.data('href'),
  			beforeSend: function() {
  				NProgress.start();
  			},
  			success: function() {
  				location.reload();
  			},
  			complete: function() {
  				NProgress.done();
  			}
  		});
  	};
  
  	/**
  	 *
  	 * @returns {Array}
  	 */
  	ExtensionManager.getUrlVars = function() {
  		var vars = [], hash;
  		var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
  		for (var i = 0; i < hashes.length; i++) {
  			hash = hashes[i].split('=');
  			vars.push(hash[0]);
  			vars[hash[0]] = hash[1];
  		}
  		return vars;
  	};
  
  	$.fn.dataTableExt.oSort['extension-asc'] = function(a, b) {
  		return ExtensionManager.extensionCompare(a, b);
  	};
  
  	$.fn.dataTableExt.oSort['extension-desc'] = function(a, b) {
  		var result = ExtensionManager.extensionCompare(a, b);
  		return result * -1;
  	};
  
  	$.fn.dataTableExt.oSort['version-asc'] = function(a, b) {
  		var result = ExtensionManager.versionCompare(a, b);
  		return result * -1;
  	};
  
  	$.fn.dataTableExt.oSort['version-desc'] = function(a, b) {
  		return ExtensionManager.versionCompare(a, b);
  	};
  
  	/**
  	 * Special sorting for the extension version column
  	 *
  	 * @param {String} a
  	 * @param {String} b
  	 * @returns {Number}
  	 */
  	ExtensionManager.versionCompare = function(a, b) {
  		if (a === b) {
  			return 0;
  		}
  
  		var a_components = a.split(".");
  		var b_components = b.split(".");
  
  		var len = Math.min(a_components.length, b_components.length);
  
  		// loop while the components are equal
  		for (var i = 0; i < len; i++) {
  			// A bigger than B
  			if (parseInt(a_components[i]) > parseInt(b_components[i])) {
  				return 1;
  			}
  
  			// B bigger than A
  			if (parseInt(a_components[i]) < parseInt(b_components[i])) {
  				return -1;
  			}
  		}
  
  		// If one's a prefix of the other, the longer one is greaRepository.
  		if (a_components.length > b_components.length) {
  			return 1;
  		}
  
  		if (a_components.length < b_components.length) {
  			return -1;
  		}
  		// Otherwise they are the same.
  		return 0;
  	};
  
  	/**
  	 * The extension name column can contain various forms of HTML that
  	 * break a direct comparison of values
  	 *
  	 * @param {String} a
  	 * @param {String} b
  	 * @returns {Number}
  	 */
  	ExtensionManager.extensionCompare = function(a, b) {
  		var div = document.createElement("div");
  		div.innerHTML = a;
  		var aStr = div.textContent || div.innerText || a;
  
  		div.innerHTML = b;
  		var bStr = div.textContent || div.innerText || b;
  
  		return aStr.trim().localeCompare(bStr.trim());
  	}
  
  	/**
  	 *
  	 * @param {Object} data
  	 */
  	ExtensionManager.updateExtension = function(data) {
  		var message = '<h1>' + TYPO3.lang['extensionList.updateConfirmation.title'] + '</h1>';
  		message += '<h2>' + TYPO3.lang['extensionList.updateConfirmation.message'] + '</h2>';
  		message += '<form>';
  		var i = 0;
  		$.each(data.updateComments, function(version, comment) {
  			comment = comment.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1<br />$2');
  			message += '<h3><input type="radio" ' + (i === 0 ? 'checked="checked" ' : '') + 'name="version" value="' + version + '" /> ' + version + '</h3>';
  			message += '<div>' + comment + '</div>';
  			i++;
  		});
  		message += '</form>';
  
  		NProgress.done();
  
  		Modal.confirm(
  			TYPO3.lang['extensionList.updateConfirmation.questionVersionComments'],
  			message,
  			Severity.warning,
  			[
  				{
  					text: TYPO3.lang['button.cancel'],
  					active: true,
  					btnClass: 'btn-default',
  					trigger: function() {
  						Modal.dismiss();
  					}
  				}, {
  					text: TYPO3.lang['button.updateExtension'],
  					btnClass: 'btn-warning',
  					trigger: function() {
  						$.ajax({
  							url: data.url,
  							data: {
  								tx_extensionmanager_tools_extensionmanagerextensionmanager: {
  									version: $('input:radio[name=version]:checked', Modal.currentModal).val()
  								}
  							},
  							dataType: 'json',
  							beforeSend: function() {
  								NProgress.start();
  							},
  							complete: function() {
  								location.reload();
  							}
  						});
  						Modal.dismiss();
  					}
  				}
  			]
  		);
  	};
  
  	/**
  	 * configuration properties
  	 */
  	ExtensionManager.configurationFieldSupport = function() {
  		$('.t3js-emconf-offset').each(function() {
  			var $me = $(this),
  				$parent = $me.parent(),
  				id = $me.attr('id'),
  				val = $me.attr('value'),
  				valArr = val.split(',');
  
  			$me.attr('data-offsetfield-x', '#' + id + '_offset_x')
  				.attr('data-offsetfield-y', '#' + id + '_offset_y')
  				.wrap('<div class="hidden"></div>');
  
  			var elementX = '' +
  				'<div class="form-multigroup-item">' +
  					'<div class="input-group">' +
  						'<div class="input-group-addon">x</div>' +
  						'<input id="' + id + '_offset_x" class="form-control t3js-emconf-offsetfield" data-target="#' + id + '" value="' + $.trim(valArr[0]) + '">' +
  					'</div>' +
  				'</div>';
  			var elementY = '' +
  				'<div class="form-multigroup-item">' +
  					'<div class="input-group">' +
  						'<div class="input-group-addon">y</div>' +
  						'<input id="' + id + '_offset_y" class="form-control t3js-emconf-offsetfield" data-target="#' + id + '" value="' + $.trim(valArr[1]) + '">' +
  					'</div>' +
  				'</div>';
  
  			var offsetGroup = '<div class="form-multigroup-wrap">' + elementX + elementY + '</div>';
  			$parent.append(offsetGroup);
  			$parent.find('.t3js-emconf-offset').keyup(function() {
  				var $target = $($(this).data('target'));
  				$target.attr(
  					'value',
  					$($target.data('offsetfield-x')).val() + ',' + $($target.data('offsetfield-y')).val()
  				);
  			});
  		});
  
  		$('.t3js-emconf-wrap').each(function() {
  			var $me = $(this),
  				$parent = $me.parent(),
  				id = $me.attr('id'),
  				val = $me.attr('value'),
  				valArr = val.split('|');
  
  			$me.attr('data-wrapfield-start', '#' + id + '_wrap_start')
  				.attr('data-wrapfield-end', '#' + id + '_wrap_end')
  				.wrap('<div class="hidden"></div>');
  
  			var elementStart = '' +
  				'<div class="form-multigroup-item">' +
  					'<input id="' + id + '_wrap_start" class="form-control t3js-emconf-wrapfield" data-target="#' + id + '" value="' + $.trim(valArr[0]) + '">' +
  				'</div>';
  			var elementEnd = '' +
  				'<div class="form-multigroup-item">' +
  					'<input id="' + id + '_wrap_end" class="form-control t3js-emconf-wrapfield" data-target="#' + id + '" value="' + $.trim(valArr[1]) + '">' +
  				'</div>';
  
  			var wrapGroup = '<div class="form-multigroup-wrap">' + elementStart + elementEnd + '</div>';
  			$parent.append(wrapGroup);
  			$parent.find('.t3js-emconf-wrapfield').keyup(function() {
  				var $target = $($(this).data('target'));
  				$target.attr(
  					'value',
  					$($target.data('wrapfield-start')).val() + '|' + $($target.data('wrapfield-end')).val()
  				);
  			});
  		});
  	};
  
  	/**
  	 *
  	 * @type {{downloadPath: string}}
  	 */
  	var Repository = {
  		downloadPath: ''
  	};
  
  	/**
  	 *
  	 */
  	Repository.initDom = function() {
  		NProgress.configure({parent: '.module-loading-indicator', showSpinner: false});
  
  		$('#terTable').DataTable({
  			lengthChange: false,
  			pageLength: 15,
  			stateSave: false,
  			info: false,
  			paging: false,
  			searching: false,
  			ordering: false,
  			drawCallback: Repository.bindDownload
  		});
  
  		$('#terVersionTable').DataTable({
  			lengthChange: false,
  			pageLength: 15,
  			stateSave: false,
  			info: false,
  			paging: false,
  			searching: false,
  			drawCallback: Repository.bindDownload,
  			order: [
  				[2, 'asc']
  			],
  			columns: [
  				{orderable: false},
  				null,
  				{type: 'version'},
  				null,
  				null,
  				null
  			]
  		});
  
  		$('#terSearchTable').DataTable({
  			paging: false,
  			lengthChange: false,
  			stateSave: false,
  			searching: false,
  			language: {
  				search: 'Filter results:'
  			},
  			ordering: false,
  			drawCallback: Repository.bindDownload
  		});
  
  		Repository.bindDownload();
  		Repository.bindSearchFieldResetter();
  	};
  
  	/**
  	 *
  	 */
  	Repository.bindDownload = function() {
  		var installButtons = $('.downloadFromTer form.download button[type=submit]');
  		installButtons.off('click');
  		installButtons.on('click', function(event) {
  			event.preventDefault();
  			var url = $(event.currentTarget.form).attr('data-href');
  			Repository.downloadPath = $(event.currentTarget.form).find('input.downloadPath:checked').val();
  			$.ajax({
  				url: url,
  				dataType: 'json',
  				beforeSend: function() {
  					NProgress.start();
  				},
  				success: Repository.getDependencies
  			});
  		});
  	};
  
  	/**
  	 *
  	 * @param {Object} data
  	 * @returns {Boolean}
  	 */
  	Repository.getDependencies = function(data) {
  		NProgress.done();
  		if (data.hasDependencies) {
  			Modal.confirm(data.title, data.message, Severity.info, [
  				{
  					text: TYPO3.lang['button.cancel'],
  					active: true,
  					btnClass: 'btn-default',
  					trigger: function() {
  						Modal.dismiss();
  					}
  				}, {
  					text: TYPO3.lang['button.resolveDependencies'],
  					btnClass: 'btn-info',
  					trigger: function() {
  						Repository.getResolveDependenciesAndInstallResult(data.url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager[downloadPath]=' + Repository.downloadPath);
  						Modal.dismiss();
  					}
  				}
  			]);
  		} else {
  			if(data.hasErrors) {
  				Notification.error(data.title, data.message, 15);
  			} else {
  				Repository.getResolveDependenciesAndInstallResult(data.url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager[downloadPath]=' + Repository.downloadPath);
  			}
  		}
  		return false;
  	};
  
  	/**
  	 *
  	 * @param {String} url
  	 */
  	Repository.getResolveDependenciesAndInstallResult = function(url) {
  		$.ajax({
  			url: url,
  			dataType: 'json',
  			beforeSend: function() {
  				NProgress.start();
  			},
  			success: function (data) {
  				if (data.errorCount > 0) {
  					Modal.confirm(data.errorTitle, data.errorMessage, Severity.error, [
  						{
  							text: TYPO3.lang['button.cancel'],
  							active: true,
  							btnClass: 'btn-default',
  							trigger: function() {
  								Modal.dismiss();
  							}
  						}, {
  							text: TYPO3.lang['button.resolveDependenciesIgnore'],
  							btnClass: 'btn-danger disabled t3js-dependencies',
  							trigger: function() {
  								if (!$(this).hasClass('disabled')) {
  									Repository.getResolveDependenciesAndInstallResult(data.skipDependencyUri);
  									Modal.dismiss();
  								}
  							}
  						}
  					]);
  					Modal.currentModal.on('shown.bs.modal', function() {
  						var $actionButton = Modal.currentModal.find('.t3js-dependencies');
  						$('input[name="unlockDependencyIgnoreButton"]', Modal.currentModal).on('change', function() {
  							$actionButton.toggleClass('disabled', !$(this).prop('checked'));
  						});
  					});
  				} else {
  					var successMessage = TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.message' + data.installationTypeLanguageKey].replace(/\{0\}/g, data.extension);
  
  					successMessage += '\n' + TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.header'] + ': ';
  					$.each(data.result, function(index, value) {
  						successMessage += '\n\n' + TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.item'] + ' ' + index + ': ';
  						$.each(value, function(extkey) {
  							successMessage += '\n* ' + extkey
  						});
  					});
  					Notification.info(TYPO3.lang['extensionList.dependenciesResolveFlashMessage.title' + data.installationTypeLanguageKey].replace(/\{0\}/g, data.extension), successMessage, 15);
  					top.TYPO3.ModuleMenu.App.refreshMenu();
  				}
  			},
  			complete: function() {
  				NProgress.done();
  			}
  		});
  	};
  
  	/**
  	 *
  	 */
  	Repository.bindSearchFieldResetter = function() {
  		var $searchFields = $('.typo3-extensionmanager-searchTerForm input[type="text"]');
  		var searchResultShown = ('' !== $searchFields.first().val());
  
  		$searchFields.clearable(
  			{
  				onClear: function() {
  					if (searchResultShown) {
  						$(this).closest('form').submit();
  					}
  				}
  			}
  		);
  	};
  
  	/**
  	 *
  	 * @type {{identifier: {extensionTable: string, terUpdateAction: string, pagination: string, splashscreen: string, terTableWrapper: string, terTableDataTableWrapper: string}}}
  	 */
  	ExtensionManager.Update = {
  		identifier: {
  			extensionTable: '#terTable',
  			terUpdateAction: '.update-from-ter',
  			pagination: '.pagination-wrap',
  			splashscreen: '.splash-receivedata',
  			terTableWrapper: '#terTableWrapper',
  			terTableDataTableWrapper: '#terTableWrapper .dataTables_wrapper'
  		}
  	};
  
  	/**
  	 * Register "update from ter" action
  	 */
  	ExtensionManager.Update.initializeEvents = function() {
  		$(ExtensionManager.Update.identifier.terUpdateAction).each(function() {
  
  			// "this" is the form which updates the extension list from
  			// TER on submit
  			var $me = $(this),
  				updateURL = $(this).attr('action');
  
  			$me.attr('action', '#');
  			$me.submit(function() {
  				// Force update on click.
  				ExtensionManager.Update.updateFromTer(updateURL, true);
  
  				// Prevent normal submit action.
  				return false;
  			});
  
  			// This might give problems when there are more "update"-buttons,
  			// each one would trigger a TER-ExtensionManager.Update.
  			ExtensionManager.Update.updateFromTer(updateURL, false);
  		});
  	};
  
  	/**
  	 *
  	 * @param {String} url
  	 * @param {Boolean} forceUpdate
  	 */
  	ExtensionManager.Update.updateFromTer = function(url, forceUpdate) {
  		if (forceUpdate) {
  			url = url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager%5BforceUpdateCheck%5D=1';
  		}
  
  		// Hide triggers for TER update
  		$(ExtensionManager.Update.identifier.terUpdateAction).addClass('is-hidden');
  
  		// Hide extension table
  		$(ExtensionManager.Update.identifier.extensionTable).hide();
  
  		// Show loaders
  		$(ExtensionManager.Update.identifier.splashscreen).addClass('is-shown');
  		$(ExtensionManager.Update.identifier.terTableDataTableWrapper).addClass('is-loading');
  		$(ExtensionManager.Update.identifier.pagination).addClass('is-loading');
  
  		var reload = false;
  
  		$.ajax({
  			url: url,
  			dataType: 'json',
  			cache: false,
  			beforeSend: function() {
  				NProgress.start();
  			},
  			success: function(data) {
  				// Something went wrong, show message
  				if (data.errorMessage.length) {
  					Notification.error(TYPO3.lang['extensionList.updateFromTerFlashMessage.title'], data.errorMessage, 10);
  				}
  
  				// Message with latest updates
  				var $lastUpdate = $(ExtensionManager.Update.identifier.terUpdateAction + ' .time-since-last-update');
  				$lastUpdate.text(data.timeSinceLastUpdate);
  				$lastUpdate.attr(
  					'title',
  					TYPO3.lang['extensionList.updateFromTer.lastUpdate.timeOfLastUpdate'] + data.lastUpdateTime
  				);
  
  				if (data.updated) {
  					// Reload page
  					reload = true;
  					window.location.replace(window.location.href);
  				}
  			},
  			error: function(jqXHR, textStatus, errorThrown) {
  				// Create an error message with diagnosis info.
  				var errorMessage = textStatus + '(' + errorThrown + '): ' + jqXHR.responseText;
  
  				Notification.warning(
  					TYPO3.lang['extensionList.updateFromTerFlashMessage.title'],
  					errorMessage,
  					10
  				);
  			},
  			complete: function() {
  				NProgress.done();
  
  				if (!reload) {
  					// Hide loaders
  					$(ExtensionManager.Update.identifier.splashscreen).removeClass('is-shown');
  					$(ExtensionManager.Update.identifier.terTableDataTableWrapper).removeClass('is-loading');
  					$(ExtensionManager.Update.identifier.pagination).removeClass('is-loading');
  
  					// Show triggers for TER-update
  					$(ExtensionManager.Update.identifier.terUpdateAction).removeClass('is-hidden');
  
  					// Show extension table
  					$(ExtensionManager.Update.identifier.extensionTable).show();
  				}
  			}
  		});
  	};
  
  	/**
  	 *
  	 */
  	ExtensionManager.Update.transformPaginatorToAjax = function () {
  		$(ExtensionManager.Update.identifier.pagination + ' a').each(function() {
  			var $me = $(this);
  			$me.data('href', $(this).attr('href'));
  			$me.attr('href', '#');
  			$me.click(function() {
  				var $terTableWrapper = $(ExtensionManager.Update.identifier.terTableWrapper);
  				NProgress.start();
  				$.ajax({
  					url: $(this).data('href'),
  					dataType: 'json',
  					success: function(data) {
  						$terTableWrapper.html(data);
  						ExtensionManager.Update.transformPaginatorToAjax();
  					},
  					complete: function() {
  						NProgress.done();
  					}
  				});
  			});
  		});
  	};
  
  	/**
  	 * show the uploading form
  	 */
  	ExtensionManager.UploadForm = {
  		expandedUploadFormClass: 'transformed'
  	};
  
  	/**
  	 *
  	 */
  	ExtensionManager.UploadForm.initializeEvents = function() {
  		// Show upload form
  		$(document).on('click', '.t3js-upload', function(event) {
  			var $me = $(this),
  				$uploadForm = $('.uploadForm');
  
  			event.preventDefault();
  			if($me.hasClass(ExtensionManager.UploadForm.expandedUploadFormClass)) {
  				$uploadForm.stop().slideUp();
  				$me.removeClass(ExtensionManager.UploadForm.expandedUploadFormClass);
  			} else {
  				$me.addClass(ExtensionManager.UploadForm.expandedUploadFormClass);
  				$uploadForm.stop().slideDown();
  
  				$.ajax({
  					url: $me.attr('href'),
  					dataType: 'html',
  					success: function (data) {
  						$uploadForm.html(data);
  					}
  				});
  			}
  		});
  	};
  
  	$(function() {
  		var dataTable = ExtensionManager.manageExtensionListing();
  
  		$(document).on('click', '.onClickMaskExtensionManager', function() {
  			NProgress.start();
  		}).on('click', 'a[data-action=update-extension]', function(e) {
  			e.preventDefault();
  			$.ajax({
  				url: $(this).attr('href'),
  				dataType: 'json',
  				beforeSend: function() {
  					NProgress.start();
  				},
  				success: ExtensionManager.updateExtension
  			});
  		}).on('change', 'input[name=unlockDependencyIgnoreButton]', function() {
  			var $actionButton = $('.t3js-dependencies');
  			$actionButton.toggleClass('disabled', !$(this).prop('checked'));
  		});
  
  		$(ExtensionManager.identifier.searchField).clearable({
  			onClear: function() {
  				dataTable.search('').draw();
  			}
  		});
  
  		$(document).on('click', '.t3-button-action-installdistribution', function() {
  			NProgress.start();
  		});
  
  		ExtensionManager.configurationFieldSupport();
  
  		SplitButtons.addPreSubmitCallback(function(e) {
  			if ($(e.target).hasClass('t3js-save-close')) {
  				$('#configurationform').append($('<input />', {type: 'hidden', name: 'tx_extensionmanager_tools_extensionmanagerextensionmanager[action]', value: 'saveAndClose'}));
  			}
  		});
  
  		// initialize the repository
  		Repository.initDom();
  
  		ExtensionManager.Update.initializeEvents();
  		ExtensionManager.UploadForm.initializeEvents();
  
  		Tooltip.initialize('#typo3-extension-list [title]', {
  			delay: {
  				show: 500,
  				hide: 100
  			},
  			trigger: 'hover',
  			container: 'body'
  		});
  	});
  
  	if (typeof TYPO3.ExtensionManager === 'undefined') {
  		TYPO3.ExtensionManager = ExtensionManager;
  	}
  
  	return ExtensionManager;
  });
  