WIP image upload via drag into ckeditor 4.5

This commit is contained in:
Ralf Becker 2015-08-07 14:18:07 +00:00
parent 3853343f7e
commit 9ede2c0b70
4 changed files with 123 additions and 60 deletions

View File

@ -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;
}
/**

View File

@ -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)

View File

@ -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);
}
}

View File

@ -79,7 +79,7 @@
</columns>
<rows>
<row valign="top">
<htmlarea statustext="Web-Site for this resource" id="long_description" height="200" toolbar="true"/>
<htmlarea statustext="Web-Site for this resource" id="long_description" height="200" toolbar="true" imageUpload="link_to"/>
</row>
</rows>
</grid>
@ -105,7 +105,7 @@
</row>
</rows>
</grid>
</template>
</template>
<template id="resources.edit_tabs.custom" template="" lang="" group="0" version="">
<grid width="100%" height="245" class="row_on" spacing="0" padding="0" overflow="auto">
<columns>