diff --git a/etemplate/inc/class.etemplate_widget_vfs.inc.php b/etemplate/inc/class.etemplate_widget_vfs.inc.php
index a88b267f2c..6780f88e72 100644
--- a/etemplate/inc/class.etemplate_widget_vfs.inc.php
+++ b/etemplate/inc/class.etemplate_widget_vfs.inc.php
@@ -77,6 +77,54 @@ class etemplate_widget_vfs extends etemplate_widget_file
}
}
+ /**
+ * Upload via dragging images into ckeditor
+ */
+ public static function ajax_htmlarea_upload()
+ {
+ $request_id = str_replace(' ', '+', rawurldecode($_REQUEST['request_id']));
+ $widget_id = $_REQUEST['widget_id'];
+ if(!self::$request = etemplate_request::read($request_id))
+ {
+ $error = lang("Could not read session");
+ }
+ elseif (!($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 = lang("Could not get template for file upload, callback skipped");
+ }
+ /*elseif (!($widget = $template->getElementById($widget_id)))
+ {
+ $error = "Widget '$widget_id' not found!";
+ }*/
+ elseif (!isset($_FILES['upload']))
+ {
+ $error = lang('No _FILES[upload] found!');
+ }
+ else
+ {
+ $data = self::$request->content[$widget_id];
+ $path = self::store_file($path = self::get_vfs_path($data['to_app'].':'.$data['to_id']).'/', $_FILES['upload']);
+ }
+ // switch regular JSON response handling off
+ egw_json_request::isJSONRequest(false);
+
+ $file = array(
+ "uploaded" => (int)empty($error),
+ "fileName" => html::htmlspecialchars($_FILES['upload']['name']),
+ "url" => egw::link(egw_vfs::download_url($path)),
+ "error" => array(
+ "message" => $error,
+ )
+ );
+
+ header('Content-Type: application/json; charset=utf-8');
+ echo json_encode($file);
+
+ common::egw_exit();
+ }
+
/**
* Ajax callback to receive an incoming file
*
@@ -91,7 +139,7 @@ class etemplate_widget_vfs extends etemplate_widget_file
// Find real path
if($path[0] != '/')
{
- $path = self::get_vfs_path($path, $file['name']);
+ $path = self::get_vfs_path($path);
}
$filename = $file['name'];
if (substr($path,-1) != '/')
@@ -120,6 +168,8 @@ class etemplate_widget_vfs extends etemplate_widget_file
// Try to remove temp file
unlink($file['tmp_name']);
+
+ return $path;
}
/**
diff --git a/etemplate/js/et2_widget_file.js b/etemplate/js/et2_widget_file.js
index 3cf1e6349e..8bed84eb03 100644
--- a/etemplate/js/et2_widget_file.js
+++ b/etemplate/js/et2_widget_file.js
@@ -19,9 +19,9 @@
/**
* Class which implements file upload
- *
+ *
* @augments et2_inputWidget
- */
+ */
var et2_file = et2_inputWidget.extend(
{
attributes: {
@@ -90,14 +90,14 @@ var et2_file = et2_inputWidget.extend(
"type": "any",
"default": et2_no_init,
"description": "A (js) function called when a file to be uploaded is finished."
- },
+ }
},
asyncOptions: {},
/**
* Constructor
- *
+ *
* @memberOf et2_file
*/
init: function() {
@@ -121,19 +121,19 @@ var et2_file = et2_inputWidget.extend(
// Set up the URL to have the request ID & the widget ID
var instance = this.getInstanceManager();
-
+
var self = this;
this.asyncOptions = jQuery.extend({
// Callbacks
- onStart: function(event, file_count) {
- return self.onStart(event, file_count);
+ onStart: function(event, file_count) {
+ return self.onStart(event, file_count);
},
- onFinish: function(event, file_count) {
+ onFinish: function(event, file_count) {
self.onFinish.apply(self, [event, file_count])
},
- onStartOne: function(event, file_name, index, file_count) {
-
+ onStartOne: function(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);},
@@ -158,7 +158,7 @@ var et2_file = et2_inputWidget.extend(
this.span = null;
this.progress = null;
},
-
+
createInputWidget: function() {
this.node = $j(document.createElement("div")).addClass("et2_file");
this.span = $j(document.createElement("span"))
@@ -172,7 +172,7 @@ var et2_file = et2_inputWidget.extend(
.hover(function(e){
$j(span)
.toggleClass('et2_file_spanHover');
- })
+ })
.on({
mousedown:function (e){
$j(span).addClass('et2_file_spanActive');
@@ -218,14 +218,14 @@ var et2_file = et2_inputWidget.extend(
this.setDOMNode(this.node[0]);
},
-
+
/**
* Set a widget or DOM node as a HTML5 file drop target
- *
+ *
* @param String new_target widget ID or DOM node ID to be used as a new target
*/
set_drop_target: function(new_target)
- {
+ {
// Cancel old drop target
if(this.options.drop_target)
{
@@ -236,11 +236,11 @@ var et2_file = et2_inputWidget.extend(
this.resumable.unAssignDrop(drop_target);
}
}
-
+
this.options.drop_target = new_target;
-
+
if(!this.options.drop_target) return;
-
+
// Set up new drop target
var widget = this.getRoot().getWidgetById(this.options.drop_target);
var drop_target = widget && widget.getDOMNode() || document.getElementById(this.options.drop_target);
@@ -265,10 +265,10 @@ var et2_file = et2_inputWidget.extend(
},
/**
- * Set the value of the file widget.
- *
+ * Set the value of the file widget.
+ *
* If you pass a FileList or list of files, it will trigger the async upload
- *
+ *
* @param {FileList|File[]|false} value List of files to be uploaded, or false to reset.
* @param {Event} event Most browsers require the user to initiate file transfers in some way.
* Pass the event in, if you have it.
@@ -289,7 +289,7 @@ var et2_file = et2_inputWidget.extend(
return;
}
-
+
if(typeof value == 'object' && value.length && typeof value[0] == 'object' && value[0].name)
{
try
@@ -304,11 +304,11 @@ var et2_file = et2_inputWidget.extend(
}
}
},
-
+
/**
* Set the value for label
* The label is used as caption for span tag which customize the HTML file upload styling
- *
+ *
* @param {string} value text value of label
*/
set_label: function (value)
@@ -402,13 +402,13 @@ var et2_file = et2_inputWidget.extend(
}
},
-
+
/**
* Add in the request id
*/
beforeSend: function(form) {
var instance = this.getInstanceManager();
-
+
return {
request_id: instance.etemplate_exec_id,
widget_id: this.id
@@ -431,13 +431,13 @@ var et2_file = et2_inputWidget.extend(
.css('cursor', 'default');
event.data = this;
-
+
//Add dropdown_progress
if (this.options.progress_dropdownlist)
{
this._build_progressDropDownList();
}
-
+
// Callback
if(this.options.onStart) return et2_call(this.options.onStart, event, file_count);
return true;
@@ -448,7 +448,7 @@ var et2_file = et2_inputWidget.extend(
*/
onFinish: function() {
this.disabled_buttons.attr("disabled", false).css('cursor','pointer');
-
+
var file_count = this.resumable.files.length;
// Remove files from list
@@ -458,19 +458,19 @@ var et2_file = et2_inputWidget.extend(
}
var event = jQuery.Event('upload');
-
+
event.data = this;
var result = false;
-
+
//Remove progress_dropDown_fileList class and unbind the click handler from body
if (this.options.progress_dropdownlist)
{
this.progress.removeClass("progress_dropDown_fileList");
jQuery(this.node).find('span').removeClass('totalProgress_loader');
jQuery('body').off('click');
- }
-
+ }
+
if(this.options.onFinish && !jQuery.isEmptyObject(this.getValue()))
{
result = et2_call(this.options.onFinish, event, file_count);
@@ -485,19 +485,19 @@ var et2_file = et2_inputWidget.extend(
this.change(this.input);
}
},
-
+
/**
* Build up dropdown progress with total count indicator
- *
+ *
* @todo Implement totalProgress bar instead of ajax-loader, in order to show how much percent of uploading is completed
*/
_build_progressDropDownList: function ()
{
this.progress.addClass("progress_dropDown_fileList");
-
+
//Add uploading indicator and bind hover handler on it
jQuery(this.node).find('span').addClass('totalProgress_loader');
-
+
jQuery(this.node).find('input').hover(function(){
jQuery('.progress_dropDown_fileList').show();
});
@@ -506,11 +506,11 @@ var et2_file = et2_inputWidget.extend(
if (event.target.className != 'remove')
{
jQuery('.progress_dropDown_fileList').hide();
- }
+ }
});
-
+
},
-
+
/**
* Creates the elements used for displaying the file, and it's upload status, and
* attaches them to the DOM
@@ -523,7 +523,7 @@ var et2_file = et2_inputWidget.extend(
if(this.options.max_file_size && file.size > this.options.max_file_size) {
error = this.egw().lang("File too large. Maximum %1", et2_vfsSize.prototype.human_size(this.options.max_file_size));
}
-
+
if(this.options.progress)
{
var widget = this.getRoot().getWidgetById(this.options.progress);
@@ -599,9 +599,9 @@ var et2_file = et2_inputWidget.extend(
.text(this.egw().lang("Server error"));
}
var event = jQuery.Event('upload');
-
+
event.data = this;
-
+
// Callback
if(this.options.onFinishOne)
{
@@ -642,7 +642,7 @@ var et2_file = et2_inputWidget.extend(
e.preventDefault();
// Look for file name in list
var target = $j(e.target).parents("li");
-
+
this.remove_file(e.data);
// In case it didn't make it to the list (error)
diff --git a/etemplate/js/et2_widget_htmlarea.js b/etemplate/js/et2_widget_htmlarea.js
index a22875fb1f..18d4a4683c 100644
--- a/etemplate/js/et2_widget_htmlarea.js
+++ b/etemplate/js/et2_widget_htmlarea.js
@@ -71,11 +71,11 @@ var et2_htmlarea = et2_inputWidget.extend([et2_IResizeable],
type: "html", // "string" would remove html tags by running html_entity_decode
default: et2_no_init
},
- imageDataUrl: {
- name: "imageDataUrl",
- description: "Allow images dragged in as data-url, default false = handle them as fileupload",
- type: "boolean",
- default: false
+ imageUpload: {
+ name: "imageUpload",
+ description: "Url to upload images dragged in or id of link_to widget to it's vfs upload",
+ type: "string",
+ default: null
}
},
@@ -123,6 +123,20 @@ var et2_htmlarea = et2_inputWidget.extend([et2_IResizeable],
if(this.mode == 'ascii' || this.ckeditor != null) return;
var self = this;
+ if (!this.options.imageUpload)
+ {
+ delete self.options.config.imageUploadUrl;
+ }
+ else if (this.options.imageUpload[0] !== '/' && this.options.imageUpload.substr(0, 4) != 'http')
+ {
+ self.options.config.imageUploadUrl = egw.ajaxUrl(self.egw().getAppName()+".etemplate_widget_vfs.ajax_htmlarea_upload.etemplate")+
+ '&request_id='+self.getInstanceManager().etemplate_exec_id+'&widget_id='+this.options.imageUpload;
+ self.options.config.imageUploadUrl = self.options.config.imageUploadUrl.substr(egw.webserverUrl.length+1);
+ }
+ else
+ {
+ self.options.config.imageUploadUrl = this.options.imageUpload.substr(egw.webserverUrl.length+1);
+ }
try
{
this.ckeditor = CKEDITOR.replace(this.dom_id,jQuery.extend({},this.options.config,this.options));
@@ -172,14 +186,13 @@ var et2_htmlarea = et2_inputWidget.extend([et2_IResizeable],
return;
// allow data-URL, returning false to stop regular upload
- if (self.options.imageDataUrl)
+ if (!self.options.imageUpload)
{
- return false;
+ // Remove the image from the text
+ setTimeout( function() {
+ editor.document.$.body.innerHTML = replaceImgText(editor.document.$.body.innerHTML);
+ },200);
}
- // Remove the image from the text
- setTimeout( function() {
- editor.document.$.body.innerHTML = replaceImgText(editor.document.$.body.innerHTML);
- },200);
// Try to pass the image into the first et2_file that will accept it
if(e.data.$.dataTransfer)
@@ -274,7 +287,7 @@ var et2_htmlarea = et2_inputWidget.extend([et2_IResizeable],
var h = 0;
if (typeof this.ckeditor.container !='undefined' && this.ckeditor.container.$.clientHeight > 0)
{
- h = (this.ckeditor.container.$.clientHeight + _height) > 0 ?
+ h = (this.ckeditor.container.$.clientHeight + _height) > 0 ?
this.ckeditor.container.$.clientHeight + _height: this.ckeditor.config.height;
}
else if (this.ckeditor.ui.space('contents'))
@@ -289,7 +302,7 @@ var et2_htmlarea = et2_inputWidget.extend([et2_IResizeable],
this.ckeditor.resize('',h);
}
else // No CKEDITOR
- {
+ {
this.htmlNode.height(this.htmlNode.height() + _height);
}
}
diff --git a/resources/templates/default/edit.xet b/resources/templates/default/edit.xet
index f3296929e0..f18d1b5726 100644
--- a/resources/templates/default/edit.xet
+++ b/resources/templates/default/edit.xet
@@ -79,7 +79,7 @@
-
+
@@ -105,7 +105,7 @@
-
+