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");
|
$response->error("Could not read session");
|
||||||
return;
|
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']))
|
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_');
|
$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'].'+';
|
$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');
|
// Data to send back to client
|
||||||
list($prefix, $data) = explode(',', file_get_contents($file['tmp_name']));
|
$temp_name = basename($file['tmp_name']);
|
||||||
$file['tmp_name'] = $new_file;
|
$file_data[$temp_name] = array(
|
||||||
fwrite($handle, base64_decode($data));
|
'name' => $file['name'],
|
||||||
fclose($handle);
|
'type' => $file['type']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$response->data($file_data);
|
||||||
|
|
||||||
// Store info for future submit
|
// Check for a callback, call it if there is one
|
||||||
$data = egw_session::appsession($request_id.'_files');
|
foreach($_FILES as $field => $file) {
|
||||||
$form_name = self::form_name($cname, $field);
|
if($element = $template->getElementById($field))
|
||||||
$data[$form_name][] = $file;
|
{
|
||||||
egw_session::appsession($request_id.'_files','',$data);
|
$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);
|
$value = $value_in = self::get_array($content, $form_name);
|
||||||
$valid =& self::get_array($validated, $form_name, true);
|
$valid =& self::get_array($validated, $form_name, true);
|
||||||
|
|
||||||
$files = egw_session::appsession(self::$request->id().'_files');
|
if(!is_array($value)) $value = array();
|
||||||
$valid = $files[$form_name];
|
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'));
|
etemplate_widget::registerWidget('etemplate_widget_file', array('file'));
|
||||||
|
@ -62,9 +62,12 @@ var et2_file = et2_inputWidget.extend({
|
|||||||
var self = this;
|
var self = this;
|
||||||
this.asyncOptions = {
|
this.asyncOptions = {
|
||||||
// Callbacks
|
// 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);},
|
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,
|
sendBoundary: window.FormData || jQuery.browser.mozilla,
|
||||||
url: egw_json_request.prototype._assembleAjaxUrl("etemplate_widget_file::ajax_upload") +
|
url: egw_json_request.prototype._assembleAjaxUrl("etemplate_widget_file::ajax_upload") +
|
||||||
"&request_id="+ instance.etemplate_exec_id
|
"&request_id="+ instance.etemplate_exec_id
|
||||||
@ -84,6 +87,10 @@ var et2_file = et2_inputWidget.extend({
|
|||||||
{
|
{
|
||||||
this.input.html5_upload(this.asyncOptions);
|
this.input.html5_upload(this.asyncOptions);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This may be a problem submitting via ajax
|
||||||
|
}
|
||||||
this.progress = this.options.progress ?
|
this.progress = this.options.progress ?
|
||||||
$j(document.getElementById(this.options.progress)) :
|
$j(document.getElementById(this.options.progress)) :
|
||||||
$j(document.createElement("div")).appendTo(this.node);
|
$j(document.createElement("div")).appendTo(this.node);
|
||||||
@ -94,31 +101,111 @@ var et2_file = et2_inputWidget.extend({
|
|||||||
}
|
}
|
||||||
this.setDOMNode(this.node[0]);
|
this.setDOMNode(this.node[0]);
|
||||||
},
|
},
|
||||||
|
getValue: function() {
|
||||||
|
var value = this.options.value ? this.options.value : this.input.val();
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
|
||||||
getInputNode: function() {
|
getInputNode: function() {
|
||||||
return this.input[0];
|
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
|
* Creates the elements used for displaying the file, and it's upload status, and
|
||||||
* attaches them to the DOM
|
* 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)
|
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;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onError: function(event, name, error) {
|
||||||
|
console.warn(event,name,error);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A file upload is finished, update the UI
|
* A file upload is finished, update the UI
|
||||||
*/
|
*/
|
||||||
finishUpload: function(event, response, name, number, total) {
|
finishUpload: function(event, response, name, number, total) {
|
||||||
if(this.progress)
|
if(typeof response == 'string') response = jQuery.parseJSON(response);
|
||||||
{
|
if(response.response[0].data && typeof response.response[0].data.length == 'undefined') {
|
||||||
$j("[file='"+name+"']",this.progress).addClass("upload_finished");
|
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
|
* File upload
|
||||||
*/
|
*/
|
||||||
.et2_file .progress {
|
.et2_file .progress {
|
||||||
|
width: 300px;
|
||||||
max-height: 6em;
|
max-height: 6em;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
-moz-column-count: 4;
|
.et2_file .progress span.progressBar {
|
||||||
-moz-column-gap: 20px;
|
height: 5px;
|
||||||
-webkit-column-count: 4;
|
width: 150px;
|
||||||
-webkit-column-gap: 20px;
|
max-width: 150px;
|
||||||
column-count: 4;
|
display: inline;
|
||||||
column-gap: 20px;
|
}
|
||||||
|
|
||||||
|
/* 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 {
|
.et2_file .progress li {
|
||||||
color: blue;
|
color: blue;
|
||||||
|
margin: .5ex;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.et2_file .progress li.upload_finished {
|
/* Hide progress bar when completed */
|
||||||
color: green;
|
.et2_file .progress li.success > span.progressBar {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.egw_tooltip
|
.egw_tooltip
|
||||||
{
|
{
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -22,7 +22,7 @@ include('../../../header.inc.php');
|
|||||||
/*
|
/*
|
||||||
* Test using any actual template
|
* Test using any actual template
|
||||||
*/
|
*/
|
||||||
// $template = 'etemplate.et2_test_file_upload';
|
$template = 'etemplate.et2_test_file_upload';
|
||||||
if($template) {
|
if($template) {
|
||||||
$etemplate = new etemplate_new('etemplate.et2_test_file_upload');
|
$etemplate = new etemplate_new('etemplate.et2_test_file_upload');
|
||||||
$etemplate->exec('',array());
|
$etemplate->exec('',array());
|
||||||
|
Loading…
Reference in New Issue
Block a user