forked from extern/egroupware
- Nicer UI for status
- Implement server side callback function when file is uploaded - Send needed file info back to client instead of storing in session
This commit is contained in:
parent
02c414129a
commit
b2e032245a
@ -40,8 +40,17 @@ class etemplate_widget_file extends etemplate_widget
|
||||
$response->error("Could not read session");
|
||||
return;
|
||||
}
|
||||
foreach ($_FILES as $field => $file) {
|
||||
if ($file['error'] == UPLOAD_ERR_OK) {
|
||||
|
||||
if (!($template = etemplate_widget_template::instance(self::$request->template['name'], self::$request->template['template_set'],
|
||||
self::$request->template['version'], self::$request->template['load_via'])))
|
||||
{
|
||||
// Can't use callback
|
||||
error_log("Could not get template for file upload, callback skipped");
|
||||
}
|
||||
|
||||
$file_data = array();
|
||||
foreach ($_FILES as $field => &$file) {
|
||||
if ($file['error'] == UPLOAD_ERR_OK && trim($file['name']) != '' && $file['size'] > 0) {
|
||||
if (is_dir($GLOBALS['egw_info']['server']['temp_dir']) && is_writable($GLOBALS['egw_info']['server']['temp_dir']))
|
||||
{
|
||||
$new_file = tempnam($GLOBALS['egw_info']['server']['temp_dir'],'egw_');
|
||||
@ -50,19 +59,30 @@ class etemplate_widget_file extends etemplate_widget
|
||||
{
|
||||
$new_file = $value['file']['tmp_name'].'+';
|
||||
}
|
||||
// Files come from ajax Base64 encoded
|
||||
if(move_uploaded_file($file['tmp_name'], $new_file)) {
|
||||
$file['tmp_name'] = $new_file;
|
||||
|
||||
$handle = fopen($new_file, 'w');
|
||||
list($prefix, $data) = explode(',', file_get_contents($file['tmp_name']));
|
||||
$file['tmp_name'] = $new_file;
|
||||
fwrite($handle, base64_decode($data));
|
||||
fclose($handle);
|
||||
// Data to send back to client
|
||||
$temp_name = basename($file['tmp_name']);
|
||||
$file_data[$temp_name] = array(
|
||||
'name' => $file['name'],
|
||||
'type' => $file['type']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
$response->data($file_data);
|
||||
|
||||
// Store info for future submit
|
||||
$data = egw_session::appsession($request_id.'_files');
|
||||
$form_name = self::form_name($cname, $field);
|
||||
$data[$form_name][] = $file;
|
||||
egw_session::appsession($request_id.'_files','',$data);
|
||||
// Check for a callback, call it if there is one
|
||||
foreach($_FILES as $field => $file) {
|
||||
if($element = $template->getElementById($field))
|
||||
{
|
||||
$callback = $element->attrs['callback'];
|
||||
if(!$callback) $callback = $template->getElementAttribute($field, 'callback');
|
||||
if($callback)
|
||||
{
|
||||
ExecMethod($callback, $_FILES[$field]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -81,8 +101,29 @@ class etemplate_widget_file extends etemplate_widget
|
||||
$value = $value_in = self::get_array($content, $form_name);
|
||||
$valid =& self::get_array($validated, $form_name, true);
|
||||
|
||||
$files = egw_session::appsession(self::$request->id().'_files');
|
||||
$valid = $files[$form_name];
|
||||
if(!is_array($value)) $value = array();
|
||||
foreach($value as $tmp => $file)
|
||||
{
|
||||
if (is_dir($GLOBALS['egw_info']['server']['temp_dir']) && is_writable($GLOBALS['egw_info']['server']['temp_dir']))
|
||||
{
|
||||
$path = $GLOBALS['egw_info']['server']['temp_dir'].'/'.$tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
$path = $tmp.'+';
|
||||
}
|
||||
$stat = stat($path);
|
||||
$valid[] = array(
|
||||
'name' => $file['name'],
|
||||
'type' => $file['type'],
|
||||
'tmp_name' => $path,
|
||||
'error' => UPLOAD_ERR_OK, // Always OK if we get this far
|
||||
'size' => $stat['size'],
|
||||
'ip' => $_SERVER['REMOTE_ADDR'], // Assume it's the same as for when it was uploaded...
|
||||
);
|
||||
}
|
||||
|
||||
if($valid && !$this->attrs['multiple']) $valid = $valid[0];
|
||||
}
|
||||
}
|
||||
etemplate_widget::registerWidget('etemplate_widget_file', array('file'));
|
||||
|
@ -62,9 +62,12 @@ var et2_file = et2_inputWidget.extend({
|
||||
var self = this;
|
||||
this.asyncOptions = {
|
||||
// Callbacks
|
||||
onStartOne: function(event, file_name) { return self.createStatus(event,file_name);},
|
||||
onStart: function(event, file_count) { return self.onStart(event, file_count); },
|
||||
onFinish: function(event, file_count) { return self.onFinish(event, file_count); },
|
||||
onStartOne: function(event, file_name, index, file_count) { return self.createStatus(event,file_name, index,file_count);},
|
||||
onFinishOne: function(event, response, name, number, total) { return self.finishUpload(event,response,name,number,total);},
|
||||
|
||||
onProgress: function(event, progress, name, number, total) { return self.onProgress(event,progress,name,number,total);},
|
||||
onError: function(event, name, error) { return self.onError(event,name,error);},
|
||||
sendBoundary: window.FormData || jQuery.browser.mozilla,
|
||||
url: egw_json_request.prototype._assembleAjaxUrl("etemplate_widget_file::ajax_upload") +
|
||||
"&request_id="+ instance.etemplate_exec_id
|
||||
@ -84,6 +87,10 @@ var et2_file = et2_inputWidget.extend({
|
||||
{
|
||||
this.input.html5_upload(this.asyncOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This may be a problem submitting via ajax
|
||||
}
|
||||
this.progress = this.options.progress ?
|
||||
$j(document.getElementById(this.options.progress)) :
|
||||
$j(document.createElement("div")).appendTo(this.node);
|
||||
@ -94,31 +101,111 @@ var et2_file = et2_inputWidget.extend({
|
||||
}
|
||||
this.setDOMNode(this.node[0]);
|
||||
},
|
||||
getValue: function() {
|
||||
var value = this.options.value ? this.options.value : this.input.val();
|
||||
return value;
|
||||
},
|
||||
|
||||
getInputNode: function() {
|
||||
return this.input[0];
|
||||
},
|
||||
|
||||
/**
|
||||
* Disables submit buttons while uploading
|
||||
*/
|
||||
onStart: function(event, file_count) {
|
||||
this.disabled_buttons = $j("input[type='submit'], button").not("[disabled]").attr("disabled", true);
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Re-enables submit buttons when done
|
||||
*/
|
||||
onFinish: function(event, file_count) {
|
||||
this.disabled_buttons.attr("disabled", false);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Creates the elements used for displaying the file, and it's upload status, and
|
||||
* attaches them to the DOM
|
||||
*/
|
||||
createStatus: function(event, file_name) {
|
||||
createStatus: function(event, file_name, index, file_count) {
|
||||
var error = ""
|
||||
if(this.input[0].files[index]) {
|
||||
var file = this.input[0].files[index];
|
||||
if(file.size > this.options.max_file_size) {
|
||||
error = egw.lang("File too large");
|
||||
}
|
||||
}
|
||||
if(this.progress)
|
||||
{
|
||||
$j("<li file='"+file_name+"'>"+file_name+"<div class='progressBar'><p/></div></li>").appendTo(this.progress);
|
||||
var status = $j("<li file='"+file_name+"'>"+file_name
|
||||
+"<div class='remove'/><span class='progressBar'><p/></span></li>")
|
||||
.appendTo(this.progress)
|
||||
.click(this, this.cancel);
|
||||
if(error != "")
|
||||
{
|
||||
status.addClass("message validation_error");
|
||||
status.append("<div>"+error+"</diff>");
|
||||
$j(".progressBar",status).css("display", "none");
|
||||
}
|
||||
}
|
||||
return error == "";
|
||||
},
|
||||
|
||||
onProgress: function(event, percent, name, number, total) {
|
||||
if(this.progress)
|
||||
{
|
||||
$j("li[file='"+name+"'] > span.progressBar > p").css("width", Math.ceil(percent*100)+"%");
|
||||
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
onError: function(event, name, error) {
|
||||
console.warn(event,name,error);
|
||||
},
|
||||
|
||||
/**
|
||||
* A file upload is finished, update the UI
|
||||
*/
|
||||
finishUpload: function(event, response, name, number, total) {
|
||||
if(this.progress)
|
||||
{
|
||||
$j("[file='"+name+"']",this.progress).addClass("upload_finished");
|
||||
if(typeof response == 'string') response = jQuery.parseJSON(response);
|
||||
if(response.response[0].data && typeof response.response[0].data.length == 'undefined') {
|
||||
if(typeof this.options.value != 'object') this.options.value = {};
|
||||
for(var key in response.response[0].data) {
|
||||
this.options.value[key] = response.response[0].data[key];
|
||||
}
|
||||
if(this.progress)
|
||||
{
|
||||
$j("[file='"+name+"']",this.progress).addClass("message success");
|
||||
}
|
||||
}
|
||||
else if (this.progress)
|
||||
{
|
||||
$j("[file='"+name+"']",this.progress).addClass("error").css("display", "block");
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Cancel a file
|
||||
*/
|
||||
cancel: function(e) {
|
||||
e.preventDefault();
|
||||
// Look for file name in list
|
||||
var target = $j(e.target);
|
||||
for(var key in e.data.options.value) {
|
||||
if(e.data.options.value[key].name == target.attr("file"))
|
||||
{
|
||||
delete e.data.options.value[key];
|
||||
$j(e.target).remove();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// In case it didn't make it to the list (error)
|
||||
$j(e.target).remove();
|
||||
}
|
||||
});
|
||||
|
||||
|
BIN
etemplate/js/test/gfx/close.png
Executable file
BIN
etemplate/js/test/gfx/close.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 963 B |
@ -194,26 +194,49 @@ span.et2_date span {
|
||||
* File upload
|
||||
*/
|
||||
.et2_file .progress {
|
||||
width: 300px;
|
||||
max-height: 6em;
|
||||
overflow: auto;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
-moz-column-count: 4;
|
||||
-moz-column-gap: 20px;
|
||||
-webkit-column-count: 4;
|
||||
-webkit-column-gap: 20px;
|
||||
column-count: 4;
|
||||
column-gap: 20px;
|
||||
.et2_file .progress span.progressBar {
|
||||
height: 5px;
|
||||
width: 150px;
|
||||
max-width: 150px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
/* Remove icon displayed when hovering */
|
||||
.et2_file .progress li div.remove {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.et2_file .progress li:hover div.remove {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
float: right;
|
||||
display: block;
|
||||
background-image: url("gfx/close.png");
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.et2_file .progress p {
|
||||
background-color: green;
|
||||
height:5px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.et2_file .progress li {
|
||||
color: blue;
|
||||
margin: .5ex;
|
||||
cursor: pointer;
|
||||
}
|
||||
.et2_file .progress li.upload_finished {
|
||||
color: green;
|
||||
/* Hide progress bar when completed */
|
||||
.et2_file .progress li.success > span.progressBar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.egw_tooltip
|
||||
{
|
||||
position: fixed;
|
||||
|
@ -22,7 +22,7 @@ include('../../../header.inc.php');
|
||||
/*
|
||||
* Test using any actual template
|
||||
*/
|
||||
// $template = 'etemplate.et2_test_file_upload';
|
||||
$template = 'etemplate.et2_test_file_upload';
|
||||
if($template) {
|
||||
$etemplate = new etemplate_new('etemplate.et2_test_file_upload');
|
||||
$etemplate->exec('',array());
|
||||
|
Loading…
Reference in New Issue
Block a user