diff options
28 files changed, 850 insertions, 500 deletions
| diff --git a/phpBB/assets/javascript/plupload.js b/phpBB/assets/javascript/plupload.js index 1befb88eb6..6b37b009a4 100644 --- a/phpBB/assets/javascript/plupload.js +++ b/phpBB/assets/javascript/plupload.js @@ -1,38 +1,77 @@  plupload.addI18n(phpbb.plupload.i18n); -plupload.attachment_data = []; +phpbb.plupload.ids = []; + +(function($) {  // Avoid conflicts with other libraries + +"use strict";  /** - * Returns the index of the plupload.attachment_data array where the given - * attach id appears + * Set up the uploader.   * - * @param int id The attachment id of the file + * @return undefined + */ +phpbb.plupload.initialize = function() { +	phpbb.plupload.form = $(phpbb.plupload.config.form_hook)[0], +	phpbb.plupload.rowTpl = $('#attach-row-tpl')[0].outerHTML; + +	// Hide the basic upload panel and remove the attach row template. +	$('#attach-row-tpl, #attach-panel-basic').remove(); +	// Show multi-file upload options. +	$('#attach-panel-multi').show(); + +	// Set attachment data. +	phpbb.plupload.setData(phpbb.plupload.data); +	phpbb.plupload.updateMultipartParams(phpbb.plupload.getSerializedData()); + +	// Initialize the Plupload uploader. +	uploader.init(); + +	// Point out the drag-and-drop zone if it's supported. +	if (!uploader.features.dragdrop) { +		$('#drag-n-drop-message').show(); +	} +}; + +/** + * Unsets all elements in the object uploader.settings.multipart_params whose keys + * begin with 'attachment_data['   * - * @return bool	Returns false if the id cannot be found - * @return int	Returns the index in the main array where the attachment id - * 	was found + * @return undefined   */ -function phpbb_plupload_find_attachment_idx(id) { -	var data = plupload.attachment_data; -	for (var i = 0; i < data.length; i++) { -		if (data[i].attach_id == id) { -			return i; +phpbb.plupload.clearParams = function() { +	var obj = uploader.settings.multipart_params; +	for (var key in obj) { +		if (!obj.hasOwnProperty(key) || key.indexOf('attachment_data[') !== 0) { +			continue;  		} + +		delete uploader.settings.multipart_params[key];  	} +}; -	return false; -} +/** + * Update uploader.settings.multipart_params object with new data. + * + * @param object obj + * @return undefined + */ +phpbb.plupload.updateMultipartParams = function(obj) { +	uploader.settings.multipart_params = $.extend( +		uploader.settings.multipart_params, +		obj +	); +};  /** - * Converts an array of objects into an object that PHP would expect as POST - * data + * Convert the array of attachment objects into an object that PHP would expect as POST data.   *   * @return object An object in the form 'attachment_data[i][key]': value as   * 	expected by the server   */ -function phpbb_plupload_attachment_data_serialize() { +phpbb.plupload.getSerializedData = function() {  	var obj = {}; -	for (var i = 0; i < plupload.attachment_data.length; i++) { -		var datum = plupload.attachment_data[i]; +	for (var i = 0; i < phpbb.plupload.data.length; i++) { +		var datum = phpbb.plupload.data[i];  		for (var key in datum) {  			if (!datum.hasOwnProperty(key)) {  				continue; @@ -41,264 +80,596 @@ function phpbb_plupload_attachment_data_serialize() {  			obj['attachment_data[' + i + '][' + key + ']'] = datum[key];  		}  	} -  	return obj; -} +};  /** - * Unsets all elements in an object whose keys begin with 'attachment_data[' + * Get the index from the phpbb.plupload.data array where the given + * attachment id appears.   * - * @param object The object to be cleared + * @param int attach_id The attachment id of the file. + * @return bool	Returns false if the id cannot be found. + * @return int	Returns the index of the file if it exists. + */ +phpbb.plupload.getIndex = function(attach_id) { +	var index = phpbb.plupload.ids.indexOf(Number(attach_id)); +	return (index !== -1) ? index : false; +}; + +/** + * Set the data in phpbb.plupload.data and phpbb.plupload.ids arrays. + *  + * @param array data	Array containing the new data to use. In the form of  + * array(index => object(property: value). Requires attach_id to be one of the object properties.   *   * @return undefined   */ -function phpbb_plupload_clear_params(obj) { -	for (var key in obj) { -		if (!obj.hasOwnProperty(key) || key.indexOf('attachment_data[') !== 0) { -			continue; -		} +phpbb.plupload.setData = function(data) { +	// Make sure that the array keys are reset. +	phpbb.plupload.ids = phpbb.plupload.data = []; +	phpbb.plupload.data = data; -		delete obj[key]; +	for (var i = 0; i < data.length; i++) { +		phpbb.plupload.ids.push(Number(data[i].attach_id));  	} -} +};  /** - * Update hidden attachment inputs in posting form - * Pre-existing hidden inputs will be removed by comparing the old attachment - * data (old_data) to the new attachment data (data) that has been sent back - * by plupload. - * - * @param object form Posting form - * @param object data Current attachment_data - * @param object old_date Previous attachment_data (before submission) - * - * @return void + * Update the attachment data in the HTML and the phpbb & phpbb.plupload objects. + *  + * @param array data		Array containing the new data to use. + * @param string action		The action that required the update. Used to update the inline attachment bbcodes. + * @param int index			The index from phpbb.plupload_ids that was affected by the action. + * @param array downloadUrl	Optional array of download urls to update. + * @return undefined   */ -phpbb.update_hidden_attachment_inputs = function(form, data, old_data) { -	// Update already existing hidden inputs -	for (var i = 0; i < form.length; i++) { -		if (data.hasOwnProperty(form[i].name)) { -			form[i].value = data[form[i].name]; -			delete data[form[i].name]; -		} else if (typeof old_data !== 'undefined' && old_data.hasOwnProperty(form[i].name)) { -			var inputRegex = /\b^[a-z_]+[+[0-9]+]/; -			var inputName = inputRegex.exec(form[i].name); -			if (typeof inputName !== 'undefined' && inputName[0] !== '') { -				$("input[type='hidden'][name^='" + inputName[0] + "']").remove(); -			} -		} +phpbb.plupload.update = function(data, action, index, downloadUrl) { + +	phpbb.plupload.updateBbcode(action, index); +	phpbb.plupload.setData(data); +	phpbb.plupload.updateRows(downloadUrl); +	phpbb.plupload.clearParams(); +	phpbb.plupload.updateMultipartParams(phpbb.plupload.getSerializedData()); +}; + +/** + * Update the relevant elements and hidden data for all attachments. + *  + * @param array downloadUrl	Optional array of download urls to update. + * @return undefined + */ +phpbb.plupload.updateRows = function(downloadUrl) { +	for (var i = 0; i < phpbb.plupload.ids.length; i++) { +		phpbb.plupload.updateRow(i, downloadUrl);  	} +}; -	// Append new inputs -	for (var key in data) { -		if (!data.hasOwnProperty(key)) { -			continue; -		} +/** + * Insert a row for a new attachment. This expects an HTML snippet in the HTML + * using the id "attach-row-tpl" to be present. This snippet is cloned and the + * data for the file inserted into it. The row is then appended or prepended to + * #file-list based on the attach_order setting. + *  + * @param object file	Plupload file object for the new attachment. + * @return undefined + */ +phpbb.plupload.insertRow = function(file) { +	var row = $(phpbb.plupload.rowTpl); + +	row.attr('id', file.id); +	row.find('.file-name').html(file.name); +	row.find('.file-size').html(plupload.formatSize(file.size)); + +	if (phpbb.plupload.order == 'desc') { +		$('#file-list').prepend(row); +	} else { +		$('#file-list').append(row); +	} +}; + +/** + * Update the relevant elements and hidden data for an attachment. + *  + * @param int index	The index from phpbb.plupload.ids of the attachment to edit. + * @param array downloadUrl	Optional array of download urls to update.  + * @return undefined + */ +phpbb.plupload.updateRow = function(index, downloadUrl) { +	var attach = phpbb.plupload.data[index], +		row = $('[data-attach-id="' + attach.attach_id + '"]'); + +	// Add the link to the file +	if (typeof downloadUrl !== 'undefined' && typeof downloadUrl[index] !== 'undefined') { +		var url = downloadUrl[index].replace('&', '&'), +			link = $('<a></a>'); + +		link.attr('href', url).html(attach.real_filename); +		row.find('.file-name').html(link)	 +	} + +	row.find('textarea').attr('name', 'comment_list[' + index + ']'); +	phpbb.plupload.updateHiddenData(row, attach, index); +}; + +/** + * Update hidden input data for an attachment. + * + * @param object row	jQuery object for the attachment row. + * @param object attach	Attachment data object from phpbb.plupload.data + * @param int index		Attachment index from phpbb.plupload.ids + * @return undefined + */ +phpbb.plupload.updateHiddenData = function(row, attach, index) { +	row.find('input[type="hidden"]').remove(); +	for (var key in attach) {  		var input = $('<input />')  			.attr('type', 'hidden') -			.attr('name', key) -			.attr('value', data[key]); -		$(form).append(input); +			.attr('name', 'attachment_data[' + index + '][' + key +']') +			.attr('value', attach[key]); +		$('textarea', row).after(input);  	} -} +}; -jQuery(function($) { -	$(phpbb.plupload.config.element_hook).pluploadQueue(phpbb.plupload.config); -	var uploader = $(phpbb.plupload.config.element_hook).pluploadQueue(); - -	// Check the page for already-existing attachment data and add it to the -	// array -	var form = $(phpbb.plupload.config.form_hook)[0]; -	for (var i = 0; i < form.length; i++) { -		if (form[i].name.indexOf('attachment_data[') !== 0) { -			continue; -		} -		 -		var matches = form[i].name.match(/\[(\d+)\]\[([^\]]+)\]/); -		var index = matches[1]; -		var property = matches[2]; -		 -		if (!plupload.attachment_data[index]) { -			plupload.attachment_data[index] = {}; -		} -		 -		plupload.attachment_data[index][property] = form[i].value; -		uploader.settings.multipart_params[form[i].name] = form[i].value; +/** + * Deleting a file removes it from the queue and fires an AJAX event to the + * server to tell it to remove the temporary attachment. The server + * responds with the updated attachment data list so that any future + * uploads can maintain state with the server + * + * @param object row	jQuery object for the attachment row. + * @param int attachId	Attachment id of the file to be removed. + * + * @return undefined + */ +phpbb.plupload.deleteFile = function(row, attachId) { +	// If there's no attach id, then the file hasn't been uploaded. Simply delete the row. +	if (typeof attachId === 'undefined') { +		row.slideUp(100, function() { +			row.remove(); +			phpbb.plupload.hideEmptyList(); +		});  	} -	/** -	 * Fires before a given file is about to be uploaded. This allows us to -	 * send the real filename along with the chunk. This is necessary because -	 * for some reason the filename is set to 'blob' whenever a file is chunked -	 * -	 * @param object up		The plupload.Uploader object -	 * @param object file	The plupload.File object that is about to be -	 * 	uploaded -	 * -	 * @return undefined -	 */ -	uploader.bind('BeforeUpload', function(up, file) { -		up.settings.multipart_params = $.extend( -			up.settings.multipart_params, -			{'real_filename': file.name} -		); -	}); +	var index = phpbb.plupload.getIndex(attachId); +	row.find('.file-status').toggleClass('file-uploaded file-working'); -	/** -	 * Fired when a single chunk of any given file is uploaded. This parses the -	 * response from the server and checks for an error. If an error occurs it -	 * is reported to the user and the upload of this particular file is halted -	 * -	 * @param object up			The plupload.Uploader object -	 * @param object file		The plupload.File object whose chunk has just -	 * 	been uploaded -	 * @param object response	The response object from the server -	 * -	 * @return undefined -	 */ -	uploader.bind('ChunkUploaded', function(up, file, response) { -		if (response.chunk >= response.chunks - 1) { -			return; -		} +	if (index === false) { +		return; +	} +	var fields = {}; +	fields['delete_file[' + index + ']'] = 1; +	var always = function() { +		row.find('.file-status').removeClass('file-working'); +	}; + +	var done = function(response) {  		var json = {};  		try { -			json = $.parseJSON(response.response); +			json = $.parseJSON(response);  		} catch (e) { -			file.status = plupload.FAILED; -			up.trigger('FileUploaded', file, { -				response: JSON.stringify({ -					error: { -						message: 'Error parsing server response.' -					} -				}) -			}); +			return;  		} -		if (json.error) { -			file.status = plupload.FAILED; -			up.trigger('FileUploaded', file, { -				response: JSON.stringify({ -					error: { -						message: json.error.message -					} -				}) -			}); +		// trigger_error() was called which likely means a permission error was encountered. +		if (typeof response.title !== 'undefined') { +			uploader.trigger('Error', {message: response.message}); +			// We will have to assume that the deletion failed. So leave the file status as uploaded. +			row.find('.file-status').toggleClass('file-uploaded'); + +			return;  		} -	}); +		phpbb.plupload.update(response, 'removal', index); +		// Check if the user can upload files now if he had reached the max files limit. +		phpbb.plupload.handleMaxFilesReached(); -	/** -	 * Fires when an entire file has been uploaded. It checks for errors -	 * returned by the server otherwise parses the list of attachment data and -	 * appends it to the next file upload so that the server can maintain state -	 * with regards to the attachments in a given post -	 * -	 * @param object up			The plupload.Uploader object -	 * @param object file		The plupload.File object that has just been -	 * 	uploaded -	 * @param string response	The response string from the server -	 * -	 * @return undefined -	 */ -	uploader.bind('FileUploaded', function(up, file, response) { -		var json = {}; -		try { -			json = $.parseJSON(response.response); -		} catch (e) { -			file.status = plupload.FAILED; -			file.error = 'Error parsing server response.' +		if (row.attr('id')) { +			var file = uploader.getFile(row.attr('id')); +			uploader.removeFile(file); +		} +		row.slideUp(100, function() { +			row.remove(); +			// Hide the file list if it's empty now. +			phpbb.plupload.hideEmptyList(); +		}); +		uploader.trigger('FilesRemoved'); +	}; + +	$.ajax(phpbb.plupload.config.url, { +		type: 'POST', +		data: $.extend(fields, phpbb.plupload.getSerializedData()), +		headers: {'X-PHPBB-USING-PLUPLOAD': '1', 'X-Requested-With': 'XMLHttpRequest'} +	}) +	.always(always) +	.done(done); +}; + +/** + * Check the attachment list and hide its container if it's empty. + * + * @return undefined + */ +phpbb.plupload.hideEmptyList = function() { +	if (!$('#file-list').children().length) { +		$('#file-list-container').slideUp(100); +	} +} + +/** + * Update the indices used in inline attachment bbcodes. This ensures that the bbcodes + * correspond to the correct file after a file is added or removed. This should be called  + * before the phpbb.plupload,data and phpbb.plupload.ids arrays are updated, otherwise it will + * not work correctly. + * + * @param string action	The action that occurred -- either "addition" or "removal" + * @param int index		The index of the attachment from phpbb.plupload.ids that was affected. + * + * @return undefined + */ +phpbb.plupload.updateBbcode = function(action, index) { +	var	textarea = $(phpbb.plupload.form).find('textarea[name="message"]'), +		text = textarea.val(), +		removal = (action === 'removal'); + +	// Return if the bbcode isn't used at all. +	if (text.indexOf('[attachment=') === -1) { +		return; +	} + +	// Private function used to replace the bbcode. +	var updateBbcode = function(match, fileName) { +		// Remove the bbcode if the file was removed. +		if (removal && index === i) { +			return '';  		} +		var newIndex = i + ((removal) ? -1 : 1); +		return '[attachment=' + newIndex +']' + fileName + '[/attachment]'; +	}; -		if (json.error) { -			file.status = plupload.FAILED; -			file.error = json.error.message; -		} else if (file.status === plupload.DONE) { -			plupload.attachment_data = json; -			file.attachment_data = json[0]; -			up.settings.multipart_params = $.extend( -				up.settings.multipart_params, -				phpbb_plupload_attachment_data_serialize() -			); +	// Private function used to generate search regexp +	var searchRegexp = function(index) { +		return new RegExp('\\[attachment=' + index + '\\](.*?)\\[\\/attachment\\]', 'g'); +	} +	// The update order of the indices is based on the action taken to ensure that we don't corrupt +	// the bbcode index by updating it several times as we move through the loop. +	// Removal loop starts at the removed index and moves to the end of the array. +	// Addition loop starts at the end of the array and moves to the added index at 0. +	var searchLoop = function() { +		if (typeof i === 'undefined') { +			i = (removal) ? index : phpbb.plupload.ids.length - 1; +		} +		return (removal) ? (i < phpbb.plupload.ids.length): (i >= index); +	} +	var i; + +	while (searchLoop()) { +		text = text.replace(searchRegexp(i), updateBbcode); +		(removal) ? i++ : i--; +	} +	textarea.val(text); +}; + +/** + * Get Plupload file objects based on their upload status. + * + * @param int status Plupload status - plupload.DONE, plupload.FAILED, plupload.QUEUED, + * plupload.STARTED, plupload.STOPPED + * + * @return Returns an array of the Plupload file objects matching the status. + */ +phpbb.plupload.getFilesByStatus = function(status) { +	var files = []; + +	$.each(uploader.files, function(i, file) { +		if (file.status === status) { +			files.push(file);  		}  	}); +	return files; +} -	/** -	 * Fires when the entire queue of files have been uploaded. It resets the -	 * 'add files' button to allow more files to be uploaded and also attaches -	 * several events to each row of the currently-uploaded files to facilitate -	 * deleting any one of the files. -	 * -	 * Deleting a file removes it from the queue and fires an ajax event to the -	 * server to tell it to remove the temporary attachment. The server -	 * responds with the updated attachment data list so that any future -	 * uploads can maintain state with the server -	 * -	 * @param object up		The plupload.Uploader object -	 * @param array files	An array of plupload.File objects that have just -	 * 	been uploaded as part of a queue -	 * -	 * @return undefined -	 */ -	uploader.bind('UploadComplete', function(up, files) { -		$('.plupload_upload_status').css('display', 'none'); -		$('.plupload_buttons').css('display', 'block'); - -		// Insert a bunch of hidden input elements containing the attachment -		// data so that the save/preview/submit buttons work as expected. -		var form = $(phpbb.plupload.config.form_hook)[0]; -		var data = phpbb_plupload_attachment_data_serialize(); - -		phpbb.update_hidden_attachment_inputs(form, data); - -		files.forEach(function(file) { -			if (file.status !== plupload.DONE) { -				var click = function(evt) { -					alert(file.error); -				} +/** + * Check whether the user has reached the maximun number of files that he's allowed + * to upload. If so, disables the uploader and marks the queued files as failed. Otherwise + * makes sure that the uploader is enabled. + * + * @return bool Returns true if the limit has been reached. False if otherwise. + */ +phpbb.plupload.handleMaxFilesReached = function() { +	// If there is no limit, the user is an admin or moderator. +	if (!phpbb.plupload.maxFiles) { +		return false; +	} -				$('#' + file.id).attr('title', file.error); -				$('#' + file.id).click(click); +	if (phpbb.plupload.maxFiles <= phpbb.plupload.ids.length) { +		// Fail the rest of the queue. +		phpbb.plupload.markQueuedFailed(phpbb.plupload.lang.TOO_MANY_ATTACHMENTS); +		// Disable the uploader. +		phpbb.plupload.disableUploader(); +		uploader.trigger('Error', {message: phpbb.plupload.lang.TOO_MANY_ATTACHMENTS}); + +		return true; +	} else if(phpbb.plupload.maxFiles > phpbb.plupload.ids.length) { +		// Enable the uploader if the user is under the limit +		phpbb.plupload.enableUploader(); +	} +	return false; +} + +/** + * Disable the uploader + * + * @return undefined + */ +phpbb.plupload.disableUploader = function() { +	$('#add_files').addClass('disabled'); +	uploader.disableBrowse(); +} + +/** + * Enable the uploader + * + * @return undefined + */ +phpbb.plupload.enableUploader = function() { +	$('#add_files').removeClass('disabled'); +	uploader.disableBrowse(false); +} + +/** + * Mark all queued files as failed. + * + * @param string error Error message to present to the user. + * @return undefined + */ +phpbb.plupload.markQueuedFailed = function(error) { +	var files = phpbb.plupload.getFilesByStatus(plupload.QUEUED); + +	$.each(files, function(i, file) { +		$('#' + file.id).find('.file-progress').hide(); +		phpbb.plupload.fileError(file, error); +	}); +} + +/** + * Marks a file as failed and sets the error message for it. + * + * @param object file	Plupload file object that failed. + * @param string error	Error message to present to the user. + * @return undefined + */ +phpbb.plupload.fileError = function(file, error) { +	file.status = plupload.FAILED; +	file.error = error; +	$('#' + file.id).find('.file-status').addClass('file-error').attr({'data-error-title': phpbb.plupload.lang.ERROR, 'data-error-message': error}); +} -				return; -			} -			var click = function(evt) { -				$(evt.target).find('a').addClass('working'); - -				// The index is always found because file.attachment_data is -				// just an element of plupload.attachment_data -				var idx = phpbb_plupload_find_attachment_idx(file.attachment_data.attach_id); -				var fields = {}; -				fields['delete_file[' + idx + ']'] = 1; - -				var always = function() { -					$(evt.target).find('a').removeClass('working'); -				}; - -				var done = function(response) { -					up.removeFile(file); -					plupload.attachment_data = response; -					phpbb.update_hidden_attachment_inputs(form, phpbb_plupload_attachment_data_serialize(), data); -					phpbb_plupload_clear_params(up.settings.multipart_params); -					up.settings.multipart_params = $.extend( -						up.settings.multipart_params, -						phpbb_plupload_attachment_data_serialize() -					); -				}; -				 -				$.ajax(phpbb.plupload.config.url, { -					type: 'POST', -					data: $.extend(fields, phpbb_plupload_attachment_data_serialize()), -					headers: {'X-PHPBB-USING-PLUPLOAD': '1'} -				}) -				.always(always) -				.done(done); -			}; -			 -			$('#' + file.id) -			.addClass('can_delete') -			.click(click); + + +/** + * Set up the Plupload object and get some basic data. + */ +var	uploader = new plupload.Uploader(phpbb.plupload.config); +phpbb.plupload.initialize(); + + + + +/** + * Insert inline attachment bbcode. + */ + $('#file-list').on('click', '.file-inline-bbcode', function(e) { +	var attachId = $(this).parents('.attach-row').attr('data-attach-id'), +		index = phpbb.plupload.getIndex(attachId); + +	attach_inline(index, phpbb.plupload.data[index].real_filename);	 +	e.preventDefault(); +}); + +/** + * Delete a file. + */ +$('#file-list').on('click', '.file-delete', function(e) { +	var row = $(this).parents('.attach-row'), +		attachId = row.attr('data-attach-id'); + +	phpbb.plupload.deleteFile(row, attachId); +	e.preventDefault(); +}); + +/** + * Display the error message for a particular file when the error icon is clicked. + */ +$('#file-list').on('click', '.file-error', function(e) { +	phpbb.alert($(this).attr('data-error-title'), $(this).attr('data-error-message')); +	e.preventDefault(); +}); + +/** + * Fires when an error occurs. + */ +uploader.bind('Error', function(up, error) { +	// The error message that Plupload provides for these is vague, so we'll be more specific. +	if (error.code === plupload.FILE_EXTENSION_ERROR) { +		error.message = plupload.translate('Invalid file extension:') + ' ' + error.file.name; +	} else if (error.code === plupload.FILE_SIZE_ERROR) { +		error.message = plupload.translate('File too large:') + ' ' + error.file.name; +	} +	phpbb.alert(phpbb.plupload.lang.ERROR, error.message); +}); + +/** + * Fires before a given file is about to be uploaded. This allows us to + * send the real filename along with the chunk. This is necessary because + * for some reason the filename is set to 'blob' whenever a file is chunked + * + * @param object up		The plupload.Uploader object + * @param object file	The plupload.File object that is about to be + * 	uploaded + * + * @return undefined + */ +uploader.bind('BeforeUpload', function(up, file) { +	if (phpbb.plupload.handleMaxFilesReached()) { +		return; +	} + +	phpbb.plupload.updateMultipartParams({'real_filename': file.name}); +}); + +/** + * Fired when a single chunk of any given file is uploaded. This parses the + * response from the server and checks for an error. If an error occurs it + * is reported to the user and the upload of this particular file is halted + * + * @param object up			The plupload.Uploader object + * @param object file		The plupload.File object whose chunk has just + * 	been uploaded + * @param object response	The response object from the server + * + * @return undefined + */ +uploader.bind('ChunkUploaded', function(up, file, response) { +	if (response.chunk >= response.chunks - 1) { +		return; +	} + +	var json = {}; +	try { +		json = $.parseJSON(response.response); +	} catch (e) { +		file.status = plupload.FAILED; +		up.trigger('FileUploaded', file, { +			response: JSON.stringify({ +				error: { +					message: 'Error parsing server response.' +				} +			})  		}); +	} + +	// If trigger_error() was called, then a permission error likely occurred. +	if (typeof json.title !== 'undefined') { +		json.error = {message: json.message}; +	} + +	if (json.error) { +		file.status = plupload.FAILED; +		up.trigger('FileUploaded', file, { +			response: JSON.stringify({ +				error: { +					message: json.error.message +				} +			}) +		}); +	} +}); + +/** + * Fires when files are added to the queue. + * + * @return undefined + */ +uploader.bind('FilesAdded', function(up, files) { +	// Prevent unnecessary requests to the server if the user already uploaded +	// the maximum number of files allowed. +	if (phpbb.plupload.handleMaxFilesReached()) { +		return; +	} + +	// Show the file list if there aren't any files currently. +	if (!$('#file-list-container').is(':visible')) { +		$('#file-list-container').show(100); +	} + +	$.each(files, function(i, file) { +		phpbb.plupload.insertRow(file);  	}); + +	up.bind('UploadProgress', function(up, file) { +		$('#' + file.id + " .file-progress-bar").css('width', file.percent + '%'); +		$('#file-total-progress-bar').css('width', up.total.percent + '%'); +	}); + +	// Do not allow more files to be added to the running queue. +	phpbb.plupload.disableUploader(); + +	// Start uploading the files once the user has selected them. +	up.start(); +}); + + +/** + * Fires when an entire file has been uploaded. It checks for errors + * returned by the server otherwise parses the list of attachment data and + * appends it to the next file upload so that the server can maintain state + * with regards to the attachments in a given post + * + * @param object up			The plupload.Uploader object + * @param object file		The plupload.File object that has just been + * 	uploaded + * @param string response	The response string from the server + * + * @return undefined + */ +uploader.bind('FileUploaded', function(up, file, response) { +	var json = {}, +		row = $('#' + file.id), +		error; + +	// Hide the progress indicator. +	row.find('.file-progress').hide(); + +	try { +		json = $.parseJSON(response.response); +	} catch (e) { +		error = 'Error parsing server response.'; +	} + +	// If trigger_error() was called, then a permission error likely occurred. +	if (typeof json.title !== 'undefined') { +		error = json.message; +		up.trigger('Error', {message: error}); + +		// The rest of the queue will fail. +		phpbb.plupload.markQueuedFailed(error); +	} else if (json.error) { +		error = json.error.message; +	} + +	if (typeof error !== 'undefined') { +		phpbb.plupload.fileError(file, error); +	} else if (file.status === plupload.DONE) { +		file.attachment_data = json['data'][0]; + +		row.attr('data-attach-id', file.attachment_data.attach_id); +		row.find('.file-inline-bbcode').show(); +		row.find('.file-status').addClass('file-uploaded'); +		phpbb.plupload.update(json['data'], 'addition', 0, [json['download_url']]); +	}  }); + +/** + * Fires when the entire queue of files have been uploaded.  + * + * @param object up		The plupload.Uploader object + * @param array files	An array of plupload.File objects that have just + * 	been uploaded as part of a queue + * + * @return undefined + */ +uploader.bind('UploadComplete', function(up, files) { +	// Hide the progress bar +	setTimeout(function() { +		$('#file-total-progress-bar').fadeOut(500, function() { +			$(this).css('width', 0).show(); +		}); +	}, 2000); + +	// Re-enable the uploader +	phpbb.plupload.enableUploader(); +}); + +})(jQuery); // Avoid conflicts with other libraries diff --git a/phpBB/assets/plupload/jquery.plupload.queue/img/done.gif b/phpBB/assets/plupload/img/done.gifBinary files differ index 29f3ed7c97..29f3ed7c97 100644 --- a/phpBB/assets/plupload/jquery.plupload.queue/img/done.gif +++ b/phpBB/assets/plupload/img/done.gif diff --git a/phpBB/assets/plupload/jquery.plupload.queue/img/error.gif b/phpBB/assets/plupload/img/error.gifBinary files differ index 4682b63007..4682b63007 100644 --- a/phpBB/assets/plupload/jquery.plupload.queue/img/error.gif +++ b/phpBB/assets/plupload/img/error.gif diff --git a/phpBB/assets/plupload/jquery.plupload.queue/img/throbber.gif b/phpBB/assets/plupload/img/throbber.gifBinary files differ index 4ae8b16a5a..4ae8b16a5a 100644 --- a/phpBB/assets/plupload/jquery.plupload.queue/img/throbber.gif +++ b/phpBB/assets/plupload/img/throbber.gif diff --git a/phpBB/assets/plupload/jquery.plupload.queue/css/jquery.plupload.queue.css b/phpBB/assets/plupload/jquery.plupload.queue/css/jquery.plupload.queue.css deleted file mode 100644 index 1a23a3d8a2..0000000000 --- a/phpBB/assets/plupload/jquery.plupload.queue/css/jquery.plupload.queue.css +++ /dev/null @@ -1,181 +0,0 @@ -/*  -   Plupload -------------------------------------------------------------------- */ - -.plupload_button { -	display: -moz-inline-box; /* FF < 3*/ -	display: inline-block; -	font: normal 12px sans-serif; -	text-decoration: none; -    color: #42454a; -    border: 1px solid #bababa; -    padding: 2px 8px 3px 20px; -	margin-right: 4px; -    background: #f3f3f3 url('../img/buttons.png') no-repeat 0 center; -	outline: 0; - -    /* Optional rounded corners for browsers that support it */ -    -moz-border-radius: 3px; -    -khtml-border-radius: 3px; -    -webkit-border-radius: 3px; -    border-radius: 3px; -} - -.plupload_button:hover { -	color: #000; -	text-decoration: none; -} - -.plupload_disabled, a.plupload_disabled:hover { -    color: #737373; -    border-color: #c5c5c5; -    background: #ededed url('../img/buttons-disabled.png') no-repeat 0 center; -	cursor: default; -} - -.plupload_add { -	background-position: -181px center; -} - -.plupload_wrapper { -	font: normal 11px Verdana,sans-serif; -	width: 100%; -} - -.plupload_container { -	padding: 8px; -	background: url('../img/transp50.png'); -	/*-moz-border-radius: 5px;*/ -} - -.plupload_container input { -	border: 1px solid #DDD; -	font: normal 11px Verdana,sans-serif; -	width: 98%; -} - -.plupload_header {background: #2A2C2E url('../img/backgrounds.gif') repeat-x;} -.plupload_header_content { -	background: url('../img/backgrounds.gif') no-repeat 0 -317px; -	min-height: 56px; -	padding-left: 60px; -	color: #FFF; -} -.plupload_header_title { -	font: normal 18px sans-serif; -	padding: 6px 0 3px; -} -.plupload_header_text { -	font: normal 12px sans-serif; -} - -.plupload_filelist { -	margin: 0; -	padding: 0; -	list-style: none; -} - -.plupload_scroll .plupload_filelist { -	height: 185px; -	background: #F5F5F5; -	overflow-y: scroll; -} - -.plupload_filelist li { -	padding: 10px 8px; -	background: #F5F5F5 url('../img/backgrounds.gif') repeat-x 0 -156px; -	border-bottom: 1px solid #DDD; -} - -.plupload_filelist_header, .plupload_filelist_footer { -	background: #DFDFDF; -	padding: 8px 8px; -	color: #42454A; -} -.plupload_filelist_header {	 -	border-top: 1px solid #EEE; -	border-bottom: 1px solid #CDCDCD; -} - -.plupload_filelist_footer {border-top: 1px solid #FFF; height: 22px; line-height: 20px; vertical-align: middle;} -.plupload_file_name {float: left; overflow: hidden} -.plupload_file_status {color: #777;} -.plupload_file_status span {color: #42454A;} -.plupload_file_size, .plupload_file_status, .plupload_progress { -	float: right; -	width: 80px; -} -.plupload_file_size, .plupload_file_status, .plupload_file_action {text-align: right;} - -.plupload_filelist .plupload_file_name { -	width: 205px; -	white-space: nowrap; -	text-overflow: ellipsis; -} - -.plupload_file_action { -	float: right; -	width: 16px; -	height: 16px; -	margin-left: 15px; -} - -.plupload_file_action * { -	display: none; -	width: 16px; -	height: 16px; -} - -li.plupload_uploading {background: #ECF3DC url('../img/backgrounds.gif') repeat-x 0 -238px;} -li.plupload_done {color:#AAA} - -li.plupload_delete a { -	background: url('../img/delete.gif'); -} - -li.plupload_failed a { -	background: url('../img/error.gif'); -	cursor: default; -} - -li.plupload_done a { -	background: url('../img/done.gif'); -	cursor: default; -} - -.plupload_progress, .plupload_upload_status { -	display: none; -} - -.plupload_progress_container { -	margin-top: 3px; -	border: 1px solid #CCC; -	background: #FFF; -	padding: 1px; -} -.plupload_progress_bar { -	width: 0px; -	height: 7px; -	background: #CDEB8B; -} - -.plupload_scroll .plupload_filelist_header .plupload_file_action, .plupload_scroll .plupload_filelist_footer .plupload_file_action { -	margin-right: 17px; -} - -/* Floats */ - -.plupload_clear,.plupload_clearer {clear: both;} -.plupload_clearer, .plupload_progress_bar { -	display: block; -	font-size: 0; -	line-height: 0;	 -} - -li.plupload_droptext { -	background: transparent; -	text-align: center; -	vertical-align: middle; -	border: 0; -	line-height: 165px; -} diff --git a/phpBB/assets/plupload/jquery.plupload.queue/img/backgrounds.gif b/phpBB/assets/plupload/jquery.plupload.queue/img/backgrounds.gifBinary files differ deleted file mode 100644 index 39e33ebc02..0000000000 --- a/phpBB/assets/plupload/jquery.plupload.queue/img/backgrounds.gif +++ /dev/null diff --git a/phpBB/assets/plupload/jquery.plupload.queue/img/buttons-disabled.png b/phpBB/assets/plupload/jquery.plupload.queue/img/buttons-disabled.pngBinary files differ deleted file mode 100644 index afa11af9b9..0000000000 --- a/phpBB/assets/plupload/jquery.plupload.queue/img/buttons-disabled.png +++ /dev/null diff --git a/phpBB/assets/plupload/jquery.plupload.queue/img/buttons.png b/phpBB/assets/plupload/jquery.plupload.queue/img/buttons.pngBinary files differ deleted file mode 100644 index 153e73885a..0000000000 --- a/phpBB/assets/plupload/jquery.plupload.queue/img/buttons.png +++ /dev/null diff --git a/phpBB/assets/plupload/jquery.plupload.queue/img/delete.gif b/phpBB/assets/plupload/jquery.plupload.queue/img/delete.gifBinary files differ deleted file mode 100644 index 78ca8b3b49..0000000000 --- a/phpBB/assets/plupload/jquery.plupload.queue/img/delete.gif +++ /dev/null diff --git a/phpBB/assets/plupload/jquery.plupload.queue/img/transp50.png b/phpBB/assets/plupload/jquery.plupload.queue/img/transp50.pngBinary files differ deleted file mode 100644 index eb0efe104b..0000000000 --- a/phpBB/assets/plupload/jquery.plupload.queue/img/transp50.png +++ /dev/null diff --git a/phpBB/assets/plupload/jquery.plupload.queue/jquery.plupload.queue.min.js b/phpBB/assets/plupload/jquery.plupload.queue/jquery.plupload.queue.min.js deleted file mode 100644 index a38f914ad7..0000000000 --- a/phpBB/assets/plupload/jquery.plupload.queue/jquery.plupload.queue.min.js +++ /dev/null @@ -1 +0,0 @@ -;(function(e,t){function r(e){return plupload.translate(e)||e}function i(t,n){n.contents().each(function(t,n){n=e(n),n.is(".plupload")||n.remove()}),n.prepend('<div class="plupload_wrapper plupload_scroll"><div id="'+t+'_container" class="plupload_container">'+'<div class="plupload">'+'<div class="plupload_header">'+'<div class="plupload_header_content">'+'<div class="plupload_header_title">'+r("Select files")+"</div>"+'<div class="plupload_header_text">'+r("Add files to the upload queue and click the start button.")+"</div>"+"</div>"+"</div>"+'<div class="plupload_content">'+'<div class="plupload_filelist_header">'+'<div class="plupload_file_name">'+r("Filename")+"</div>"+'<div class="plupload_file_action"> </div>'+'<div class="plupload_file_status"><span>'+r("Status")+"</span></div>"+'<div class="plupload_file_size">'+r("Size")+"</div>"+'<div class="plupload_clearer"> </div>'+"</div>"+'<ul id="'+t+'_filelist" class="plupload_filelist"></ul>'+'<div class="plupload_filelist_footer">'+'<div class="plupload_file_name">'+'<div class="plupload_buttons">'+'<a href="#" class="plupload_button plupload_add" id="'+t+'_browse">'+r("Add Files")+"</a>"+'<a href="#" class="plupload_button plupload_start">'+r("Start Upload")+"</a>"+"</div>"+'<span class="plupload_upload_status"></span>'+"</div>"+'<div class="plupload_file_action"></div>'+'<div class="plupload_file_status"><span class="plupload_total_status">0%</span></div>'+'<div class="plupload_file_size"><span class="plupload_total_file_size">0 b</span></div>'+'<div class="plupload_progress">'+'<div class="plupload_progress_container">'+'<div class="plupload_progress_bar"></div>'+"</div>"+"</div>"+'<div class="plupload_clearer"> </div>'+"</div>"+"</div>"+"</div>"+"</div>"+'<input type="hidden" id="'+t+'_count" name="'+t+'_count" value="0" />'+"</div>")}var n={};e.fn.pluploadQueue=function(s){return s?(this.each(function(){function c(t){var n;t.status==plupload.DONE&&(n="plupload_done"),t.status==plupload.FAILED&&(n="plupload_failed"),t.status==plupload.QUEUED&&(n="plupload_delete"),t.status==plupload.UPLOADING&&(n="plupload_uploading");var r=e("#"+t.id).attr("class",n).find("a").css("display","block");t.hint&&r.attr("title",t.hint)}function h(){e("span.plupload_total_status",a).html(u.total.percent+"%"),e("div.plupload_progress_bar",a).css("width",u.total.percent+"%"),e("span.plupload_upload_status",a).html(t.sprintf(r("Uploaded %d/%d files"),u.total.uploaded,u.files.length))}function p(){var n=e("ul.plupload_filelist",a).html(""),i=0,s;e.each(u.files,function(t,r){s="",r.status==plupload.DONE&&(r.target_name&&(s+='<input type="hidden" name="'+f+"_"+i+'_tmpname" value="'+plupload.xmlEncode(r.target_name)+'" />'),s+='<input type="hidden" name="'+f+"_"+i+'_name" value="'+plupload.xmlEncode(r.name)+'" />',s+='<input type="hidden" name="'+f+"_"+i+'_status" value="'+(r.status==plupload.DONE?"done":"failed")+'" />',i++,e("#"+f+"_count").val(i)),n.append('<li id="'+r.id+'">'+'<div class="plupload_file_name"><span>'+r.name+"</span></div>"+'<div class="plupload_file_action"><a href="#"></a></div>'+'<div class="plupload_file_status">'+r.percent+"%</div>"+'<div class="plupload_file_size">'+plupload.formatSize(r.size)+"</div>"+'<div class="plupload_clearer"> </div>'+s+"</li>"),c(r),e("#"+r.id+".plupload_delete a").click(function(t){e("#"+r.id).remove(),u.removeFile(r),t.preventDefault()})}),e("span.plupload_total_file_size",a).html(plupload.formatSize(u.total.size)),u.total.queued===0?e("span.plupload_add_text",a).html(r("Add Files")):e("span.plupload_add_text",a).html(t.sprintf(r("%d files queued"),u.total.queued)),e("a.plupload_start",a).toggleClass("plupload_disabled",u.files.length==u.total.uploaded+u.total.failed),n[0].scrollTop=n[0].scrollHeight,h(),!u.files.length&&u.features.dragdrop&&u.settings.dragdrop&&e("#"+f+"_filelist").append('<li class="plupload_droptext">'+r("Drag files here.")+"</li>")}function d(){delete n[f],u.destroy(),a.html(l),u=a=l=null}var u,a,f,l;a=e(this),f=a.attr("id"),f||(f=plupload.guid(),a.attr("id",f)),l=a.html(),i(f,a),s=e.extend({dragdrop:!0,browse_button:f+"_browse",container:f},s),s.dragdrop&&(s.drop_element=f+"_filelist"),u=new plupload.Uploader(s),n[f]=u,u.bind("UploadFile",function(t,n){e("#"+n.id).addClass("plupload_current_file")}),u.bind("Init",function(t,n){!s.unique_names&&s.rename&&a.on("click","#"+f+"_filelist div.plupload_file_name span",function(n){var r=e(n.target),i,s,o,u="";i=t.getFile(r.parents("li")[0].id),o=i.name,s=/^(.+)(\.[^.]+)$/.exec(o),s&&(o=s[1],u=s[2]),r.hide().after('<input type="text" />'),r.next().val(o).focus().blur(function(){r.show().next().remove()}).keydown(function(t){var n=e(this);t.keyCode==13&&(t.preventDefault(),i.name=n.val()+u,r.html(i.name),n.blur())})}),e("#"+f+"_container").attr("title","Using runtime: "+n.runtime),e("a.plupload_start",a).click(function(t){e(this).hasClass("plupload_disabled")||u.start(),t.preventDefault()}),e("a.plupload_stop",a).click(function(e){e.preventDefault(),u.stop()}),e("a.plupload_start",a).addClass("plupload_disabled")}),u.bind("Error",function(t,n){var i=n.file,s;i&&(s=n.message,n.details&&(s+=" ("+n.details+")"),n.code==plupload.FILE_SIZE_ERROR&&alert(r("Error: File too large:")+" "+i.name),n.code==plupload.FILE_EXTENSION_ERROR&&alert(r("Error: Invalid file extension:")+" "+i.name),i.hint=s,e("#"+i.id).attr("class","plupload_failed").find("a").css("display","block").attr("title",s)),n.code===plupload.INIT_ERROR&&setTimeout(function(){d()},1)}),u.bind("PostInit",function(t){t.settings.dragdrop&&t.features.dragdrop&&e("#"+f+"_filelist").append('<li class="plupload_droptext">'+r("Drag files here.")+"</li>")}),u.init(),u.bind("StateChanged",function(){u.state===plupload.STARTED?(e("li.plupload_delete a,div.plupload_buttons",a).hide(),e("span.plupload_upload_status,div.plupload_progress,a.plupload_stop",a).css("display","block"),e("span.plupload_upload_status",a).html("Uploaded "+u.total.uploaded+"/"+u.files.length+" files"),s.multiple_queues&&e("span.plupload_total_status,span.plupload_total_file_size",a).show()):(p(),e("a.plupload_stop,div.plupload_progress",a).hide(),e("a.plupload_delete",a).css("display","block"),s.multiple_queues&&u.total.uploaded+u.total.failed==u.files.length&&(e(".plupload_buttons,.plupload_upload_status",a).css("display","inline"),e(".plupload_start",a).addClass("plupload_disabled"),e("span.plupload_total_status,span.plupload_total_file_size",a).hide()))}),u.bind("FilesAdded",p),u.bind("FilesRemoved",function(){var t=e("#"+f+"_filelist").scrollTop();p(),e("#"+f+"_filelist").scrollTop(t)}),u.bind("FileUploaded",function(e,t){c(t)}),u.bind("UploadProgress",function(t,n){e("#"+n.id+" div.plupload_file_status",a).html(n.percent+"%"),c(n),h()}),s.setup&&s.setup(u)}),this):n[e(this[0]).attr("id")]}})(jQuery,mOxie);
\ No newline at end of file diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 172f4403ac..e14e9e27be 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -862,6 +862,7 @@ function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_a  				'ATTACH_ID'			=> $attach_row['attach_id'],  				'S_IS_ORPHAN'		=> $attach_row['is_orphan'],  				'ASSOC_INDEX'		=> $count, +				'FILESIZE'			=> get_formatted_filesize($attach_row['filesize']),  				'U_VIEW_ATTACHMENT'	=> $download_link,  				'S_HIDDEN'			=> $hidden) diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index b29f587385..ad6743b3a3 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -1461,6 +1461,7 @@ class parse_message extends bbcode_firstpass  						'is_orphan'		=> 1,  						'real_filename'	=> $filedata['real_filename'],  						'attach_comment'=> $this->filename_data['filecomment'], +						'filesize'		=> $filedata['filesize'],  					);  					$this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data); @@ -1572,6 +1573,7 @@ class parse_message extends bbcode_firstpass  							'is_orphan'		=> 1,  							'real_filename'	=> $filedata['real_filename'],  							'attach_comment'=> $this->filename_data['filecomment'], +							'filesize'		=> $filedata['filesize'],  						);  						$this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data); @@ -1580,8 +1582,10 @@ class parse_message extends bbcode_firstpass  						if (isset($this->plupload) && $this->plupload->is_active())  						{ +							$download_url = append_sid("{$phpbb_root_path}download/file.{$phpEx}", 'mode=view&id=' . $new_entry['attach_id']); +  							// Send the client the attachment data to maintain state -							$json_response->send($this->attachment_data); +							$json_response->send(array('data' => $this->attachment_data, 'download_url' => $download_url));  						}  					}  				} @@ -1649,7 +1653,7 @@ class parse_message extends bbcode_firstpass  		if (sizeof($not_orphan))  		{  			// Get the attachment data, based on the poster id... -			$sql = 'SELECT attach_id, is_orphan, real_filename, attach_comment +			$sql = 'SELECT attach_id, is_orphan, real_filename, attach_comment, filesize  				FROM ' . ATTACHMENTS_TABLE . '  				WHERE ' . $db->sql_in_set('attach_id', array_keys($not_orphan)) . '  					AND poster_id = ' . $check_user_id; @@ -1674,7 +1678,7 @@ class parse_message extends bbcode_firstpass  		// Regenerate newly uploaded attachments  		if (sizeof($orphan))  		{ -			$sql = 'SELECT attach_id, is_orphan, real_filename, attach_comment +			$sql = 'SELECT attach_id, is_orphan, real_filename, attach_comment, filesize  				FROM ' . ATTACHMENTS_TABLE . '  				WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan)) . '  					AND poster_id = ' . $user->data['user_id'] . ' diff --git a/phpBB/language/en/plupload.php b/phpBB/language/en/plupload.php index 74ae8b7c78..6039de7dbf 100644 --- a/phpBB/language/en/plupload.php +++ b/phpBB/language/en/plupload.php @@ -42,6 +42,7 @@ $lang = array_merge($lang, array(  	'PLUPLOAD_CLOSE'			=> 'Close',  	'PLUPLOAD_DRAG'				=> 'Drag files here.',  	'PLUPLOAD_DUPLICATE_ERROR'	=> 'Duplicate file error.', +	'PLUPLOAD_DRAG_TEXTAREA'	=> 'You may also attach files by dragging and dropping them in the message box.',  	'PLUPLOAD_ERR_INPUT'		=> 'Failed to open input stream.',  	'PLUPLOAD_ERR_MOVE_UPLOADED'	=> 'Failed to move uploaded file.',  	'PLUPLOAD_ERR_OUTPUT'		=> 'Failed to open output stream.', @@ -49,7 +50,6 @@ $lang = array_merge($lang, array(  	'PLUPLOAD_ERR_FILE_COUNT'	=> 'File count error.',  	'PLUPLOAD_ERR_FILE_INVALID_EXT'	=> 'Error: Invalid file extension:',  	'PLUPLOAD_ERR_RUNTIME_MEMORY'	=> 'Runtime ran out of available memory.', -	'PLUPLOAD_ERR_UPLOAD_LIMIT'	=> 'Upload element accepts only %d file(s) at a time. Extra files were stripped.',  	'PLUPLOAD_ERR_UPLOAD_URL'	=> 'Upload URL might be wrong or does not exist.',  	'PLUPLOAD_EXTENSION_ERROR'	=> 'File extension error.',  	'PLUPLOAD_FILE'				=> 'File: %s', diff --git a/phpBB/posting.php b/phpBB/posting.php index 0d2cff40bc..902f1b2175 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -255,8 +255,18 @@ if (!$auth->acl_get('f_read', $forum_id))  	{  		trigger_error('USER_CANNOT_READ');  	} +	$message = $user->lang['LOGIN_EXPLAIN_POST']; -	login_box('', $user->lang['LOGIN_EXPLAIN_POST']); +	if ($request->is_ajax()) +	{ +		$json = new phpbb\json_response(); +		$json->send(array( +			'title'		=> $user->lang['INFORMATION'], +			'message'	=> $message, +		)); +	} + +	login_box('', $message);  }  // Permission to do the action asked? @@ -326,8 +336,18 @@ if (!$is_authed)  	{  		trigger_error('USER_CANNOT_' . strtoupper($check_auth));  	} +	$message = $user->lang['LOGIN_EXPLAIN_' . strtoupper($mode)]; -	login_box('', $user->lang['LOGIN_EXPLAIN_' . strtoupper($mode)]); +	if ($request->is_ajax()) +	{ +		$json = new phpbb\json_response(); +		$json->send(array( +			'title'		=> $user->lang['INFORMATION'], +			'message'	=> $message, +		)); +	} + +	login_box('', $message);  }  // Is the user able to post within this forum? @@ -484,7 +504,7 @@ $message_parser->get_submitted_attachment_data($post_data['poster_id']);  if ($post_data['post_attachment'] && !$submit && !$refresh && !$preview && $mode == 'edit')  {  	// Do not change to SELECT * -	$sql = 'SELECT attach_id, is_orphan, attach_comment, real_filename +	$sql = 'SELECT attach_id, is_orphan, attach_comment, real_filename, filesize  		FROM ' . ATTACHMENTS_TABLE . "  		WHERE post_msg_id = $post_id  			AND in_message = 0 @@ -1464,6 +1484,7 @@ $template->assign_vars(array(  	'L_POST_A'					=> $page_title,  	'L_ICON'					=> ($mode == 'reply' || $mode == 'quote' || ($mode == 'edit' && $post_id != $post_data['topic_first_post_id'])) ? $user->lang['POST_ICON'] : $user->lang['TOPIC_ICON'],  	'L_MESSAGE_BODY_EXPLAIN'	=> $user->lang('MESSAGE_BODY_EXPLAIN', (int) $config['max_post_chars']), +	'L_TOO_MANY_ATTACHMENTS'	=> $user->lang('TOO_MANY_ATTACHMENTS', (int) $config['max_attachments']),  	'FORUM_NAME'			=> $post_data['forum_name'],  	'FORUM_DESC'			=> ($post_data['forum_desc']) ? generate_text_for_display($post_data['forum_desc'], $post_data['forum_desc_uid'], $post_data['forum_desc_bitfield'], $post_data['forum_desc_options']) : '', @@ -1487,6 +1508,8 @@ $template->assign_vars(array(  	'U_VIEW_TOPIC'			=> ($mode != 'post') ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id") : '',  	'U_PROGRESS_BAR'		=> append_sid("{$phpbb_root_path}posting.$phpEx", "f=$forum_id&mode=popup"),  	'UA_PROGRESS_BAR'		=> addslashes(append_sid("{$phpbb_root_path}posting.$phpEx", "f=$forum_id&mode=popup")), +	'ATTACH_ORDER'			=> ($config['display_order']) ? 'asc' : 'desc', +	'MAX_ATTACHMENTS'		=> ($auth->acl_get('a_') || $auth->acl_get('m_', $forum_id)) ? 0 : (int) $config['max_attachments'],  	'S_PRIVMSGS'				=> false,  	'S_CLOSE_PROGRESS_WINDOW'	=> (isset($_POST['add_file'])) ? true : false, @@ -1525,8 +1548,9 @@ $template->assign_vars(array(  	'S_BBCODE_QUOTE'		=> $quote_status,  	'S_POST_ACTION'			=> $s_action, -	'S_HIDDEN_FIELDS'		=> $s_hidden_fields) -); +	'S_HIDDEN_FIELDS'		=> $s_hidden_fields, +	'S_ATTACH_DATA'			=> json_encode($message_parser->attachment_data), +));  /**  * This event allows you to modify template variables for the posting screen diff --git a/phpBB/styles/prosilver/template/forum_fn.js b/phpBB/styles/prosilver/template/forum_fn.js index a45f750a63..495df2871d 100644 --- a/phpBB/styles/prosilver/template/forum_fn.js +++ b/phpBB/styles/prosilver/template/forum_fn.js @@ -747,7 +747,7 @@ function parse_document(container)  	/**  	* Hide empty responsive tables  	*/ -	container.find('table.responsive > tbody').each(function() { +	container.find('table.responsive > tbody').not('.responsive-skip-empty').each(function() {  		var items = $(this).children('tr');  		if (items.length == 0)  		{ diff --git a/phpBB/styles/prosilver/template/mcp_header.html b/phpBB/styles/prosilver/template/mcp_header.html index e3efe49943..51f496605e 100644 --- a/phpBB/styles/prosilver/template/mcp_header.html +++ b/phpBB/styles/prosilver/template/mcp_header.html @@ -39,7 +39,7 @@  		</div>  	</div> -	<div id="cp-main" class="mcp-main"> +	<div id="cp-main" class="mcp-main panel-container">  		<!-- IF MESSAGE -->  		<div class="content">  			<h2>{L_MESSAGE}</h2> diff --git a/phpBB/styles/prosilver/template/overall_footer.html b/phpBB/styles/prosilver/template/overall_footer.html index f7d0269edb..662008b7fa 100644 --- a/phpBB/styles/prosilver/template/overall_footer.html +++ b/phpBB/styles/prosilver/template/overall_footer.html @@ -60,8 +60,8 @@  <!-- EVENT overall_footer_after --> -{$SCRIPTS}  <!-- IF S_PLUPLOAD --><!-- INCLUDE plupload.html --><!-- ENDIF --> +{$SCRIPTS}  </body>  </html> diff --git a/phpBB/styles/prosilver/template/overall_header.html b/phpBB/styles/prosilver/template/overall_header.html index 529e6625fe..a89585d899 100644 --- a/phpBB/styles/prosilver/template/overall_header.html +++ b/phpBB/styles/prosilver/template/overall_header.html @@ -36,7 +36,6 @@  <!-- ENDIF -->  <!-- IF S_PLUPLOAD --> -	<link href="{T_ASSETS_PATH}/plupload/jquery.plupload.queue/css/jquery.plupload.queue.css?assets_version={T_ASSETS_VERSION}" rel="stylesheet" type="text/css" media="screen, projection" />  	<link href="{T_THEME_PATH}/plupload.css?assets_version={T_ASSETS_VERSION}" rel="stylesheet" type="text/css" media="screen, projection" />  <!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/plupload.html b/phpBB/styles/prosilver/template/plupload.html index 290992ddd6..21acae1c44 100644 --- a/phpBB/styles/prosilver/template/plupload.html +++ b/phpBB/styles/prosilver/template/plupload.html @@ -1,5 +1,3 @@ -<script type="text/javascript" src="{T_ASSETS_PATH}/plupload/plupload.full.min.js?assets_version={T_ASSETS_VERSION}"></script> -<script type="text/javascript" src="{T_ASSETS_PATH}/plupload/jquery.plupload.queue/jquery.plupload.queue.min.js?assets_version={T_ASSETS_VERSION}"></script>  <script type="text/javascript">  //<![CDATA[  phpbb.plupload = { @@ -37,7 +35,6 @@ phpbb.plupload = {  		'Status': '{LA_PLUPLOAD_STATUS}',  		'Stop Upload': '{LA_PLUPLOAD_STOP_UPLOAD}',  		'Stop current upload': '{LA_PLUPLOAD_STOP_CURRENT_UPLOAD}', -		'Upload element accepts only %d file(s) at a time. Extra files were stripped.': '{LA_PLUPLOAD_ERR_UPLOAD_LIMIT}',  		"Upload URL might be wrong or doesn't exist.": '{LA_PLUPLOAD_ERR_UPLOAD_URL}',  		'Uploaded %d/%d files': '{LA_PLUPLOAD_UPLOADED}',  		'%d files queued': '{LA_PLUPLOAD_FILES_QUEUED}', @@ -51,14 +48,22 @@ phpbb.plupload = {  		unique_names: true,  		filters: [{FILTERS}],  		{S_RESIZE} -		headers: {'X-PHPBB-USING-PLUPLOAD': '1'}, +		headers: {'X-PHPBB-USING-PLUPLOAD': '1', 'X-Requested-With': 'XMLHttpRequest'},  		file_data_name: 'fileupload',  		multipart_params: {'add_file': '{LA_ADD_FILE}'}, -		img_path: '{T_ASSETS_PATH}/plupload/jquery.plupload.queue/img', -		element_hook: '#attach-panel .inner', -		form_hook: '#postform' -	} -}; +		form_hook: '#postform', +		browse_button: 'add_files', +		drop_element : 'message', +	}, +	lang: { +		ERROR: '{LA_ERROR}', +		TOO_MANY_ATTACHMENTS: '{LA_TOO_MANY_ATTACHMENTS}', +	}, +	order: '{ATTACH_ORDER}', +	maxFiles: {MAX_ATTACHMENTS}, +	data: {S_ATTACH_DATA}, +}  //]]>  </script> -<script type="text/javascript" src="{T_ASSETS_PATH}/javascript/plupload.js"></script> +<!-- INCLUDEJS {T_ASSETS_PATH}/plupload/plupload.full.min.js --> +<!-- INCLUDEJS {T_ASSETS_PATH}/javascript/plupload.js --> diff --git a/phpBB/styles/prosilver/template/posting_attach_body.html b/phpBB/styles/prosilver/template/posting_attach_body.html index fa9dd19c09..8a2004c29b 100644 --- a/phpBB/styles/prosilver/template/posting_attach_body.html +++ b/phpBB/styles/prosilver/template/posting_attach_body.html @@ -1,9 +1,9 @@ -<div class="panel bg3" id="attach-panel"> +<div class="panel bg3 panel-container" id="attach-panel">  	<div class="inner"> -	<p>{L_ADD_ATTACHMENT_EXPLAIN}</p> +	<p>{L_ADD_ATTACHMENT_EXPLAIN} <span class="hidden" id="drag-n-drop-message">{L_PLUPLOAD_DRAG_TEXTAREA}</span></p> -	<fieldset class="fields2"> +	<fieldset class="fields2" id="attach-panel-basic">  	<dl>  		<dt><label for="fileupload">{L_FILENAME}{L_COLON}</label></dt>  		<dd> @@ -17,5 +17,73 @@  	</dl>  	</fieldset> +	<div id="attach-panel-multi"> +		<input type="button" class="button2" value="{L_PLUPLOAD_ADD_FILES}" id="add_files" /> +	</div> + +	<div class="panel<!-- IF not .attach_row --> hidden<!-- ENDIF -->" id="file-list-container"> +		<div class="inner"> +			<table class="table1 zebra-list"> +				<thead> +					<tr> +						<th class="attach-name">{L_PLUPLOAD_FILENAME}</th> +						<th class="attach-comment">{L_FILE_COMMENT}</th> +						<th class="attach-filesize">{L_PLUPLOAD_SIZE}</th> +						<th class="attach-status">{L_PLUPLOAD_STATUS}</th> +					</tr> +				</thead> +				<tbody class="responsive-skip-empty" id="file-list"> +					<tr class="attach-row" id="attach-row-tpl"> +							<td class="attach-name"> +								<dfn style="display: none;">{L_PLUPLOAD_FILENAME}</dfn> +								<span class="file-name"></span> +								<span class="attach-controls"> +									<input type="button" value="{L_PLACE_INLINE}" class="button2 hidden file-inline-bbcode" />  +									<input type="button" value="{L_DELETE_FILE}" class="button2 file-delete" /> +								</span> +								<span class="clear"></span> +							</td> +							<td class="attach-comment"> +								<dfn style="display: none;">{L_FILE_COMMENT}</dfn> +								<textarea rows="1" cols="30" class="inputbox"></textarea> +							</td> +							<td class="attach-filesize"> +								<dfn style="display: none;">{L_PLUPLOAD_SIZE}</dfn> +								<span class="file-size"></span> +							</td> +							<td class="attach-status"> +								<dfn style="display: none;">{L_PLUPLOAD_STATUS}</dfn> +								<span class="file-progress"> +									<span class="file-progress-bar"></span> +								</span> +								<span class="file-status"></span> +							</td> +					</tr> +					<!-- BEGIN attach_row --> +						<tr class="attach-row" data-attach-id="{attach_row.ATTACH_ID}"> +							<td class="attach-name"> +								<span class="file-name"><a href="{attach_row.U_VIEW_ATTACHMENT}">{attach_row.FILENAME}</a></span> +								<span class="attach-controls"> +									<!-- IF S_INLINE_ATTACHMENT_OPTIONS --><input type="button" value="{L_PLACE_INLINE}" class="button2 file-inline-bbcode" />  <!-- ENDIF --> +									<input type="submit" name="delete_file[{attach_row.ASSOC_INDEX}]" value="{L_DELETE_FILE}" class="button2 file-delete" /> +								</span> +								<span class="clear"></span> +							</td> +							<td class="attach-comment"> +								<textarea name="comment_list[{attach_row.ASSOC_INDEX}]" rows="1" cols="30" class="inputbox">{attach_row.FILE_COMMENT}</textarea> +								{attach_row.S_HIDDEN} +							</td> +							<td class="attach-filesize"> +								<span class="file-size">{attach_row.FILESIZE}</span> +							</td> +							<td class="attach-status"> +								<span class="file-status file-uploaded"></span> +							</td> +						</tr> +					<!-- END attach_row --> +				</tbody> +			</table> +		</div> +	</div>  	</div>  </div> diff --git a/phpBB/styles/prosilver/template/posting_editor.html b/phpBB/styles/prosilver/template/posting_editor.html index 5677b92fc3..2ae224bc3a 100644 --- a/phpBB/styles/prosilver/template/posting_editor.html +++ b/phpBB/styles/prosilver/template/posting_editor.html @@ -149,34 +149,6 @@  	</div>  	<!-- ENDIF --> -	<!-- IF S_HAS_ATTACHMENTS --> -		<div class="panel bg2"> -			<div class="inner"> -			<h3>{L_POSTED_ATTACHMENTS}</h3> - -			<fieldset class="fields2"> - -			<!-- BEGIN attach_row --> -			<dl> - -				<dt><label for="comment_list_{attach_row.ASSOC_INDEX}">{L_FILE_COMMENT}{L_COLON}</label></dt> -				<dd><textarea name="comment_list[{attach_row.ASSOC_INDEX}]" id="comment_list_{attach_row.ASSOC_INDEX}" rows="1" cols="35" class="inputbox">{attach_row.FILE_COMMENT}</textarea></dd> -				<dd><a href="{attach_row.U_VIEW_ATTACHMENT}">{attach_row.FILENAME}</a></dd> -				<dd style="margin-top: 5px;"> -					<!-- IF S_INLINE_ATTACHMENT_OPTIONS --><input type="button" value="{L_PLACE_INLINE}" onclick="attach_inline({attach_row.ASSOC_INDEX}, '{attach_row.A_FILENAME}');" class="button2" />  <!-- ENDIF --> -					<input type="submit" name="delete_file[{attach_row.ASSOC_INDEX}]" value="{L_DELETE_FILE}" class="button2" /> -				</dd> -			</dl> -			{attach_row.S_HIDDEN} -				<!-- IF not attach_row.S_LAST_ROW --><hr class="dashed" /><!-- ENDIF --> -			<!-- END attach_row --> - -			</fieldset> - -			</div> -		</div> -	<!-- ENDIF --> -  	<!-- IF not S_SHOW_DRAFTS and not $SIG_EDIT eq 1 -->  	<div class="panel bg2">  		<div class="inner"> @@ -198,7 +170,15 @@  		<div id="tabs" class="sub-panels" data-show-panel="options-panel">  			<ul>  				<li id="options-panel-tab" class="activetab"><a href="#tabs" data-subpanel="options-panel"><span>{L_OPTIONS}</span></a></li> -				<!-- IF S_SHOW_ATTACH_BOX --><li id="attach-panel-tab"><a href="#tabs" data-subpanel="attach-panel"><span>{L_ADD_ATTACHMENT}</span></a></li><!-- ENDIF --> +				<!-- IF S_SHOW_ATTACH_BOX --> +					<li id="attach-panel-tab"> +						<a href="#tabs" data-subpanel="attach-panel"> +							<span> +								{L_ATTACHMENTS} <strong id="file-total-progress"><strong id="file-total-progress-bar"></strong></strong> +							</span> +						</a> +					</li>				 +				<!-- ENDIF -->  				<!-- IF S_SHOW_POLL_BOX || S_POLL_DELETE --><li id="poll-panel-tab"><a href="#tabs" data-subpanel="poll-panel"><span>{L_ADD_POLL}</span></a></li><!-- ENDIF -->  			</ul>  		</div> diff --git a/phpBB/styles/prosilver/template/ucp_header.html b/phpBB/styles/prosilver/template/ucp_header.html index c5d58b8eaa..8ce2c54294 100644 --- a/phpBB/styles/prosilver/template/ucp_header.html +++ b/phpBB/styles/prosilver/template/ucp_header.html @@ -98,4 +98,4 @@  	</div> -	<div id="cp-main" class="ucp-main"> +	<div id="cp-main" class="ucp-main panel-container"> diff --git a/phpBB/styles/prosilver/theme/colours.css b/phpBB/styles/prosilver/theme/colours.css index cad740200d..8c411a9f4d 100644 --- a/phpBB/styles/prosilver/theme/colours.css +++ b/phpBB/styles/prosilver/theme/colours.css @@ -76,8 +76,14 @@ hr {  	color: #000000;  } -.bg1	{ background-color: #ECF3F7; } -.bg2	{ background-color: #e1ebf2; } +table.zebra-list tr:nth-child(odd) td, ul.zebra-list li:nth-child(odd), .bg1 { +	background-color: #ECF3F7; +} + +table.zebra-list tr:nth-child(even) td, ul.zebra-list li:nth-child(even), .bg2 { +	background-color: #e1ebf2; +} +  .bg3	{ background-color: #cadceb; }  .ucprowbg { @@ -803,11 +809,11 @@ Colours and backgrounds for cp.css  /* Main CP box  ----------------------------------------*/ -#cp-main h3, #cp-main hr, #cp-menu hr { +.panel-container h3, .panel-container hr, #cp-menu hr {  	border-color: #A4B3BF;  } -#cp-main .panel li.row { +.panel-container .panel li.row {  	border-bottom-color: #B5C1CB;  	border-top-color: #F9F9F9;  } @@ -816,11 +822,11 @@ ul.cplist {  	border-top-color: #B5C1CB;  } -#cp-main .panel li.header dd, #cp-main .panel li.header dt { +.panel-container .panel li.header dd, .panel-container .panel li.header dt {  	color: #000000;  } -#cp-main table.table1 thead th { +.panel-container table.table1 thead th {  	color: #333333;  	border-bottom-color: #333333;  } @@ -921,11 +927,11 @@ ul.cplist {  /* Preferences pane layout  ----------------------------------------*/ -#cp-main h2 { +.panel-container h2 {  	color: #333333;  } -#cp-main .panel { +.panel-container .panel {  	background-color: #F9F9F9;  } diff --git a/phpBB/styles/prosilver/theme/cp.css b/phpBB/styles/prosilver/theme/cp.css index d2c69e7755..bf235b3fb5 100644 --- a/phpBB/styles/prosilver/theme/cp.css +++ b/phpBB/styles/prosilver/theme/cp.css @@ -20,16 +20,16 @@  	padding: 0;  } -#cp-main .panel p { +.panel-container .panel p {  	font-size: 1.1em;  } -#cp-main .panel ol { +.panel-container .panel ol {  	margin-left: 2em;  	font-size: 1.1em;  } -#cp-main .panel li.row { +.panel-container .panel li.row {  	border-bottom: 1px solid transparent;  	border-top: 1px solid transparent;  } @@ -39,21 +39,21 @@ ul.cplist {  	border-top: 1px solid transparent;  } -#cp-main .panel li.header dd, #cp-main .panel li.header dt { +.panel-container .panel li.header dd, .panel-container .panel li.header dt {  	margin-bottom: 2px;  } -#cp-main table.table1 { +.panel-container table.table1 {  	margin-bottom: 1em;  } -#cp-main table.table1 thead th { +.panel-container table.table1 thead th {  	font-weight: bold;  	border-bottom: 1px solid transparent;  	padding: 5px;  } -#cp-main table.table1 tbody th { +.panel-container table.table1 tbody th {  	font-style: italic;  	background-color: transparent !important;  	border-bottom: none; diff --git a/phpBB/styles/prosilver/theme/plupload.css b/phpBB/styles/prosilver/theme/plupload.css index 16c26822b5..8569eca662 100644 --- a/phpBB/styles/prosilver/theme/plupload.css +++ b/phpBB/styles/prosilver/theme/plupload.css @@ -1,11 +1,76 @@ -.plupload_filelist li.can_delete:hover { -	cursor: pointer; +#attach-panel-multi { +	display: none; +	margin-bottom: 1em;  } -.plupload_filelist li.can_delete:hover a { -	background: url('../../../assets/plupload/jquery.plupload.queue/img/delete.gif'); +#file-list td { +	vertical-align: middle;  } -.plupload_filelist li a.working { -	background: url('../../../assets/plupload/jquery.plupload.queue/img/throbber.gif'); +.attach-name { +	width: 50%; +} + +.attach-comment { +	width: 30%; +} + +.attach-filesize { +	width: 15%; +} + +.attach-status { +	width: 5%; +} + +.attach-filesize, .attach-status { +	text-align: center; +} + +.attach-controls { +	display: inline-block; +	float: right; +} + +#attach-row-tpl, .nojs .file-inline-bbcode { +	display: none; +} + +#file-total-progress { +	height: 2px; +	display: block; +	position: relative; +	margin: 4px -10px -6px -10px; +} + +.file-progress { +	background-color: #CCCCCC; +	display:inline-block; +	height: 8px; +	width: 50px; +} + +.file-progress-bar, #file-total-progress-bar { +	background-color: green; +	display: block; +	height: 100%; +	width: 0; +} + +.file-status.file-working { +	background: url('../../../assets/plupload/img/throbber.gif'); +} + +.file-status.file-uploaded { +	background: url('../../../assets/plupload/img/done.gif'); +} + +.file-status.file-error { +	background: url('../../../assets/plupload/img/error.gif'); +} + +.file-status { +	display: inline-block; +	height: 16px; +	width: 16px;  } diff --git a/phpBB/styles/prosilver/theme/responsive.css b/phpBB/styles/prosilver/theme/responsive.css index 397ff12942..bfa2448296 100644 --- a/phpBB/styles/prosilver/theme/responsive.css +++ b/phpBB/styles/prosilver/theme/responsive.css @@ -499,6 +499,10 @@ fieldset.display-actions {  	margin: 0 25px;  } +.attach-comment dfn { +	width: 100%; +} +  @media only screen and (max-width: 500px), only screen and (max-device-width: 500px)  {  	p.responsive-center { @@ -526,4 +530,9 @@ fieldset.display-actions {  		display: block;  		margin-bottom: 5px;  	} + +	.attach-controls { +		margin-top: 5px; +		width: 100%; +	}  } diff --git a/tests/functional/plupload_test.php b/tests/functional/plupload_test.php index 6dd9224839..a91e70c7bb 100644 --- a/tests/functional/plupload_test.php +++ b/tests/functional/plupload_test.php @@ -107,7 +107,7 @@ class phpbb_functional_plupload_test extends phpbb_functional_test_case  			else  			{  				$response = json_decode(self::$client->getResponse()->getContent(), true); -				$this->assertEquals('valid.jpg', $response[0]['real_filename']); +				$this->assertEquals('valid.jpg', $response['data'][0]['real_filename']);  			}  			unlink($this->path . 'chunk'); @@ -144,6 +144,6 @@ class phpbb_functional_plupload_test extends phpbb_functional_test_case  		);  		$response = json_decode(self::$client->getResponse()->getContent(), true); -		$this->assertEquals('valid.jpg', $response[0]['real_filename']); +		$this->assertEquals('valid.jpg', $response['data'][0]['real_filename']);  	}  } | 
