2800 lines
77 KiB
JavaScript
2800 lines
77 KiB
JavaScript
/**
|
|
* @file SimpleUploads plugin for CKEditor
|
|
* Version: 4.3.12
|
|
* Uploads pasted images and files inside the editor to the server for Firefox and Chrome
|
|
* Feature introduced in: https://bugzilla.mozilla.org/show_bug.cgi?id=490879
|
|
* doesn't include images inside HTML (paste from word). IE11 does.
|
|
https://bugzilla.mozilla.org/show_bug.cgi?id=665341
|
|
https://www.libreoffice.org/bugzilla/show_bug.cgi?id=72083
|
|
|
|
* Includes Drag&Drop file uploads for all the new browsers.
|
|
* Two toolbar buttons to perform quick upload of files.
|
|
* Copyright (C) 2012-14 Alfonso Martínez de Lizarrondo
|
|
*
|
|
improvements: allow d&d between 2 editors in Firefox
|
|
https://bugzilla.mozilla.org/show_bug.cgi?id=454832
|
|
|
|
*/
|
|
|
|
(function() {
|
|
"use strict";
|
|
|
|
// If the selected image is a bmp converts it to a png
|
|
function convertToBmp(ev)
|
|
{
|
|
var data = ev.data,
|
|
isBmp = /\.bmp$/.test(data.name),
|
|
editor = ev.editor;
|
|
|
|
if (!isBmp)
|
|
return;
|
|
|
|
var img = data.image;
|
|
|
|
var canvas = document.createElement("canvas");
|
|
canvas.width = img.width;
|
|
canvas.height = img.height;
|
|
|
|
var ctx = canvas.getContext('2d');
|
|
ctx.drawImage(img, 0, 0);
|
|
|
|
data.file = canvas.toDataURL("image/png");
|
|
data.name = data.name.replace(/\.bmp$/, ".png");
|
|
}
|
|
|
|
// Verifies if the selected image is within the allowed dimensions
|
|
function checkDimension(ev)
|
|
{
|
|
var data = ev.data,
|
|
editor = ev.editor,
|
|
config = editor.config,
|
|
maximum = config.simpleuploads_maximumDimensions;
|
|
|
|
var img = data.image;
|
|
|
|
if (maximum.width && img.width > maximum.width)
|
|
{
|
|
alert(editor.lang.simpleuploads.imageTooWide);
|
|
ev.cancel();
|
|
return;
|
|
}
|
|
|
|
if (maximum.height && img.height > maximum.height)
|
|
{
|
|
alert(editor.lang.simpleuploads.imageTooTall);
|
|
ev.cancel();
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Custom rule similar to the fake Object to avoid generating anything if the user tries to do something strange while a file is being uploaded
|
|
var htmlFilterRules = {
|
|
elements: {
|
|
$: function( element ) {
|
|
var attributes = element.attributes,
|
|
className = attributes && attributes[ "class" ];
|
|
|
|
// remove our wrappers
|
|
if ( className == "SimpleUploadsTmpWrapper" )
|
|
return false;
|
|
}
|
|
}
|
|
};
|
|
|
|
// CSS that we add to the editor for our internal styling
|
|
function getEditorCss( config ) {
|
|
var imgUpload = 'span.SimpleUploadsTmpWrapper>span { top: 50%; margin-top: -0.5em; width: 100%; text-align: center; color: #fff; ' +
|
|
'text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); font-size: 50px; font-family: Calibri,Arial,Sans-serif; pointer-events: none; ' +
|
|
'position: absolute; display: inline-block;}';
|
|
if (config.simpleuploads_hideImageProgress)
|
|
imgUpload = 'span.SimpleUploadsTmpWrapper { color:#333; background-color:#fff; padding:4px; border:1px solid #EEE;}';
|
|
|
|
return '.SimpleUploadsOverEditor { ' + (config.simpleuploads_editorover || 'box-shadow: 0 0 10px 1px #999999 inset !important;') + ' }' +
|
|
'a.SimpleUploadsTmpWrapper { color:#333; background-color:#fff; padding:4px; border:1px solid #EEE;}' +
|
|
'.SimpleUploadsTmpWrapper { display: inline-block; position: relative; pointer-events: none;}' +
|
|
imgUpload +
|
|
'.uploadRect {display: inline-block;height: 0.9em;vertical-align: middle;width: 20px;}' +
|
|
'.uploadRect span {background-color: #999;display: inline-block;height: 100%;vertical-align: top;}' +
|
|
'.SimpleUploadsTmpWrapper .uploadCancel { background-color: #333333;border-radius: 0.5em;color: #FFFFFF;cursor: pointer !important;' +
|
|
'display: inline-block;height: 1em;line-height: 0.8em;margin-left: 4px;padding-left: 0.18em;pointer-events: auto;' +
|
|
'position: relative; text-decoration:none; top: -2px;width: 0.7em;}' +
|
|
'.SimpleUploadsTmpWrapper span uploadCancel { width:1em; padding-left:0}';
|
|
}
|
|
|
|
var filePicker,
|
|
filePickerEditor,
|
|
filePickerForceLink;
|
|
|
|
var IEUpload_fileName,
|
|
IEUpload_caller,
|
|
IEUpload_callback,
|
|
IEUpload_forImage;
|
|
|
|
function PickAndSendFile(editor, forImage, caller, callback) {
|
|
if (IEUpload_fileName)
|
|
{
|
|
alert("Please, wait to finish the current upload");
|
|
return;
|
|
}
|
|
|
|
filePickerForceLink = !forImage;
|
|
filePickerEditor = editor;
|
|
|
|
if (typeof FormData == 'undefined')
|
|
{
|
|
// old IE
|
|
var iframe = document.getElementById("simpleUploadsTarget");
|
|
if (!iframe) {
|
|
iframe = document.createElement("iframe");
|
|
iframe.style.display = "none";
|
|
iframe.id = "simpleUploadsTarget";
|
|
document.body.appendChild(iframe);
|
|
}
|
|
IEUpload_caller = caller;
|
|
IEUpload_callback = callback;
|
|
IEUpload_forImage = forImage;
|
|
|
|
var fnNumber = editor._.simpleuploadsFormUploadFn;
|
|
var fnInitPicker = editor._.simpleuploadsFormInitFn;
|
|
if (!fnNumber)
|
|
{
|
|
editor._.simpleuploadsFormUploadFn = fnNumber = CKEDITOR.tools.addFunction( setUrl, editor );
|
|
editor._.simpleuploadsFormInitFn = fnInitPicker = CKEDITOR.tools.addFunction( function() {
|
|
window.setTimeout(function() {
|
|
var picker = document.getElementById("simpleUploadsTarget").contentWindow.document.getElementById( getUploadInputName(editor) );
|
|
picker.onchange=function() {
|
|
var evdata = {
|
|
name: this.value,
|
|
url: this.form.action,
|
|
context : IEUpload_caller,
|
|
id: 'IEUpload',
|
|
requiresImage: IEUpload_forImage
|
|
};
|
|
// , mode : {type : 'selectedFileIE'}
|
|
|
|
// Remove C:\FakePath\
|
|
var m = evdata.name.match(/\\([^\\]*)$/);
|
|
if (m)
|
|
evdata.name = m[1];
|
|
|
|
var result = filePickerEditor.fire("simpleuploads.startUpload", evdata );
|
|
// in v3 cancel() returns true and in v4 returns false
|
|
// if not canceled it's the evdata object
|
|
if ( typeof result == "boolean" )
|
|
return;
|
|
|
|
if (evdata.requiresImage && !CKEDITOR.plugins.simpleuploads.isImageExtension(filePickerEditor, evdata.name))
|
|
{
|
|
alert(filePickerEditor.lang.simpleuploads.nonImageExtension);
|
|
return;
|
|
}
|
|
|
|
if (IEUpload_callback && IEUpload_callback.start)
|
|
IEUpload_callback.start( evdata );
|
|
|
|
IEUpload_fileName = this.value;
|
|
this.form.action = evdata.url;
|
|
|
|
// Add extra fields if provided
|
|
if (evdata.extraFields)
|
|
{
|
|
var obj = evdata.extraFields;
|
|
var doc = this.ownerDocument;
|
|
for (var prop in obj)
|
|
{
|
|
if( obj.hasOwnProperty( prop ) )
|
|
{
|
|
var field = doc.createElement("input");
|
|
field.type="hidden";
|
|
field.name = prop;
|
|
field.value = obj[prop];
|
|
this.form.appendChild(field);
|
|
}
|
|
}
|
|
}
|
|
|
|
this.form.submit();
|
|
};
|
|
picker.click();
|
|
}, 100);
|
|
}, editor);
|
|
|
|
editor.on( "destroy", function () {
|
|
CKEDITOR.tools.removeFunction( this._.simpleuploadsFormUploadFn );
|
|
CKEDITOR.tools.removeFunction( this._.simpleuploadsFormInitFn );
|
|
} );
|
|
}
|
|
|
|
var inputName = getUploadInputName(editor);
|
|
var form = "<form method='post' enctype='multipart/form-data' action='" + getUploadUrl(editor, fnNumber, forImage) + "'>" +
|
|
"<input type='file' name='" + inputName + "' id='" + inputName + "'></form>";
|
|
|
|
var src= 'document.open(); document.write("' + form + '");document.close();' +
|
|
'window.parent.CKEDITOR.tools.callFunction(' + fnInitPicker + ');';
|
|
|
|
iframe.src = 'javascript:void(function(){' + encodeURIComponent( src ) + '}())';
|
|
|
|
// Detect when the file upload ends to check for errors
|
|
iframe.onreadystatechange = function() {
|
|
if (iframe.readyState == "complete") {
|
|
window.setTimeout(function() {
|
|
if (IEUpload_fileName)
|
|
{
|
|
alert("The file upload has failed");
|
|
IEUpload_fileName=null;
|
|
}
|
|
}, 100);
|
|
}
|
|
};
|
|
|
|
filePicker = null;
|
|
return;
|
|
}
|
|
|
|
if (!filePicker)
|
|
{
|
|
filePicker=document.createElement("input");
|
|
filePicker.type="file";
|
|
filePicker.style.overflow="hidden";
|
|
filePicker.style.width="1px";
|
|
filePicker.style.height="1px";
|
|
filePicker.style.opacity=0.1;
|
|
filePicker.multiple = "multiple";
|
|
|
|
// to trick jQueryUI
|
|
filePicker.position = "absolute";
|
|
filePicker.zIndex = 1000;
|
|
|
|
document.body.appendChild(filePicker);
|
|
filePicker.addEventListener("change", function ()
|
|
{
|
|
var count = filePicker.files.length;
|
|
if (!count)
|
|
return;
|
|
|
|
// Create Undo image
|
|
filePickerEditor.fire( "saveSnapshot" );
|
|
|
|
for(var i=0; i<count; i++)
|
|
{
|
|
var file = filePicker.files[i],
|
|
evData = CKEDITOR.tools.extend({}, filePicker.simpleUploadData);
|
|
|
|
evData.file = file;
|
|
evData.name = file.name;
|
|
evData.id = CKEDITOR.plugins.simpleuploads.getTimeStampId();
|
|
evData.forceLink = filePickerForceLink;
|
|
evData.mode = {
|
|
type : 'selectedFile',
|
|
i : i,
|
|
count : count
|
|
};
|
|
CKEDITOR.plugins.simpleuploads.insertSelectedFile(filePickerEditor, evData);
|
|
}
|
|
});
|
|
}
|
|
|
|
filePicker.value='';
|
|
filePicker.simpleUploadData = {
|
|
context : caller,
|
|
callback : callback,
|
|
requiresImage : forImage
|
|
};
|
|
|
|
// Keep focus on the editor instance.
|
|
if (CKEDITOR.env.webkit)
|
|
{
|
|
var manager = editor.focusManager;
|
|
if (manager && manager.lock)
|
|
{
|
|
manager.lock();
|
|
setTimeout( function() { manager.unlock(); }, 500 );
|
|
}
|
|
}
|
|
filePicker.click();
|
|
}
|
|
|
|
function getUploadUrl(editor, functionNumber, forImage) {
|
|
var url = forImage ? editor.config.filebrowserImageUploadUrl : editor.config.filebrowserUploadUrl;
|
|
if (url=="base64") return url;
|
|
|
|
var params = {};
|
|
params.CKEditor = editor.name;
|
|
params.CKEditorFuncNum = functionNumber;
|
|
params.langCode = editor.langCode;
|
|
return addQueryString( url, params );
|
|
}
|
|
|
|
// Returns the name that should be used for the file upload input
|
|
function getUploadInputName(editor) {
|
|
return editor.config.simpleuploads_inputname || "upload";
|
|
}
|
|
|
|
function setUrl( fileUrl, msg )
|
|
{
|
|
// The "msg" argument may be used to pass the error message to the editor.
|
|
if ( typeof msg == "string" && msg && !fileUrl)
|
|
alert( msg );
|
|
|
|
var editor = filePickerEditor;
|
|
editor.fire('simpleuploads.endUpload', { name: IEUpload_fileName, ok: (!!fileUrl) } );
|
|
|
|
if (IEUpload_callback)
|
|
{
|
|
IEUpload_callback.upload( fileUrl, msg, {context: IEUpload_caller} );
|
|
IEUpload_fileName = null;
|
|
IEUpload_callback = null;
|
|
IEUpload_caller = null;
|
|
return;
|
|
}
|
|
|
|
if ( fileUrl ) {
|
|
var element,
|
|
attribute;
|
|
if (filePickerForceLink)
|
|
{
|
|
element = new CKEDITOR.dom.element( "a", editor.document );
|
|
element.setText( fileUrl.match(/\/([^\/]+)$/)[1] );
|
|
attribute = "href";
|
|
}
|
|
else
|
|
{
|
|
element = new CKEDITOR.dom.element( "img", editor.document );
|
|
attribute = "src";
|
|
|
|
element.on("load", function(e) {
|
|
e.removeListener();
|
|
element.removeListener("error", errorListener);
|
|
|
|
element.setAttribute("width", element.$.width);
|
|
element.setAttribute("height", element.$.height);
|
|
|
|
editor.fire('simpleuploads.finishedUpload', { name: IEUpload_fileName, element: element } );
|
|
});
|
|
|
|
element.on("error", errorListener, null, element);
|
|
}
|
|
element.setAttribute(attribute, fileUrl);
|
|
element.data( "cke-saved-" + attribute, fileUrl);
|
|
editor.insertElement(element);
|
|
|
|
if (filePickerForceLink)
|
|
filePickerEditor.fire("simpleuploads.finishedUpload", { name: IEUpload_fileName, element: element } );
|
|
}
|
|
|
|
IEUpload_fileName = null;
|
|
IEUpload_caller = null;
|
|
}
|
|
|
|
/**
|
|
* Adds (additional) arguments to given url.
|
|
*
|
|
* @param {String}
|
|
* url The url.
|
|
* @param {Object}
|
|
* params Additional parameters.
|
|
*/
|
|
function addQueryString( url, params )
|
|
{
|
|
var queryString = [];
|
|
|
|
if ( !params )
|
|
return url;
|
|
else
|
|
{
|
|
for ( var i in params )
|
|
queryString.push( i + "=" + encodeURIComponent( params[ i ] ) );
|
|
}
|
|
|
|
return url + ( ( url.indexOf( "?" ) != -1 ) ? "&" : "?" ) + queryString.join( "&" );
|
|
}
|
|
|
|
function hasFiles(e)
|
|
{
|
|
var ev = e.data.$,
|
|
data = ev.dataTransfer;
|
|
|
|
if (!data || !data.types)
|
|
return false;
|
|
|
|
if (data.types.contains && data.types.contains("Files") && (!data.types.contains("text/html")) ) return true;
|
|
if (data.types.indexOf && data.types.indexOf( "Files" )!=-1) return true;
|
|
return false;
|
|
}
|
|
|
|
function receivedUrl(fileUrl, data, editor, el, attribute)
|
|
{
|
|
if (el.$.nodeName.toLowerCase() == "span")
|
|
{
|
|
// create the final img, getting rid of the fake div
|
|
var img;
|
|
if (data.originalNode)
|
|
{
|
|
img = data.originalNode.cloneNode( true );
|
|
// reset size
|
|
img.removeAttribute("width");
|
|
img.removeAttribute("height");
|
|
img.style.width = "";
|
|
img.style.height = "";
|
|
img = new CKEDITOR.dom.element( img );
|
|
}
|
|
else
|
|
{
|
|
img = new CKEDITOR.dom.element( "img", editor.document );
|
|
}
|
|
|
|
// wait to replace until the image is loaded to prevent flickering
|
|
img.on("load", function(e) {
|
|
e.removeListener();
|
|
img.removeListener( "error", errorListener);
|
|
|
|
checkLoadedImage(img, editor, el, data.name);
|
|
});
|
|
|
|
img.on("error", errorListener, null, el);
|
|
|
|
img.data( 'cke-saved-src', fileUrl);
|
|
img.setAttribute( 'src', fileUrl);
|
|
|
|
// in case the user tries to get the html right now, a little protection
|
|
el.data('cke-real-element-type', "img");
|
|
el.data('cke-realelement', encodeURIComponent( img.getOuterHtml() ));
|
|
el.data('cke-real-node-type', CKEDITOR.NODE_ELEMENT);
|
|
|
|
// SVG are buggy in Firefox and IE
|
|
// replace the image now without waiting to get confirmation
|
|
if ( /\.svg$/.test(data.name) )
|
|
{
|
|
img.removeAllListeners();
|
|
img.replace( el );
|
|
|
|
editor.fire('simpleuploads.finishedUpload', { name: name, element: img } );
|
|
|
|
// Correct the Undo image
|
|
editor.fire( "updateSnapshot" );
|
|
}
|
|
|
|
return;
|
|
}
|
|
if (data.originalNode)
|
|
{
|
|
var newEl = data.originalNode.cloneNode( true );
|
|
el.$.parentNode.replaceChild(newEl, el.$);
|
|
el = new CKEDITOR.dom.element( newEl );
|
|
}
|
|
else
|
|
{
|
|
el.removeAttribute( "id" );
|
|
el.removeAttribute( "class" );
|
|
el.removeAttribute( 'contentEditable' );
|
|
el.setHtml( el.getFirst().getHtml() );
|
|
}
|
|
|
|
el.data( 'cke-saved-' + attribute, fileUrl);
|
|
el.setAttribute( attribute, fileUrl);
|
|
editor.fire('simpleuploads.finishedUpload', { name: data.name, element: el } );
|
|
}
|
|
|
|
// store a reference of the native URL object as the CodeCog latex editor overwrites it
|
|
// http://www.codecogs.com/pages/forums/pagegen.php?id=2803
|
|
var nativeURL = window.URL || window.webkitURL;
|
|
|
|
CKEDITOR.plugins.add( "simpleuploads",
|
|
{
|
|
//lang : 'en,es', v4 style for builder not compatible with v3
|
|
lang : ['en','ar','cs','de','es','fr','he','hu','it','ja','ko','nl','pl','pt-br','ru','tr','zh-cn'], // "en" the first one to use it as default
|
|
icons: 'addfile,addimage', // %REMOVE_LINE_CORE%
|
|
|
|
onLoad : function() {
|
|
// v4
|
|
// In v4 this setting is global for all instances:
|
|
if (CKEDITOR.addCss)
|
|
CKEDITOR.addCss( getEditorCss(CKEDITOR.config) );
|
|
|
|
// CSS for container
|
|
var node = CKEDITOR.document.getHead().append( 'style' );
|
|
node.setAttribute( 'type', 'text/css' );
|
|
var content = '.SimpleUploadsOverContainer {' + (CKEDITOR.config.simpleuploads_containerover || 'box-shadow: 0 0 10px 1px #99DD99 !important;') + '} ' +
|
|
'.SimpleUploadsOverDialog {' + (CKEDITOR.config.simpleuploads_dialogover || 'box-shadow: 0 0 10px 4px #999999 inset !important;') + '} ' +
|
|
'.SimpleUploadsOverCover {' + (CKEDITOR.config.simpleuploads_coverover || 'box-shadow: 0 0 10px 4px #99DD99 !important;') + '} ';
|
|
|
|
// Inject the throbber styles in the page:
|
|
// If this were part of the official code it should be placed in the dialog.css skin
|
|
// We must specify the .cke_throbber for the inner divs or the reset css won't allow to use the background-color
|
|
content += [".cke_throbber {margin: 0 auto; width: 100px;}",
|
|
".cke_throbber div {float: left; width: 8px; height: 9px; margin-left: 2px; margin-right: 2px; font-size: 1px;}",
|
|
".cke_throbber .cke_throbber_1 {background-color: #737357;}",
|
|
".cke_throbber .cke_throbber_2 {background-color: #8f8f73;}",
|
|
".cke_throbber .cke_throbber_3 {background-color: #abab8f;}",
|
|
".cke_throbber .cke_throbber_4 {background-color: #c7c7ab;}",
|
|
".cke_throbber .cke_throbber_5 {background-color: #e3e3c7;}",
|
|
".uploadRect {display: inline-block;height: 11px;vertical-align: middle;width: 50px;}",
|
|
".uploadRect span {background-color: #999;display: inline-block;height: 100%;vertical-align: top;}",
|
|
".uploadName {display: inline-block;max-width: 180px;overflow: hidden;text-overflow: ellipsis;vertical-align: top;white-space: pre;}",
|
|
".uploadText {font-size:80%;}",
|
|
".cke_throbberMain a {cursor: pointer; font-size: 14px; font-weight:bold; padding: 4px 5px;position: absolute;right:0; text-decoration:none; top: -2px;}",
|
|
".cke_throbberMain {background-color: #FFF; border:1px solid #e5e5e5; padding:4px 14px 4px 4px; min-width:250px; position:absolute;}"]
|
|
.join(' ');
|
|
|
|
if ( CKEDITOR.env.ie && CKEDITOR.env.version < 11)
|
|
node.$.styleSheet.cssText = content;
|
|
else
|
|
node.$.innerHTML = content;
|
|
},
|
|
|
|
init : function( editor ) {
|
|
var config = editor.config;
|
|
|
|
if (typeof config.simpleuploads_imageExtensions == "undefined")
|
|
config.simpleuploads_imageExtensions = "jpe?g|gif|png";
|
|
|
|
// v3
|
|
if (editor.addCss)
|
|
editor.addCss( getEditorCss(config) );
|
|
|
|
// if not defined specifically for images, reuse the default file upload url
|
|
if (!config.filebrowserImageUploadUrl)
|
|
config.filebrowserImageUploadUrl = config.filebrowserUploadUrl;
|
|
|
|
if (!config.filebrowserUploadUrl && !config.filebrowserImageUploadUrl)
|
|
{
|
|
if (window.console && console.log)
|
|
{
|
|
console.log("The editor is missing the 'config.filebrowserUploadUrl' entry to know the URL that will handle uploaded files.\r\n" +
|
|
"It should handle the posted file as shown in Example 3: http://docs.ckeditor.com/#!/guide/dev_file_browser_api-section-example-3 \r\n" +
|
|
"More info: http://alfonsoml.blogspot.com/2009/12/using-your-own-uploader-in-ckeditor.html");
|
|
console[ console.warn ? "warn" : "log" ]("The 'SimpleUploads' plugin now is disabled.");
|
|
}
|
|
return;
|
|
}
|
|
|
|
// if upload URL is set to base64 data urls then exit if the browser doesn't support the file reader api
|
|
if (config.filebrowserImageUploadUrl=="base64" && (typeof FormData == 'undefined'))
|
|
return;
|
|
|
|
// v 4.1 filters
|
|
if (editor.addFeature)
|
|
{
|
|
editor.addFeature( {
|
|
allowedContent: 'img[!src,width,height];a[!href];span[id](SimpleUploadsTmpWrapper);'
|
|
} );
|
|
}
|
|
|
|
// Manages the throbber animation that appears to show a lengthy operation
|
|
CKEDITOR.dialog.prototype.showThrobber = function () {
|
|
if (!this.throbber)
|
|
{
|
|
this.throbber = {
|
|
update : function()
|
|
{
|
|
var throbberParent = this.throbberParent.$,
|
|
throbberBlocks = throbberParent.childNodes,
|
|
lastClass = throbberParent.lastChild.className;
|
|
|
|
// From the last to the second one, copy the class from the previous one.
|
|
for ( var i = throbberBlocks.length - 1 ; i > 0 ; i-- )
|
|
throbberBlocks[i].className = throbberBlocks[i-1].className ;
|
|
|
|
// For the first one, copy the last class (rotation).
|
|
throbberBlocks[0].className = lastClass ;
|
|
},
|
|
|
|
create: function( dialog )
|
|
{
|
|
if (this.throbberCover)
|
|
return;
|
|
|
|
var cover = CKEDITOR.dom.element.createFromHtml( '<div style="background-color:rgba(255,255,255,0.95);width:100%;height:100%;top:0;left:0; position:absolute; visibility:none;z-index:100;"></div>');
|
|
dialog.parts.close.setStyle("z-index", 101);
|
|
// IE8
|
|
if (CKEDITOR.env.ie && CKEDITOR.env.version<9)
|
|
{
|
|
cover.setStyle("zoom", 1);
|
|
cover.setStyle("filter", "progid:DXImageTransform.Microsoft.gradient(startColorstr=#EEFFFFFF,endColorstr=#EEFFFFFF)");
|
|
}
|
|
|
|
cover.appendTo(dialog.parts.dialog);
|
|
this.throbberCover = cover;
|
|
//dialog.throbberCover = cover;
|
|
|
|
var mainThrobber = new CKEDITOR.dom.element("div");
|
|
this.mainThrobber = mainThrobber;
|
|
var throbberParent = new CKEDITOR.dom.element("div");
|
|
this.throbberParent = throbberParent;
|
|
var throbberTitle = new CKEDITOR.dom.element("div");
|
|
this.throbberTitle = throbberTitle;
|
|
cover.append(mainThrobber).addClass("cke_throbberMain");
|
|
mainThrobber.append(throbberTitle).addClass("cke_throbberTitle");
|
|
mainThrobber.append(throbberParent).addClass("cke_throbber");
|
|
|
|
// Create the throbber blocks.
|
|
var classIds = [ 1,2,3,4,5,4,3,2 ] ;
|
|
while ( classIds.length > 0 )
|
|
throbberParent.append( new CKEDITOR.dom.element("div") ).addClass('cke_throbber_' + classIds.shift()) ;
|
|
|
|
this.center();
|
|
|
|
// Protection if the dialog is closed without removing the throbber
|
|
dialog.on("hide", this.hide, this);
|
|
},
|
|
center : function()
|
|
{
|
|
var mainThrobber = this.mainThrobber,
|
|
cover = this.throbberCover;
|
|
// Center the throbber
|
|
var x = ( cover.$.offsetWidth - mainThrobber.$.offsetWidth ) / 2,
|
|
y = ( cover.$.offsetHeight - mainThrobber.$.offsetHeight ) / 2;
|
|
mainThrobber.setStyle( "left", x.toFixed() + "px" );
|
|
mainThrobber.setStyle( "top", y.toFixed() + "px" );
|
|
},
|
|
show : function()
|
|
{
|
|
this.create(CKEDITOR.dialog.getCurrent());
|
|
|
|
this.throbberCover.setStyle("visibility", "");
|
|
|
|
// Setup the animation interval.
|
|
this.timer = setInterval( CKEDITOR.tools.bind(this.update, this), 100 ) ;
|
|
},
|
|
hide : function()
|
|
{
|
|
if ( this.timer )
|
|
{
|
|
clearInterval( this.timer ) ;
|
|
this.timer = null ;
|
|
}
|
|
|
|
if (!this.throbberCover)
|
|
return;
|
|
|
|
this.throbberCover.setStyle("visibility", "hidden");
|
|
}
|
|
};
|
|
}
|
|
this.throbber.show();
|
|
};
|
|
|
|
|
|
// Add a listener to check file size and valid extensions
|
|
editor.on( "simpleuploads.startUpload" , function(ev)
|
|
{
|
|
var editor = ev.editor,
|
|
config = editor.config,
|
|
file = ev.data && ev.data.file;
|
|
if (config.simpleuploads_maxFileSize &&
|
|
file && file.size &&
|
|
file.size > config.simpleuploads_maxFileSize )
|
|
{
|
|
alert( editor.lang.simpleuploads.fileTooBig );
|
|
ev.cancel();
|
|
}
|
|
var name = ev.data.name;
|
|
if (config.simpleuploads_invalidExtensions)
|
|
{
|
|
var reInvalid = new RegExp( "\.(?:" + config.simpleuploads_invalidExtensions + ")$", "i");
|
|
if ( reInvalid.test( name ) )
|
|
{
|
|
alert( editor.lang.simpleuploads.invalidExtension );
|
|
ev.cancel();
|
|
}
|
|
}
|
|
if (config.simpleuploads_acceptedExtensions)
|
|
{
|
|
var reAccepted = new RegExp( "\.(?:" + config.simpleuploads_acceptedExtensions + ")$", "i");
|
|
if ( !reAccepted.test( name ) )
|
|
{
|
|
alert( editor.lang.simpleuploads.nonAcceptedExtension.replace("%0", config.simpleuploads_acceptedExtensions) );
|
|
ev.cancel();
|
|
}
|
|
}
|
|
});
|
|
|
|
// Special listener that captures uploads of images and if there's some listener set for "simpleuploads.localImageReady"
|
|
// event, prepare an image with the local data (to check dimensions, convert between formats, resize...)
|
|
editor.on( 'simpleuploads.startUpload' , function(ev) {
|
|
var data = ev.data,
|
|
editor = ev.editor;
|
|
|
|
// If this function has already pre-processed the file, exit.
|
|
if (data.image)
|
|
return;
|
|
|
|
// Handle here only images
|
|
if (data.forceLink || !CKEDITOR.plugins.simpleuploads.isImageExtension(editor, data.name))
|
|
return;
|
|
|
|
// If the mode hasn't been set (picked files in IE8), don't process the data
|
|
if (!data.mode || !data.mode.type)
|
|
return;
|
|
|
|
// As this forces an asynchronous callback use it only when there's a listener set.
|
|
if (!editor.hasListeners( 'simpleuploads.localImageReady' ))
|
|
return;
|
|
|
|
// Cancel the default processing
|
|
ev.cancel();
|
|
|
|
if (data.mode.type=="base64paste")
|
|
{
|
|
// to handle multiple images in IE11, insert a marker for each one.
|
|
// we add our class so it won't remain if it's rejected in another step
|
|
var idTmp = CKEDITOR.plugins.simpleuploads.getTimeStampId();
|
|
data.result = "<span id='" + idTmp + "' class='SimpleUploadsTmpWrapper' style='display:none'> </span>";
|
|
data.mode.id = idTmp;
|
|
}
|
|
|
|
var img = new Image;
|
|
img.onload = function() {
|
|
var evData = CKEDITOR.tools.extend({}, data);
|
|
evData.image = img;
|
|
|
|
var result = editor.fire('simpleuploads.localImageReady', evData);
|
|
|
|
// in v3 cancel() returns true and in v4 returns false
|
|
// if not canceled it's the evdata object
|
|
if ( typeof result == "boolean" )
|
|
return;
|
|
|
|
CKEDITOR.plugins.simpleuploads.insertProcessedFile(ev.editor, evData);
|
|
};
|
|
|
|
if (typeof data.file == "string")
|
|
img.src = data.file; // base64 encoded
|
|
else
|
|
img.src = nativeURL.createObjectURL( data.file ); // FileReader
|
|
});
|
|
|
|
|
|
// Setup listeners if the config specifies that they should be used
|
|
if (config.simpleuploads_convertBmp)
|
|
editor.on( 'simpleuploads.localImageReady', convertToBmp);
|
|
|
|
if (config.simpleuploads_maximumDimensions)
|
|
editor.on( 'simpleuploads.localImageReady', checkDimension);
|
|
|
|
|
|
// workaround for image2 support
|
|
editor.on( 'simpleuploads.finishedUpload' , function(ev) {
|
|
if (editor.widgets && editor.plugins.image2) {
|
|
var element = ev.data.element;
|
|
if (element.getName()=="img")
|
|
{
|
|
var widget = editor.widgets.getByElement(element);
|
|
if (widget)
|
|
{
|
|
widget.data.src = element.data( 'cke-saved-src' );
|
|
widget.data.width = element.$.width;
|
|
widget.data.height = element.$.height;
|
|
}
|
|
else
|
|
{
|
|
// They have renamed the widget after the initial release :-(
|
|
// Let's try with both, one of them will work
|
|
editor.widgets.initOn(element, "image2");
|
|
editor.widgets.initOn(element, "image");
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// Paste from clipboard:
|
|
editor.on( "paste", function(e) {
|
|
var pasteData = e.data,
|
|
html = (pasteData.html || ( pasteData.type && pasteData.type=='html' && pasteData.dataValue));
|
|
|
|
if (!html)
|
|
return;
|
|
|
|
// strip out webkit-fake-url as they are useless:
|
|
if (CKEDITOR.env.webkit && (html.indexOf("webkit-fake-url")>0) )
|
|
{
|
|
alert("Sorry, the images pasted with Safari aren't usable");
|
|
window.open("https://bugs.webkit.org/show_bug.cgi?id=49141");
|
|
html = html.replace( /<img src="webkit-fake-url:.*?">/g, "");
|
|
}
|
|
|
|
// Handles image pasting in Firefox
|
|
// Replace data: images in Firefox and upload them.
|
|
// No longer required with Firefox 22
|
|
html = html.replace( /<img(.*?) src="data:image\/.{3,4};base64,.*?"(.*?)>/g, function( img )
|
|
{
|
|
if (!editor.config.filebrowserImageUploadUrl)
|
|
return "";
|
|
|
|
var match = img.match(/"(data:image\/(.{3,4});base64,.*?)"/),
|
|
imgData = match[1],
|
|
type = match[2].toLowerCase(),
|
|
id = CKEDITOR.plugins.simpleuploads.getTimeStampId();
|
|
|
|
// If it's too small then leave it as is.
|
|
if (imgData.length<128)
|
|
return img;
|
|
|
|
if (type=="jpeg")
|
|
type="jpg";
|
|
|
|
var fileName = id + '.' + type,
|
|
uploadData = {
|
|
context : "pastedimage",
|
|
name : fileName,
|
|
id : id,
|
|
forceLink : false,
|
|
file : imgData,
|
|
mode : { type: "base64paste"}
|
|
};
|
|
|
|
if (!uploadFile(editor, uploadData))
|
|
return uploadData.result;
|
|
|
|
var animation = uploadData.element,
|
|
content = animation.$.innerHTML;
|
|
animation.$.innerHTML = " ";
|
|
|
|
// only once
|
|
editor.on( "afterPaste" , function( ev ) {
|
|
ev.removeListener();
|
|
|
|
var span = editor.document.$.getElementById(id);
|
|
if (!span)
|
|
return;
|
|
|
|
// fight against ACF in v4.1 and IE11, insert svg afterwards
|
|
span.innerHTML = content;
|
|
setupCancelButton( editor, uploadData );
|
|
} );
|
|
|
|
return animation.getOuterHtml();
|
|
});
|
|
|
|
if (e.data.html)
|
|
e.data.html = html;
|
|
else
|
|
e.data.dataValue = html;
|
|
});
|
|
|
|
var avoidBadUndo = function(e) {
|
|
if (editor.mode != "wysiwyg")
|
|
return;
|
|
|
|
var root = editor.document;
|
|
if (editor.editable)
|
|
root = editor.editable();
|
|
|
|
// detect now if the contents include our tmp node
|
|
if (root.$.querySelector( ".SimpleUploadsTmpWrapper") )
|
|
{
|
|
var move = e.name.substr(5).toLowerCase();
|
|
|
|
// If the user tried to redo but there are no more saved images forward and this is a bad image, move back instead.
|
|
if ( move=="redo" && editor.getCommand(move).state == CKEDITOR.TRISTATE_DISABLED )
|
|
move = "undo";
|
|
|
|
// Move one extra step back/forward
|
|
editor.execCommand( move );
|
|
}
|
|
};
|
|
// on dev mode plugins might not load in the right order with empty cache
|
|
var cmd = editor.getCommand('undo');
|
|
cmd && cmd.on('afterUndo', avoidBadUndo );
|
|
cmd = editor.getCommand('redo');
|
|
cmd && editor.getCommand('redo').on('afterRedo', avoidBadUndo );
|
|
// http://dev.ckeditor.com/ticket/10101
|
|
editor.on('afterUndo', avoidBadUndo );
|
|
editor.on('afterRedo', avoidBadUndo );
|
|
|
|
// Buttons to launch the file picker easily
|
|
// Files
|
|
editor.addCommand( 'addFile', {
|
|
exec: function( editor ) {
|
|
PickAndSendFile(editor, false, this);
|
|
}
|
|
});
|
|
|
|
editor.ui.addButton( 'addFile', {
|
|
label: editor.lang.simpleuploads.addFile,
|
|
command: 'addFile',
|
|
icon : this.path + 'icons/addfile.png', // %REMOVE_LINE_CORE%
|
|
toolbar: 'insert',
|
|
allowedContent : 'a[!href];span[id](SimpleUploadsTmpWrapper);',
|
|
requiredContent : 'a[href]'
|
|
});
|
|
|
|
// Images
|
|
editor.addCommand( 'addImage', {
|
|
exec: function( editor ) {
|
|
PickAndSendFile(editor, true, this);
|
|
}
|
|
});
|
|
|
|
editor.ui.addButton( 'addImage', {
|
|
label: editor.lang.simpleuploads.addImage,
|
|
command: 'addImage',
|
|
icon : this.path + 'icons/addimage.png', // %REMOVE_LINE_CORE%
|
|
toolbar: 'insert',
|
|
allowedContent : 'img[!src,width,height];span[id](SimpleUploadsTmpWrapper);',
|
|
requiredContent : 'img[src]'
|
|
});
|
|
|
|
|
|
if (typeof FormData == 'undefined')
|
|
return;
|
|
|
|
var root,
|
|
visibleRoot,
|
|
pasteRoot;
|
|
|
|
var minX=-1, minY, maxX, maxY;
|
|
// Hint in the main document
|
|
var mainMinX=-1, mainMinY, mainMaxX, mainMaxY;
|
|
|
|
var removeBaseHighlight = function() {
|
|
var dialog = CKEDITOR.dialog.getCurrent();
|
|
if ( dialog )
|
|
{
|
|
var div = dialog.parts.title.getParent();
|
|
div.removeClass( 'SimpleUploadsOverCover' );
|
|
}
|
|
else
|
|
{
|
|
editor.container.removeClass( 'SimpleUploadsOverContainer' );
|
|
}
|
|
};
|
|
|
|
editor.on( 'destroy', function() {
|
|
CKEDITOR.removeListener( 'simpleuploads.droppedFile', removeBaseHighlight);
|
|
CKEDITOR.document.removeListener( 'dragenter', CKEDITORdragenter);
|
|
CKEDITOR.document.removeListener( 'dragleave', CKEDITORdragleave);
|
|
domUnload();
|
|
});
|
|
|
|
var domUnload = function() {
|
|
if (!root || !root.removeListener)
|
|
return;
|
|
|
|
pasteRoot.removeListener( 'paste', pasteListener);
|
|
root.removeListener( 'dragenter', rootDragEnter);
|
|
root.removeListener( 'dragleave', rootDragLeave);
|
|
root.removeListener( 'dragover', rootDragOver);
|
|
root.removeListener( 'drop', rootDropListener);
|
|
|
|
pasteRoot = null;
|
|
root = null;
|
|
visibleRoot = null;
|
|
};
|
|
|
|
CKEDITOR.on( 'simpleuploads.droppedFile', removeBaseHighlight);
|
|
|
|
var CKEDITORdragenter = function(e) {
|
|
if (mainMinX == -1)
|
|
{
|
|
if (!hasFiles(e))
|
|
return;
|
|
|
|
var dialog = CKEDITOR.dialog.getCurrent();
|
|
if ( dialog )
|
|
{
|
|
if (!dialog.handleFileDrop)
|
|
return;
|
|
|
|
var div = dialog.parts.title.getParent();
|
|
div.addClass( 'SimpleUploadsOverCover' );
|
|
}
|
|
else
|
|
{
|
|
if (!editor.readOnly)
|
|
editor.container.addClass( 'SimpleUploadsOverContainer' );
|
|
}
|
|
|
|
mainMinX=0;
|
|
mainMinY=0;
|
|
mainMaxX=CKEDITOR.document.$.body.parentNode.clientWidth;
|
|
mainMaxY=CKEDITOR.document.$.body.parentNode.clientHeight;
|
|
}
|
|
};
|
|
var CKEDITORdragleave = function(e) {
|
|
if ( mainMinX == -1 )
|
|
return;
|
|
|
|
var ev = e.data.$;
|
|
if ((ev.clientX<=mainMinX) || (ev.clientY<=mainMinY) || (ev.clientX>=mainMaxX) || (ev.clientY>=mainMaxY))
|
|
{
|
|
removeBaseHighlight();
|
|
mainMinX = -1;
|
|
}
|
|
};
|
|
|
|
CKEDITOR.document.on( 'dragenter', CKEDITORdragenter);
|
|
CKEDITOR.document.on( 'dragleave', CKEDITORdragleave);
|
|
|
|
var rootDropListener = function(e) {
|
|
// editor
|
|
visibleRoot.removeClass( "SimpleUploadsOverEditor" );
|
|
minX = -1;
|
|
|
|
//container
|
|
// We fire an event on CKEDITOR so all the instances get notified and remove their class
|
|
// This is an "internal" event to the plugin
|
|
CKEDITOR.fire( 'simpleuploads.droppedFile' );
|
|
mainMinX = -1;
|
|
|
|
if (editor.readOnly)
|
|
{
|
|
e.data.preventDefault();
|
|
return false;
|
|
}
|
|
|
|
var ev = e.data.$,
|
|
data = ev.dataTransfer;
|
|
if ( data && data.files && data.files.length>0 )
|
|
{
|
|
// Create Undo image
|
|
editor.fire( "saveSnapshot" );
|
|
|
|
// Prevent default insertion
|
|
e.data.preventDefault();
|
|
|
|
var dropLocation = {
|
|
ev : ev,
|
|
range : false,
|
|
count : data.files.length,
|
|
rangeParent : ev.rangeParent,
|
|
rangeOffset : ev.rangeOffset
|
|
};
|
|
|
|
// store the location for IE
|
|
if (!dropLocation.rangeParent && !document.caretRangeFromPoint)
|
|
{
|
|
if (ev.target.nodeName.toLowerCase()!="img")
|
|
{
|
|
var doc = editor.document.$;
|
|
if ( doc.body.createTextRange )
|
|
{
|
|
var textRange = doc.body.createTextRange();
|
|
try
|
|
{
|
|
textRange.moveToPoint( ev.clientX, ev.clientY );
|
|
|
|
dropLocation.range = textRange;
|
|
}
|
|
catch (ex)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for( var i=0; i<data.files.length; i++)
|
|
{
|
|
var file = data.files[ i ],
|
|
id = CKEDITOR.tools.getNextId(),
|
|
fileName = file.name,
|
|
evData = {
|
|
context : ev,
|
|
name : fileName,
|
|
file : file,
|
|
forceLink : ev.shiftKey, // If shift is pressed, create a link even if the drop is an image
|
|
id : id,
|
|
mode : {
|
|
type : 'droppedFile',
|
|
dropLocation: dropLocation
|
|
}
|
|
};
|
|
|
|
CKEDITOR.plugins.simpleuploads.insertDroppedFile(editor, evData);
|
|
}
|
|
}
|
|
};
|
|
|
|
var rootDragEnter = function(e) {
|
|
if (minX == -1)
|
|
{
|
|
if (!hasFiles(e))
|
|
return;
|
|
|
|
if (!editor.readOnly)
|
|
visibleRoot.addClass( "SimpleUploadsOverEditor" );
|
|
|
|
var rect = visibleRoot.$.getBoundingClientRect();
|
|
minX=rect.left;
|
|
minY=rect.top;
|
|
maxX=minX + visibleRoot.$.clientWidth;
|
|
maxY=minY + visibleRoot.$.clientHeight;
|
|
}
|
|
};
|
|
|
|
var rootDragLeave = function(e) {
|
|
if ( minX == -1 )
|
|
return;
|
|
|
|
var ev = e.data.$;
|
|
|
|
if ((ev.clientX<=minX) || (ev.clientY<=minY) || (ev.clientX>=maxX) || (ev.clientY>=maxY))
|
|
{
|
|
visibleRoot.removeClass( "SimpleUploadsOverEditor" );
|
|
minX = -1;
|
|
}
|
|
};
|
|
|
|
var rootDragOver = function(e) {
|
|
if (minX != -1 )
|
|
{
|
|
if (editor.readOnly)
|
|
{
|
|
e.data.$.dataTransfer.dropEffect = "none";
|
|
e.data.preventDefault();
|
|
return false;
|
|
}
|
|
|
|
// Show Copy instead of Move. Works for Chrome
|
|
// Firefox and IE10 don't respect this change (Firefox by default doesn't enter here)
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=484511
|
|
e.data.$.dataTransfer.dropEffect = 'copy';
|
|
|
|
// IE always requires this
|
|
// Chrome almost fixed the requirement, but it's required if the body is a single line and the user drops below it.
|
|
if (!CKEDITOR.env.gecko)
|
|
e.data.preventDefault();
|
|
}
|
|
};
|
|
|
|
// drag & drop, paste
|
|
editor.on( 'contentDom', function(ev) {
|
|
root = editor.document;
|
|
visibleRoot = root.getBody().getParent();
|
|
|
|
// v4 inline editing
|
|
// ELEMENT_MODE_INLINE
|
|
if (editor.elementMode == 3 )
|
|
{
|
|
root = editor.editable();
|
|
visibleRoot = root;
|
|
}
|
|
// v4 divArea
|
|
if ( editor.elementMode == 1 && 'divarea' in editor.plugins )
|
|
{
|
|
root = editor.editable();
|
|
visibleRoot = root;
|
|
}
|
|
|
|
pasteRoot = editor.editable ? editor.editable() : root;
|
|
|
|
// Special case for IE in forcePasteAsPlainText:
|
|
// CKEditor uses the beforepaste event to move the target, but we can't use that to check for files,
|
|
// so in that case, set a listener on the document on each paste
|
|
if (CKEDITOR.env.ie && CKEDITOR.env.version>=11 && editor.config.forcePasteAsPlainText && editor.editable().isInline())
|
|
{
|
|
// Is an editable instance, so let's use attachListener here
|
|
pasteRoot.attachListener(pasteRoot, "beforepaste", function( bpEv ) {
|
|
// Only once, so we can check always which editor the paste belongs to
|
|
editor.document.on( "paste", function( pEv ) {
|
|
pEv.removeListener();
|
|
|
|
// redirect the original data to our paste listener
|
|
pasteListener(pEv);
|
|
}, null, {editor : editor });
|
|
});
|
|
}
|
|
else
|
|
{
|
|
// For everyone else, use the normal paste event
|
|
pasteRoot.on( "paste", pasteListener, null, {editor : editor }, 8);
|
|
}
|
|
|
|
root.on( 'dragenter', rootDragEnter);
|
|
root.on( 'dragleave', rootDragLeave);
|
|
|
|
// https://bugs.webkit.org/show_bug.cgi?id=57185
|
|
if ( !CKEDITOR.env.gecko )
|
|
{
|
|
root.on( 'dragover', rootDragOver);
|
|
}
|
|
|
|
// Must use CKEditor 3.6.3 for IE 10
|
|
root.on( 'drop', rootDropListener);
|
|
});
|
|
|
|
editor.on( 'contentDomUnload', domUnload);
|
|
|
|
editor.plugins.fileDropHandler = {
|
|
addTarget : function( target, callback )
|
|
{
|
|
target.on( 'dragenter', function(e) {
|
|
if (minX == -1)
|
|
{
|
|
if (!hasFiles(e))
|
|
return;
|
|
|
|
target.addClass( 'SimpleUploadsOverDialog' );
|
|
|
|
var rect = target.$.getBoundingClientRect();
|
|
minX=rect.left;
|
|
minY=rect.top;
|
|
maxX=minX + target.$.clientWidth;
|
|
maxY=minY + target.$.clientHeight;
|
|
}
|
|
});
|
|
|
|
target.on( 'dragleave', function(e) {
|
|
if ( minX == -1 )
|
|
return;
|
|
|
|
var ev = e.data.$;
|
|
|
|
if ((ev.clientX<=minX) || (ev.clientY<=minY) || (ev.clientX>=maxX) || (ev.clientY>=maxY))
|
|
{
|
|
target.removeClass( 'SimpleUploadsOverDialog' );
|
|
minX = -1;
|
|
}
|
|
});
|
|
|
|
target.on( 'dragover', function(e) {
|
|
if (minX != -1 )
|
|
{
|
|
// Show Copy instead of Move. Works for Chrome
|
|
// Firefox and IE10 don't respect this change (Firefox by default doesn't enter here)
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=484511
|
|
e.data.$.dataTransfer.dropEffect = 'copy';
|
|
|
|
e.data.preventDefault();
|
|
}
|
|
});
|
|
|
|
target.on( 'drop', function(e) {
|
|
target.removeClass( 'SimpleUploadsOverDialog' );
|
|
minX = -1;
|
|
|
|
//container
|
|
// We fire an event on CKEDITOR so all the instances get notified and remove their class
|
|
// This is an "internal" event to the plugin
|
|
CKEDITOR.fire( 'simpleuploads.droppedFile' );
|
|
mainMinX = -1;
|
|
|
|
var ev = e.data.$,
|
|
data = ev.dataTransfer;
|
|
if ( data && data.files && data.files.length>0 )
|
|
{
|
|
// Prevent default insertion
|
|
e.data.preventDefault();
|
|
|
|
// only one
|
|
for( var i=0; i<1; i++)
|
|
{
|
|
var file = data.files[ i ];
|
|
var evData = {
|
|
context : ev,
|
|
name : file.name,
|
|
file : file,
|
|
id : CKEDITOR.tools.getNextId(),
|
|
forceLink : false,
|
|
callback : callback,
|
|
mode : { type: "callback" }
|
|
};
|
|
|
|
CKEDITOR.plugins.simpleuploads.processFileWithCallback( editor, evData );
|
|
}
|
|
}
|
|
});
|
|
}
|
|
};
|
|
}, //Init
|
|
|
|
afterInit: function( editor ) {
|
|
var dataProcessor = editor.dataProcessor,
|
|
htmlFilter = dataProcessor && dataProcessor.htmlFilter;
|
|
|
|
if ( htmlFilter )
|
|
htmlFilter.addRules( htmlFilterRules , {applyToAll :true} );
|
|
}
|
|
|
|
} );
|
|
|
|
// API
|
|
CKEDITOR.plugins.simpleuploads = {
|
|
getTimeStampId : (function()
|
|
{
|
|
var counter = 0;
|
|
return function()
|
|
{
|
|
counter++;
|
|
return (new Date()).toISOString().replace(/\..*/, "").replace(/\D/g, "_") + counter;
|
|
};
|
|
})(),
|
|
|
|
isImageExtension: function(editor, filename)
|
|
{
|
|
if (!editor.config.simpleuploads_imageExtensions)
|
|
return false;
|
|
|
|
var imageRegexp = new RegExp( "\.(?:" + editor.config.simpleuploads_imageExtensions + ")$", "i");
|
|
return imageRegexp.test( filename );
|
|
},
|
|
|
|
// Main entry point for callbacks
|
|
insertProcessedFile: function(editor, evData) {
|
|
evData.element = null;
|
|
evData.id = this.getTimeStampId(); // new id
|
|
var that = this;
|
|
|
|
switch (evData.mode.type)
|
|
{
|
|
case 'selectedFile':
|
|
window.setTimeout( function() {
|
|
that.insertSelectedFile( editor, evData );
|
|
}, 50);
|
|
break;
|
|
|
|
case 'pastedFile':
|
|
this.insertPastedFile( editor, evData );
|
|
break;
|
|
|
|
case 'callback':
|
|
window.setTimeout( function() {
|
|
that.processFileWithCallback( editor, evData );
|
|
}, 50);
|
|
break;
|
|
|
|
case 'droppedFile':
|
|
this.insertDroppedFile( editor, evData );
|
|
break;
|
|
|
|
case 'base64paste':
|
|
this.insertBase64File( editor, evData );
|
|
break;
|
|
|
|
default:
|
|
alert("Error, no valid type", evData.mode);
|
|
break;
|
|
}
|
|
},
|
|
|
|
// Insert a file from the toolbar buttons
|
|
insertSelectedFile: function(editor, evData) {
|
|
var mode = evData.mode,
|
|
i = mode.i,
|
|
count = mode.count;
|
|
|
|
// Upload the file
|
|
if (!uploadFile( editor, evData ))
|
|
return;
|
|
|
|
var element = evData.element;
|
|
if (!element)
|
|
return;
|
|
|
|
if (count == 1)
|
|
{
|
|
var selection = editor.getSelection(),
|
|
selected = selection.getSelectedElement(),
|
|
originalNode;
|
|
|
|
// If it's just one image and the user has another one selected, replace it
|
|
if (selected && selected.getName() == "img" && element.getName() == "span")
|
|
{
|
|
originalNode = selected.$;
|
|
}
|
|
|
|
// Image2 widget
|
|
if (editor.widgets)
|
|
{
|
|
var focused = editor.widgets.focused;
|
|
if (focused && focused.wrapper.equals(selected))
|
|
{
|
|
originalNode = selected.$.querySelector("img");
|
|
}
|
|
}
|
|
|
|
// a link
|
|
if (element.getName() == "a")
|
|
{
|
|
var parent = selected,
|
|
ranges = selection.getRanges(),
|
|
range = ranges && ranges[0];
|
|
|
|
if (!parent)
|
|
{
|
|
if (ranges && ranges.length == 1)
|
|
{
|
|
parent = range.startContainer.$;
|
|
if (parent.nodeType == document.TEXT_NODE)
|
|
parent = parent.parentNode;
|
|
}
|
|
}
|
|
|
|
while ( parent && (parent.nodeType == document.ELEMENT_NODE) && (parent.nodeName.toLowerCase() != "a") )
|
|
parent = parent.parentNode;
|
|
|
|
if ( parent && parent.nodeName && parent.nodeName.toLowerCase() == "a" )
|
|
{
|
|
originalNode = parent;
|
|
}
|
|
// there was no link, check the best way to create one:
|
|
|
|
// create a link
|
|
if (!originalNode && range && (selected || !range.collapsed) )
|
|
{
|
|
var style = new CKEDITOR.style({ element: 'a', attributes: {href:'#'} } );
|
|
style.type = CKEDITOR.STYLE_INLINE; // need to override... dunno why.
|
|
style.applyToRange( range );
|
|
|
|
parent = range.startContainer.$;
|
|
if (parent.nodeType == document.TEXT_NODE)
|
|
parent = parent.parentNode;
|
|
|
|
originalNode = parent;
|
|
}
|
|
}
|
|
|
|
if (originalNode)
|
|
{
|
|
originalNode.parentNode.replaceChild(element.$, originalNode);
|
|
evData.originalNode = originalNode;
|
|
editor.fire( "saveSnapshot" );
|
|
return;
|
|
}
|
|
}
|
|
|
|
// insert a space between links
|
|
if (i>0 && element.getName()=="a")
|
|
editor.insertHtml(" ");
|
|
|
|
editor.insertElement(element);
|
|
setupCancelButton( editor, evData );
|
|
},
|
|
|
|
// Insert a file that has been pasted into the content (as File)
|
|
insertPastedFile: function(editor, evData) {
|
|
// Upload the file
|
|
if (!uploadFile( editor, evData ))
|
|
return;
|
|
|
|
var element = evData.element;
|
|
|
|
var dialog = evData.mode.dialog;
|
|
if (dialog)
|
|
{
|
|
editor.fire( "updateSnapshot" );
|
|
editor.insertElement(element);
|
|
editor.fire( "updateSnapshot" );
|
|
}
|
|
else
|
|
{
|
|
// Insert in the correct position after the pastebin has been removed
|
|
var processElement = function() {
|
|
// Check if there's a valid selection or if it's the pastebin
|
|
var ranges = editor.getSelection().getRanges();
|
|
|
|
if (!ranges.length)
|
|
{
|
|
// Put back in the queue
|
|
window.setTimeout(processElement, 0);
|
|
return;
|
|
}
|
|
// verify that it has really been removed
|
|
if (editor.editable && editor.editable().$.querySelector("#cke_pastebin"))
|
|
{
|
|
// Put back in the queue
|
|
window.setTimeout(processElement, 0);
|
|
return;
|
|
}
|
|
|
|
editor.fire( "updateSnapshot" );
|
|
editor.insertElement(element);
|
|
editor.fire( "updateSnapshot" );
|
|
setupCancelButton( editor, evData );
|
|
};
|
|
window.setTimeout(processElement, 0);
|
|
}
|
|
},
|
|
|
|
// The evData includes a callback that takes care of everything (a file dropped in a dialog)
|
|
processFileWithCallback: function(editor, evData) {
|
|
uploadFile( editor, evData );
|
|
},
|
|
|
|
insertDroppedFile: function(editor, evData) {
|
|
if (!uploadFile( editor, evData ))
|
|
return;
|
|
|
|
var element = evData.element;
|
|
var dropLocation = evData.mode.dropLocation,
|
|
range = dropLocation.range,
|
|
ev = dropLocation.ev,
|
|
count = dropLocation.count;
|
|
|
|
// if we're adding several links, add a space between them
|
|
if ( range && element.getName()=="a" )
|
|
{
|
|
if ( range.pasteHTML )
|
|
range.pasteHTML( " " ); // simple space doesn't work
|
|
else
|
|
range.insertNode( editor.document.$.createTextNode( ' ' ) );
|
|
}
|
|
|
|
var target = ev.target;
|
|
if (!range)
|
|
{
|
|
var doc = editor.document.$;
|
|
// Move to insertion point
|
|
/*
|
|
standard way: only implemented in Firefox 20
|
|
if (document.caretPositionFromPoint)
|
|
{
|
|
var caret = document.caretPositionFromPoint(ev.pageX, ev.pageY),
|
|
textNode = caret.offsetNode,
|
|
offset = caret.offset;
|
|
}
|
|
*/
|
|
|
|
// Firefox, custom properties in event.
|
|
if ( dropLocation.rangeParent )
|
|
{
|
|
// it seems that they aren't preserved in the ev after resending back the info
|
|
var node = dropLocation.rangeParent,
|
|
offset = dropLocation.rangeOffset;
|
|
range = doc.createRange();
|
|
range.setStart( node, offset );
|
|
range.collapse( true );
|
|
}
|
|
else
|
|
{
|
|
// Webkit, old documentView API
|
|
if ( document.caretRangeFromPoint )
|
|
{
|
|
range = doc.caretRangeFromPoint( ev.clientX, ev.clientY );
|
|
}
|
|
else
|
|
{
|
|
// IE
|
|
if (target.nodeName.toLowerCase()=="img")
|
|
{
|
|
range = doc.createRange();
|
|
range.selectNode(target);
|
|
} else if ( document.body.createTextRange )
|
|
{
|
|
var textRange = doc.body.createTextRange();
|
|
try
|
|
{
|
|
textRange.moveToPoint( ev.clientX, ev.clientY );
|
|
/*
|
|
// Convert to W3C range:
|
|
var node = textRange.parentElement();
|
|
var start = Math.abs( textRange.duplicate().moveStart('character', -1000000) );
|
|
var r = textRange.duplicate();
|
|
r.moveToElementText( node );
|
|
r.collapse();
|
|
var start2 = Math.abs( r.moveStart('character', -1000000) );
|
|
|
|
range = doc.createRange();
|
|
range.setStart( node.firstChild, start - start2 );
|
|
range.collapse( true );
|
|
*/
|
|
range = textRange;
|
|
}
|
|
catch (ex)
|
|
{
|
|
range = doc.createRange();
|
|
range.setStartAfter( doc.body.lastChild );
|
|
range.collapse( true );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
dropLocation.range = range;
|
|
}
|
|
|
|
var elementName = element.getName(),
|
|
handled = false;
|
|
|
|
if ( count==1 )
|
|
{
|
|
if (target.nodeName.toLowerCase() == "img" && elementName == "span" )
|
|
{
|
|
target.parentNode.replaceChild(element.$, target);
|
|
evData.originalNode = target;
|
|
handled = true;
|
|
}
|
|
|
|
if ( elementName == "a" )
|
|
{
|
|
var start;
|
|
if (range.startContainer)
|
|
{
|
|
start = range.startContainer;
|
|
if (start.nodeType == document.TEXT_NODE)
|
|
start = start.parentNode;
|
|
else
|
|
{
|
|
if (range.startOffset < start.childNodes.length)
|
|
start = start.childNodes[ range.startOffset ];
|
|
}
|
|
}
|
|
else
|
|
start = range.parentElement();
|
|
|
|
if (!start || target.nodeName.toLowerCase() == "img")
|
|
start = target;
|
|
|
|
var parent = start;
|
|
while ( parent && (parent.nodeType == document.ELEMENT_NODE) && (parent.nodeName.toLowerCase() != "a") )
|
|
parent = parent.parentNode;
|
|
|
|
if ( parent && parent.nodeName && parent.nodeName.toLowerCase() == "a" )
|
|
{
|
|
parent.parentNode.replaceChild(element.$, parent);
|
|
evData.originalNode = parent;
|
|
handled = true;
|
|
}
|
|
// dropping on an image without a parent link
|
|
if ( !handled && start.nodeName.toLowerCase() == "img" )
|
|
{
|
|
parent = start.ownerDocument.createElement('a');
|
|
parent.href = '#';
|
|
start.parentNode.replaceChild(parent, start);
|
|
parent.appendChild(start);
|
|
|
|
parent.parentNode.replaceChild(element.$, parent);
|
|
evData.originalNode = parent;
|
|
handled = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!handled)
|
|
{
|
|
if (range)
|
|
{
|
|
if ( range.pasteHTML )
|
|
range.pasteHTML( element.$.outerHTML );
|
|
else
|
|
range.insertNode( element.$ );
|
|
}
|
|
else
|
|
editor.insertElement( element );
|
|
}
|
|
|
|
setupCancelButton( editor, evData );
|
|
editor.fire( "saveSnapshot" );
|
|
},
|
|
|
|
insertBase64File: function(editor, evData) {
|
|
delete evData.result;
|
|
|
|
var id = evData.mode.id;
|
|
var tmp = editor.document.getById(id);
|
|
|
|
if (!uploadFile(editor, evData))
|
|
{
|
|
tmp.remove();
|
|
if (evData.result)
|
|
editor.insertHTML(evData.result);
|
|
|
|
return;
|
|
}
|
|
|
|
editor.getSelection().selectElement(tmp);
|
|
|
|
editor.insertElement(evData.element);
|
|
setupCancelButton( editor, evData );
|
|
}
|
|
};
|
|
|
|
// Creates the element, but doesn't insert it
|
|
function createPreview(editor, data)
|
|
{
|
|
var isImage = CKEDITOR.plugins.simpleuploads.isImageExtension( editor, data.name ),
|
|
showImageProgress = !editor.config.simpleuploads_hideImageProgress,
|
|
element;
|
|
|
|
// Create and insert our element
|
|
if ( !data.forceLink && isImage && showImageProgress)
|
|
{
|
|
element = createSVGAnimation(data.file, data.id, editor);
|
|
}
|
|
else
|
|
{
|
|
if ( isImage && !data.forceLink )
|
|
element = new CKEDITOR.dom.element( "span", editor.document );
|
|
else
|
|
element = new CKEDITOR.dom.element( "a", editor.document );
|
|
|
|
element.setAttribute( "id", data.id );
|
|
element.setAttribute( "class", "SimpleUploadsTmpWrapper");
|
|
//element.setText( data.name );
|
|
|
|
var html = "<span class='uploadName'>" + data.name + "</span>" +
|
|
" <span class='uploadRect'><span id='rect" + data.id + "'></span></span>" +
|
|
" <span id='text" + data.id + "' class='uploadText'> </span><span class='uploadCancel'>x</span>";
|
|
element.setHtml(html);
|
|
}
|
|
// Prevent selection handles in IE
|
|
element.setAttribute( 'contentEditable', false );
|
|
|
|
data.element=element;
|
|
}
|
|
|
|
function errorListener(e)
|
|
{
|
|
e.removeListener();
|
|
alert("Failed to load the image with the provided URL: '" + e.sender.data( 'cke-saved-src') + "'");
|
|
e.listenerData.remove();
|
|
}
|
|
|
|
function checkLoadedImage(img, editor, el, name)
|
|
{
|
|
if (img.$.naturalWidth === 0)
|
|
{
|
|
// when replacing an image, IE might fire the load event, but it still uses the old data
|
|
window.setTimeout( function() {checkLoadedImage(img, editor, el, name);}, 50);
|
|
return;
|
|
}
|
|
|
|
img.replace( el );
|
|
img.setAttribute("width", img.$.width);
|
|
img.setAttribute("height", img.$.height);
|
|
|
|
editor.fire('simpleuploads.finishedUpload', { name: name, element: img } );
|
|
|
|
// Correct the Undo image
|
|
editor.fire( "updateSnapshot" );
|
|
}
|
|
|
|
// Sets up a XHR object to handle the upload
|
|
function createXHRupload(editor, data)
|
|
{
|
|
var isImage = CKEDITOR.plugins.simpleuploads.isImageExtension( editor, data.name ),
|
|
attribute = "href",
|
|
forImage = false;
|
|
|
|
if ( !data.forceLink && isImage )
|
|
{
|
|
attribute = "src";
|
|
forImage=true;
|
|
}
|
|
|
|
if (data.callback)
|
|
data.callback.setup(data);
|
|
|
|
if (!data.url)
|
|
data.url = getUploadUrl(editor, 2, forImage);
|
|
|
|
if (data.requiresImage && !isImage)
|
|
{
|
|
alert(editor.lang.simpleuploads.nonImageExtension);
|
|
return null;
|
|
}
|
|
|
|
var result = editor.fire("simpleuploads.startUpload", data);
|
|
// in v3 cancel() returns true and in v4 returns false
|
|
// if not canceled it's the data object, so let's use that.
|
|
if ( typeof result == "boolean" )
|
|
return null;
|
|
|
|
// instead of uploading, use base64 encoded data
|
|
if (data.url == "base64")
|
|
{
|
|
if (typeof data.file == "string")
|
|
{
|
|
|
|
setTimeout( function() {
|
|
var fileUrl = data.file,
|
|
id = data.id,
|
|
el = editor.document.getById( id );
|
|
|
|
receivedUrl(fileUrl, data, editor, el, attribute);
|
|
}, 100);
|
|
return {};
|
|
}
|
|
else
|
|
{
|
|
var reader = new FileReader();
|
|
reader.onload = function() {
|
|
|
|
setTimeout( function() {
|
|
var fileUrl = reader.result,
|
|
id = data.id,
|
|
el = editor.document.getById( id );
|
|
|
|
receivedUrl(fileUrl, data, editor, el, attribute);
|
|
}, 100);
|
|
};
|
|
|
|
reader.readAsDataURL( data.file );
|
|
}
|
|
return {};
|
|
}
|
|
|
|
var xhr = new XMLHttpRequest(),
|
|
target = xhr.upload;
|
|
|
|
// nice progress effect. Opera used to lack xhr.upload
|
|
if ( target )
|
|
{
|
|
target.onprogress = function( evt )
|
|
{
|
|
updateProgress(editor, data.id, evt);
|
|
};
|
|
}
|
|
|
|
data.xhr = xhr;
|
|
|
|
// Upload the file
|
|
xhr.open("POST", data.url );
|
|
xhr.onload = function() {
|
|
var id = data.id,
|
|
el = editor.document.getById( id ),
|
|
fileUrl, msg;
|
|
|
|
// final update
|
|
updateProgress(editor, id, null);
|
|
// Correct the Undo image
|
|
editor.fire( "updateSnapshot" );
|
|
|
|
var evtData = { xhr: xhr, data: data, element:el };
|
|
var result = editor.fire("simpleuploads.serverResponse", evtData);
|
|
|
|
// in v3 cancel() returns true and in v4 returns false
|
|
// if not canceled it's the evdata object
|
|
if ( typeof result == "boolean" )
|
|
return; // if the listener has Cancelled the event, exit and we suppose that it took care of everything by itself.
|
|
|
|
// Check if the event has been listened and performed its own parsing
|
|
if (typeof evtData.url == "undefined")
|
|
{
|
|
// Upon finish, get the url and update the file
|
|
//var parts = xhr.responseText.match(/2,\s*("|')(.*?[^\\]?)\1(?:,\s*\1(.*?[^\\]?)\1)?\s*\)/),
|
|
//var parts = xhr.responseText.match(/\((?:"|')?\d+(?:"|')?,\s*("|')(.*?[^\\]?)\1(?:,\s*(.*?))?\s*\)\s*;?\s*<\/script>/),
|
|
var parts = xhr.responseText.match(/\((?:"|')?\d+(?:"|')?,\s*("|')(.*?[^\\]?)\1(?:,\s*(.*?))?\s*\)\s*;?/);
|
|
|
|
fileUrl = parts && parts[2];
|
|
msg = parts && parts[3];
|
|
|
|
// The server response usually is automatically parsed by the js engine, but in this case we get the "raw content"
|
|
// and must take care of un-escaping it.
|
|
// So far I haven't been able to find a single function that does it correctly in all the cases
|
|
if (fileUrl)
|
|
{
|
|
fileUrl = fileUrl.replace(/\\'/g, "'");
|
|
|
|
// Try to handle URLs with escaped chars like 51-Body/\u00E6\u00F8\u00E5.jpg
|
|
try
|
|
{
|
|
var o = JSON.parse('{"url":"' + fileUrl + '"}');
|
|
if (o && o.url)
|
|
fileUrl = o.url;
|
|
}
|
|
catch (ex) { }
|
|
}
|
|
|
|
if (msg)
|
|
{
|
|
// find out if it was a function or a string message:
|
|
var matchFunction = msg.match(/function\(\)\s*\{(.*)\}/);
|
|
if (matchFunction)
|
|
msg = new Function( matchFunction[1] );
|
|
else
|
|
{
|
|
var first=msg.substring(0,1);
|
|
if (first=="'" || first=='"')
|
|
msg = msg.substring( 1, msg.length-1 );
|
|
}
|
|
}
|
|
|
|
if (!parts)
|
|
{
|
|
msg = 'Error posting the file to ' + data.url + '\r\nInvalid data returned (check console)';
|
|
if (window.console)
|
|
console.log(xhr.responseText);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fileUrl = evtData.url;
|
|
msg = "";
|
|
}
|
|
|
|
editor.fire('simpleuploads.endUpload', { name: data.name, ok: (!!fileUrl), xhr : xhr, data : data } );
|
|
if (xhr.status!=200)
|
|
{
|
|
if (xhr.status == 413)
|
|
alert( editor.lang.simpleuploads.fileTooBig );
|
|
else
|
|
alert('Error posting the file to ' + data.url + '\r\nResponse status: ' + xhr.status);
|
|
|
|
if (window.console)
|
|
console.log(xhr);
|
|
}
|
|
|
|
if (data.callback)
|
|
{
|
|
if (!fileUrl && msg)
|
|
alert( msg );
|
|
|
|
data.callback.upload(fileUrl, msg, data);
|
|
return;
|
|
}
|
|
|
|
// If the element doesn't exists it means that the user has deleted it or pressed undo while uploading
|
|
// so let's get out
|
|
if (!el)
|
|
return;
|
|
|
|
if ( fileUrl )
|
|
{
|
|
receivedUrl(fileUrl, data, editor, el, attribute);
|
|
}
|
|
else
|
|
{
|
|
if (data.originalNode)
|
|
el.$.parentNode.replaceChild(data.originalNode, el.$);
|
|
else
|
|
el.remove();
|
|
|
|
if (msg)
|
|
alert( msg );
|
|
}
|
|
// Correct undo image
|
|
editor.fire( "updateSnapshot" );
|
|
};
|
|
|
|
xhr.onerror = function(e) {
|
|
alert('Error posting the file to ' + data.url );
|
|
if (window.console)
|
|
console.log(e);
|
|
|
|
var el = editor.document.getById( data.id );
|
|
if (el)
|
|
{
|
|
if (data.originalNode)
|
|
el.$.parentNode.replaceChild(data.originalNode, el.$);
|
|
else
|
|
el.remove();
|
|
}
|
|
// Correct undo image
|
|
editor.fire( "updateSnapshot" );
|
|
};
|
|
xhr.onabort = function(e) {
|
|
if (data.callback)
|
|
{
|
|
data.callback.upload(null);
|
|
return;
|
|
}
|
|
|
|
var el = editor.document.getById( data.id );
|
|
if (el)
|
|
{
|
|
if (data.originalNode)
|
|
el.$.parentNode.replaceChild(data.originalNode, el.$);
|
|
else
|
|
el.remove();
|
|
}
|
|
// Correct undo image
|
|
editor.fire( "updateSnapshot" );
|
|
};
|
|
|
|
// CORS https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS
|
|
xhr.withCredentials = true;
|
|
|
|
return xhr;
|
|
}
|
|
|
|
// Takes care of uploading the file using XHR
|
|
function uploadFile(editor, data)
|
|
{
|
|
if (!data.callback)
|
|
createPreview(editor, data);
|
|
|
|
var xhr = createXHRupload(editor, data);
|
|
if (!xhr)
|
|
{
|
|
data.result = data.result || "";
|
|
return false;
|
|
}
|
|
// FileReader
|
|
if (!xhr.send)
|
|
return true;
|
|
|
|
if (data.callback && data.callback.start)
|
|
data.callback.start(data);
|
|
|
|
var inputName = data.inputName|| getUploadInputName(editor);
|
|
|
|
if (typeof data.file == "string")
|
|
sendBase64File( data, xhr, inputName);
|
|
else
|
|
sendBlobFile( data, xhr, inputName);
|
|
|
|
return true;
|
|
}
|
|
|
|
function sendBlobFile(data, xhr, inputName)
|
|
{
|
|
var formdata = new FormData();
|
|
formdata.append( inputName, data.file, data.name );
|
|
// Add extra fields if provided
|
|
if (data.extraFields)
|
|
{
|
|
var obj = data.extraFields;
|
|
for (var prop in obj)
|
|
{
|
|
if( obj.hasOwnProperty( prop ) )
|
|
formdata.append( prop, obj[prop] );
|
|
}
|
|
}
|
|
if (data.extraHeaders) {
|
|
var headers = data.extraHeaders;
|
|
for (var header in headers){
|
|
if( headers.hasOwnProperty( header )){
|
|
xhr.setRequestHeader(header, headers[header]);
|
|
}
|
|
}
|
|
}
|
|
xhr.send( formdata );
|
|
}
|
|
|
|
function sendBase64File(data, xhr, inputName)
|
|
{
|
|
// Create the multipart data upload.
|
|
var BOUNDARY = "---------------------------1966284435497298061834782736",
|
|
rn = "\r\n",
|
|
req = "--" + BOUNDARY,
|
|
type = data.name.match(/\.(\w+)$/)[1];
|
|
|
|
req += rn + 'Content-Disposition: form-data; name="' + inputName + '"; filename="' + data.name + '"';
|
|
req += rn + "Content-type: image/" + type;
|
|
req += rn + rn + window.atob( data.file.split(',')[1] );
|
|
req += rn + "--" + BOUNDARY;
|
|
|
|
// Add extra fields if provided
|
|
if (data.extraFields)
|
|
{
|
|
var obj = data.extraFields;
|
|
for (var prop in obj)
|
|
{
|
|
req += rn + "Content-Disposition: form-data; name=\"" + unescape(encodeURIComponent( prop )).replace(/=/g, "\\=") + "\"";
|
|
req += rn + rn + unescape(encodeURIComponent( obj[prop] )) ;
|
|
req += rn + "--" + BOUNDARY;
|
|
}
|
|
}
|
|
|
|
req += "--";
|
|
|
|
xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
|
|
/*
|
|
if (xhr.sendAsBinary)
|
|
xhr.sendAsBinary(req);
|
|
else
|
|
{
|
|
// emulate sendAsBinary for IE11 & Chrome
|
|
*/
|
|
var bufferData = new ArrayBuffer(req.length);
|
|
var ui8a = new Uint8Array(bufferData, 0);
|
|
for (var i = 0; i < req.length; i++)
|
|
ui8a[i] = (req.charCodeAt(i) & 0xff);
|
|
xhr.send(ui8a);
|
|
/*
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
function updateProgress(editor, id, evt)
|
|
{
|
|
if (!editor.document || !editor.document.$)
|
|
return;
|
|
|
|
var dialog = CKEDITOR.dialog.getCurrent();
|
|
|
|
var doc = (dialog ? CKEDITOR : editor ).document.$,
|
|
rect = doc.getElementById("rect" + id),
|
|
text = doc.getElementById("text" + id),
|
|
value, textValue;
|
|
|
|
if ( evt )
|
|
{
|
|
if ( !evt.lengthComputable )
|
|
return;
|
|
|
|
value = (100*evt.loaded/evt.total).toFixed(2) + "%";
|
|
textValue = (100*evt.loaded/evt.total).toFixed() + "%";
|
|
}
|
|
else
|
|
{
|
|
textValue = editor.lang.simpleuploads.processing;
|
|
value = "100%";
|
|
/*
|
|
if (text)
|
|
{
|
|
text.parentNode.removeChild(text);
|
|
text = null;
|
|
}
|
|
*/
|
|
}
|
|
if (rect)
|
|
{
|
|
rect.setAttribute("width", value);
|
|
rect.style.width = value;
|
|
if (!evt)
|
|
{
|
|
var parent = rect.parentNode;
|
|
if (parent && parent.className=="uploadRect")
|
|
parent.parentNode.removeChild(parent);
|
|
}
|
|
}
|
|
if (text)
|
|
{
|
|
text.firstChild.nodeValue = textValue;
|
|
if (!evt)
|
|
{
|
|
// Remove cancel button
|
|
var sibling = text.nextSibling;
|
|
if (sibling && sibling.nodeName.toLowerCase()=="a")
|
|
sibling.parentNode.removeChild(sibling);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Show a grayscale version of the image that animates toward the full color version
|
|
function createSVGAnimation( file, id, editor )
|
|
{
|
|
var element = new CKEDITOR.dom.element( "span", editor.document ),
|
|
div = element.$,
|
|
useURL,
|
|
doc = editor.document.$,
|
|
span = doc.createElement("span");
|
|
|
|
element.setAttribute( "id", id );
|
|
element.setAttribute( "class", "SimpleUploadsTmpWrapper");
|
|
var rectSpan = doc.createElement("span");
|
|
rectSpan.setAttribute( "id" , "text" + id);
|
|
rectSpan.appendChild( doc.createTextNode("0 %"));
|
|
div.appendChild(span);
|
|
span.appendChild(rectSpan);
|
|
|
|
var cancelSpan = doc.createElement("span");
|
|
cancelSpan.appendChild( doc.createTextNode('x'));
|
|
span.appendChild(cancelSpan);
|
|
|
|
if (typeof file != "string")
|
|
{
|
|
if ( !nativeURL || !nativeURL.revokeObjectURL)
|
|
return element;
|
|
|
|
useURL = true;
|
|
}
|
|
|
|
var svg = doc.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
svg.setAttribute( "id" , "svg" + id);
|
|
|
|
// just to find out the image dimensions as they are needed for the svg block
|
|
var img = doc.createElement( "img" );
|
|
if (useURL)
|
|
{
|
|
img.onload = function(e) {
|
|
if (this.onload)
|
|
{
|
|
nativeURL.revokeObjectURL( this.src );
|
|
this.onload = null;
|
|
}
|
|
|
|
// in IE it's inserted with the HTML, so we can't reuse the svg object
|
|
var svg = doc.getElementById("svg" + id);
|
|
if (svg)
|
|
{
|
|
svg.setAttribute("width", this.width + "px");
|
|
svg.setAttribute("height", this.height + "px");
|
|
}
|
|
// Chrome
|
|
var preview = doc.getElementById(id);
|
|
if (preview)
|
|
preview.style.width = this.width + "px";
|
|
};
|
|
img.src = nativeURL.createObjectURL( file );
|
|
}
|
|
else
|
|
{
|
|
// base64 data, dimensions are available right now in Firefox
|
|
img.src = file;
|
|
// extra protection
|
|
img.onload = function(e) {
|
|
this.onload = null;
|
|
|
|
// we're pasting so it's inserted with the HTML, so we can't reuse the svg object
|
|
var svg = doc.getElementById("svg" + id);
|
|
if (svg)
|
|
{
|
|
svg.setAttribute("width", this.width + "px");
|
|
svg.setAttribute("height", this.height + "px");
|
|
}
|
|
};
|
|
svg.setAttribute("width", img.width + "px");
|
|
svg.setAttribute("height", img.height + "px");
|
|
}
|
|
|
|
div.appendChild(svg);
|
|
|
|
var filter = doc.createElementNS("http://www.w3.org/2000/svg", "filter");
|
|
filter.setAttribute("id", "SVGdesaturate");
|
|
svg.appendChild(filter);
|
|
|
|
var feColorMatrix = doc.createElementNS("http://www.w3.org/2000/svg", "feColorMatrix");
|
|
feColorMatrix.setAttribute("type", "saturate");
|
|
feColorMatrix.setAttribute("values", "0");
|
|
filter.appendChild(feColorMatrix);
|
|
|
|
var clipPath = doc.createElementNS("http://www.w3.org/2000/svg", "clipPath");
|
|
clipPath.setAttribute("id", "SVGprogress" + id);
|
|
svg.appendChild(clipPath);
|
|
|
|
var rect = doc.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
rect.setAttribute("id", "rect" + id);
|
|
rect.setAttribute("width", "0");
|
|
rect.setAttribute("height", "100%");
|
|
clipPath.appendChild(rect);
|
|
|
|
var image = doc.createElementNS("http://www.w3.org/2000/svg", "image");
|
|
image.setAttribute("width", "100%");
|
|
image.setAttribute("height", "100%");
|
|
|
|
if (useURL)
|
|
{
|
|
image.setAttributeNS('http://www.w3.org/1999/xlink',"href", nativeURL.createObjectURL( file ));
|
|
var loaded = function( e ) {
|
|
nativeURL.revokeObjectURL( image.getAttributeNS('http://www.w3.org/1999/xlink',"href") );
|
|
image.removeEventListener( "load", loaded, false);
|
|
};
|
|
image.addEventListener( "load", loaded, false);
|
|
}
|
|
else
|
|
image.setAttributeNS('http://www.w3.org/1999/xlink',"href", file );
|
|
|
|
var image2 = image.cloneNode(true);
|
|
image.setAttribute("filter", "url(#SVGdesaturate)");
|
|
image.style.opacity="0.5";
|
|
|
|
svg.appendChild(image);
|
|
|
|
image2.setAttribute("clip-path", "url(#SVGprogress" + id + ")");
|
|
svg.appendChild(image2);
|
|
|
|
return element;
|
|
}
|
|
|
|
// Compatibility between CKEditor 3 and 4
|
|
if (CKEDITOR.skins)
|
|
{
|
|
CKEDITOR.plugins.setLang = CKEDITOR.tools.override( CKEDITOR.plugins.setLang , function( originalFunction )
|
|
{
|
|
return function( plugin, lang, obj )
|
|
{
|
|
if (plugin != "devtools" && typeof obj[plugin] != "object")
|
|
{
|
|
var newObj = {};
|
|
newObj[ plugin ] = obj;
|
|
obj = newObj;
|
|
}
|
|
originalFunction.call(this, plugin, lang, obj);
|
|
};
|
|
});
|
|
}
|
|
|
|
function createSimpleUpload( editor, dialogName, definition, element )
|
|
{
|
|
if (element.type=="file")
|
|
return;
|
|
|
|
var forImage = (dialogName.substr(0,5)=="image" || element.requiresImage);
|
|
|
|
var targetField = element.filebrowser.target.split(":");
|
|
var callback = {
|
|
setup : function(data) {
|
|
if (!definition.uploadUrl)
|
|
return;
|
|
|
|
if (forImage)
|
|
data.requiresImage = true;
|
|
|
|
var params = {};
|
|
params.CKEditor = editor.name;
|
|
params.CKEditorFuncNum = 2;
|
|
params.langCode = editor.langCode;
|
|
|
|
data.url = addQueryString( definition.uploadUrl, params );
|
|
},
|
|
start : function(data) {
|
|
var dialog = CKEDITOR.dialog.getCurrent();
|
|
dialog.showThrobber();
|
|
var throbber = dialog.throbber;
|
|
|
|
if (data.xhr)
|
|
{
|
|
var html = "<span class='uploadName'>" + data.name + "</span>" +
|
|
" <span class='uploadRect'><span id='rect" + data.id + "'></span></span>" +
|
|
" <span id='text" + data.id + "' class='uploadText'> </span><a>x</a>";
|
|
|
|
throbber.throbberTitle.setHtml(html);
|
|
|
|
var cover = throbber.throbberCover;
|
|
var xhr = data.xhr;
|
|
if ( cover.timer )
|
|
{
|
|
clearInterval( cover.timer ) ;
|
|
cover.timer = null ;
|
|
}
|
|
throbber.throbberParent.setStyle("display", "none");
|
|
throbber.throbberTitle.getLast().on('click', function() {
|
|
xhr.abort();
|
|
});
|
|
|
|
// protection to check that the upload isn't pending when forcing to close the dialog
|
|
dialog.on('hide', function() {
|
|
if (xhr.readyState == 1)
|
|
xhr.abort();
|
|
});
|
|
}
|
|
|
|
throbber.center();
|
|
},
|
|
upload : function(url, msg, data) {
|
|
var dialog = CKEDITOR.dialog.getCurrent();
|
|
dialog.throbber.hide();
|
|
|
|
if ( typeof msg == 'function' && msg.call( data.context.sender ) === false )
|
|
return;
|
|
|
|
if (definition.onFileSelect) {
|
|
if ( definition.onFileSelect.call( data.context.sender, url, msg ) === false )
|
|
return;
|
|
}
|
|
|
|
if (!url)
|
|
return;
|
|
|
|
dialog.getContentElement( targetField[ 0 ], targetField[ 1 ] ).setValue( url );
|
|
dialog.selectPage( targetField[ 0 ] );
|
|
}
|
|
};
|
|
|
|
if (element.filebrowser.action == "QuickUpload") {
|
|
definition.hasQuickUpload = true;
|
|
definition.onFileSelect = null;
|
|
if (!editor.config.simpleuploads_respectDialogUploads)
|
|
{
|
|
element.label = ( forImage ? editor.lang.simpleuploads.addImage : editor.lang.simpleuploads.addFile);
|
|
|
|
element.onClick = function( evt )
|
|
{
|
|
// "element" here means the definition object, so we need to find the correct
|
|
// button to scope the event call
|
|
//var sender = evt.sender;
|
|
PickAndSendFile(editor, forImage, evt, callback);
|
|
return false;
|
|
};
|
|
|
|
var picker = definition.getContents( element[ "for" ][ 0 ] ).get( element[ "for" ][ 1 ] );
|
|
picker.hidden = true;
|
|
}
|
|
} else {
|
|
// if the dialog has already been configured with quickUpload there's no need to use the file browser config
|
|
if (definition.hasQuickUpload)
|
|
return;
|
|
|
|
if (element.filebrowser.onSelect)
|
|
definition.onFileSelect = element.filebrowser.onSelect;
|
|
}
|
|
|
|
if (!editor.plugins.fileDropHandler)
|
|
return;
|
|
|
|
if (element.filebrowser.action == "QuickUpload")
|
|
definition.uploadUrl = element.filebrowser.url;
|
|
|
|
var original = definition.onShow || (function(){});
|
|
definition.onShow = CKEDITOR.tools.override( original, function( original )
|
|
{
|
|
return function()
|
|
{
|
|
if ( typeof original == 'function' )
|
|
original.call( this );
|
|
|
|
if (element.filebrowser.action != "QuickUpload" && definition.hasQuickUpload)
|
|
return;
|
|
|
|
var dialog = this;
|
|
if (dialog.handleFileDrop)
|
|
return;
|
|
dialog.handleFileDrop = true;
|
|
dialog.getParentEditor().plugins.fileDropHandler.addTarget( dialog.parts.contents, callback );
|
|
};
|
|
} );
|
|
}
|
|
|
|
// Searches for elements in the dialog definition where we can apply our enhancements
|
|
function applySimpleUpload( editor, dialogName, definition, elements )
|
|
{
|
|
for ( var i in elements )
|
|
{
|
|
var element = elements[ i ];
|
|
// If due to some customization or external library the object isn't valid, skip it.
|
|
if (!element)
|
|
continue;
|
|
|
|
if ( element.type == 'hbox' || element.type == 'vbox' || element.type == 'fieldset' )
|
|
applySimpleUpload( editor, dialogName, definition, element.children );
|
|
|
|
if ( element.filebrowser && element.filebrowser.url )
|
|
createSimpleUpload( editor, dialogName, definition, element );
|
|
}
|
|
}
|
|
|
|
function setupCancelButton( editor, data ) {
|
|
var element = editor.document.getById( data.id );
|
|
if (!element)
|
|
return;
|
|
var links = element.$.getElementsByTagName("a");
|
|
if (!links || !links.length)
|
|
{
|
|
links = element.$.getElementsByTagName("span");
|
|
if (!links || !links.length)
|
|
return;
|
|
}
|
|
for(var i=0; i<links.length; i++) {
|
|
var link = links[ i ];
|
|
if (link.innerHTML == "x")
|
|
{
|
|
link.className = "uploadCancel";
|
|
link.onclick = function() {
|
|
if (data.xhr)
|
|
data.xhr.abort();
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
function pasteListener(e) {
|
|
var editor = e.listenerData.editor,
|
|
dialog = e.listenerData.dialog,
|
|
i,
|
|
item;
|
|
|
|
// We want IE11 here to embed images as base64 (at least for the moment)
|
|
// later use them as blob if we aren't in a dialog
|
|
|
|
// In IE11 we use the images at this point only if forcePasteAsPlainText has been set
|
|
// It doesn't work due to https://connect.microsoft.com/IE/feedback/details/813618/calling-xhr-open-in-a-paste-event-throws-an-access-denied-error
|
|
var data = (e.data && e.data.$.clipboardData) || (editor.config.forcePasteAsPlainText && window.clipboardData);
|
|
if (!data)
|
|
return;
|
|
|
|
|
|
// If forcePasteAsPlainText is set, try to detect if we're with Firefox and the clipboard content is only an image
|
|
if (CKEDITOR.env.gecko && editor.config.forcePasteAsPlainText)
|
|
{
|
|
if (data.types.length===0)
|
|
{
|
|
// only once:
|
|
editor.on( 'beforePaste', function( evt ) {
|
|
evt.removeListener();
|
|
|
|
// Force html mode :-)
|
|
evt.data.type = 'html';
|
|
} );
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Chrome has clipboardData.items. Other browsers don't provide this info at the moment.
|
|
// Firefox implements clipboardData.files in 22
|
|
var items = data.items || data.files;
|
|
if (!items || !items.length)
|
|
return;
|
|
|
|
// Check first if there is a text/html or text/plain version, and leave the browser use that:
|
|
// otherwise, pasting from MS Word to Chrome in Mac will always generate a black rectangle.
|
|
if (items[0].kind)
|
|
{
|
|
for (i=0; i< items.length; i++)
|
|
{
|
|
item = items[i];
|
|
if ( item.kind=="string" && (item.type=="text/html" || item.type=="text/plain") )
|
|
return;
|
|
}
|
|
}
|
|
|
|
// We're safe, stupid Office-Mac combination won't disturb us.
|
|
for (i=0; i< items.length; i++)
|
|
{
|
|
item = items[i];
|
|
if ( item.kind && item.kind != "file" )
|
|
continue;
|
|
|
|
e.data.preventDefault();
|
|
|
|
var file = (item.getAsFile ? item.getAsFile() : item);
|
|
|
|
if (CKEDITOR.env.ie || CKEDITOR.env.gecko || editor.config.forcePasteAsPlainText)
|
|
{
|
|
setTimeout( function() {
|
|
processPastedFile(file, e);
|
|
}, 100);
|
|
}
|
|
else
|
|
processPastedFile(file, e);
|
|
}
|
|
|
|
// autoclose the dialog
|
|
if (dialog && e.data.$.defaultPrevented)
|
|
dialog.hide();
|
|
}
|
|
|
|
function processPastedFile(file, e)
|
|
{
|
|
var editor = e.listenerData.editor,
|
|
dialog = e.listenerData.dialog;
|
|
|
|
var id = CKEDITOR.plugins.simpleuploads.getTimeStampId(),
|
|
fileName = file.name || (id + ".png"),
|
|
evData = {
|
|
context : e.data.$,
|
|
name : fileName,
|
|
file : file,
|
|
forceLink : false,
|
|
id : id,
|
|
mode : {
|
|
type : 'pastedFile',
|
|
dialog : dialog
|
|
}
|
|
};
|
|
|
|
CKEDITOR.plugins.simpleuploads.insertPastedFile(editor, evData);
|
|
}
|
|
|
|
function setupPasteListener(iframe)
|
|
{
|
|
var doc = iframe.getFrameDocument(),
|
|
body = doc.getBody();
|
|
if (!body || !body.$ || (body.$.contentEditable != "true" && doc.$.designMode != "on"))
|
|
{
|
|
setTimeout(function() { setupPasteListener(iframe);}, 100);
|
|
return;
|
|
}
|
|
var dialog = CKEDITOR.dialog.getCurrent();
|
|
|
|
doc.on("paste", pasteListener, null, {
|
|
dialog : dialog,
|
|
editor : dialog.getParentEditor()
|
|
});
|
|
}
|
|
|
|
CKEDITOR.on( "dialogDefinition", function( evt )
|
|
{
|
|
if (!evt.editor.plugins.simpleuploads)
|
|
return;
|
|
|
|
var definition = evt.data.definition;
|
|
|
|
// Associate filebrowser to elements with 'filebrowser' attribute.
|
|
for ( var i in definition.contents )
|
|
{
|
|
var contents = definition.contents[ i ];
|
|
if ( contents )
|
|
applySimpleUpload(evt.editor, evt.data.name, definition, contents.elements);
|
|
}
|
|
|
|
// Detect the Paste dialog
|
|
if (evt.data.name == "paste")
|
|
{
|
|
definition.onShow = CKEDITOR.tools.override( definition.onShow, function( original )
|
|
{
|
|
return function()
|
|
{
|
|
if ( typeof original == "function" )
|
|
original.call( this );
|
|
|
|
setupPasteListener( this.getContentElement( "general", "editing_area" ).getInputElement() );
|
|
};
|
|
} );
|
|
|
|
}
|
|
}, null, null, 30 );
|
|
|
|
})();
|
|
|
|
|
|
/**
|
|
* Fired when file starts being uploaded by the "simpleuploads" plugin
|
|
*
|
|
* @since 3.1
|
|
* @name CKEDITOR.editor#simpleuploads.startUpload
|
|
* @event
|
|
* @param {String} [name] The file name.
|
|
* @param {String} [url] The url that will be used for the upload. It can be modified to your needs on each upload.
|
|
* @param {String|Object} [context] Context that caused the upload (a string if it's a pasted image, a DOM event for drag&drop and copied files, the toolbar button for those cases)
|
|
* @param {Object} [file] The file itself (if available).
|
|
* @param {Object} [extraFields] Since 3.4.1 the event listener can add this property to indicate extra data to send in the upload as POST data
|
|
*/
|
|
|
|
/**
|
|
* Fired when the server sends the response of an upload.
|
|
*
|
|
* @since 4.3.6
|
|
* @name CKEDITOR.editor#simpleuploads.serverResponse
|
|
* @event
|
|
* @param {Object} [xhr] The XHR with the request.
|
|
* @param {Object} [data] The original data object of this upload.
|
|
* Upon processing this event, a listener can set a "url" property on the event.data object and that will tell to the SimpleUploads plugin
|
|
* that your code has processed the response.
|
|
* If url is an empty string it means that the upload has failed and that the upload placeholder must be removed silently
|
|
* Otherwise it will be treated as the response from the server
|
|
* This way you can use different responses from your server that doesn't follow the QuickUpload pattern, as well as hook any additional processing that
|
|
* you might need.
|
|
* Please, note that this is fired only for uploads using XHR, old IEs are excluded and they need the default response from the server.
|
|
*/
|
|
|
|
/**
|
|
* Fired when file upload ends on the "simpleuploads" plugin
|
|
*
|
|
* @since 3.1
|
|
* @name CKEDITOR.editor#simpleuploads.endUpload
|
|
* @event
|
|
* @param {String} [name] The file name.
|
|
* @param {Boolean} [ok] Whether the file has been correctly uploaded or not
|
|
* @param {Object} [xhr] The XHR with the request. Since 4.3
|
|
* @param {Object} [data] The original data object of this upload. Since 4.3
|
|
*/
|
|
|
|
/**
|
|
* Fired when the final element has been inserted by the "simpleuploads" plugin (after it has been uploaded)
|
|
*
|
|
* @since 3.3.4
|
|
* @name CKEDITOR.editor#simpleuploads.finishedUpload
|
|
* @event
|
|
* @param {String} [name] The file name.
|
|
* @param {CKEDITOR.dom.element} [element] The element node that has been inserted
|
|
*/
|
|
|
|
|
|
/**
|
|
* Fired when an image has been selected, before it's uploaded. It provides a reference to an img element
|
|
* that contains the selected file. Extends the data provided in the simpleuploads.startUpload event
|
|
* @since 4.2
|
|
* @name CKEDITOR.editor#simpleuploads.localImageReady
|
|
* @event
|
|
* @param {Image} [image] The element node that has been inserted
|
|
*/
|
|
|
|
/**
|
|
* Class to apply to the editor container (ie: the border outside the editor) when a file is dragged on the page
|
|
*
|
|
* CKEDITOR.config.simpleuploads_containerover='border:1px solid red !important;';
|
|
*
|
|
* @since 2.7
|
|
* @cfg {String} [simpleuploads_containerover='box-shadow: 0 0 10px 1px #99DD99 !important;']
|
|
* @member CKEDITOR.config
|
|
*/
|
|
|
|
/**
|
|
* Class to apply to the editor when a file is dragged over it
|
|
*
|
|
* CKEDITOR.config.simpleuploads_editorover='background-color:yellow !important;';
|
|
*
|
|
* @since 2.7
|
|
* @cfg {String} [simpleuploads_editorover='box-shadow: 0 0 10px 1px #999999 inset !important;']
|
|
* @member CKEDITOR.config
|
|
*/
|
|
|
|
/**
|
|
* Class to apply to the dialog border/cover when a file is dragged on the page
|
|
*
|
|
* CKEDITOR.config.simpleuploads_coverover='border:1px solid red !important;';
|
|
*
|
|
* @since 4.0
|
|
* @cfg {String} [simpleuploads_coverover='box-shadow: 0 0 10px 4px #999999 inset !important;']
|
|
* @member CKEDITOR.config
|
|
*/
|
|
|
|
/**
|
|
* Class to apply to the dialog content when a file is dragged over it
|
|
*
|
|
* CKEDITOR.config.simpleuploads_dialogover='border:1px solid red !important;';
|
|
*
|
|
* @since 4.0
|
|
* @cfg {String} [simpleuploads_dialogover='box-shadow: 0 0 10px 4px #999999 inset !important;']
|
|
* @member CKEDITOR.config
|
|
*/
|
|
|
|
|
|
/**
|
|
* List of extensions that should be recognized as belonging to image files (ie: a dropped file will be inserted as img instead of link)
|
|
*
|
|
* config.simpleuploads_imageExtensions='jpe?g';
|
|
*
|
|
* @since 3.3.3
|
|
* @cfg {String} [simpleuploads_imageExtensions='jpe?g|gif|png']
|
|
* @member CKEDITOR.config
|
|
*/
|
|
|
|
/**
|
|
* Maximum file size to allow the upload. By default there are no restrictions
|
|
*
|
|
* config.simpleuploads_maxFileSize=10*1024*1024; // 10 Mb
|
|
*
|
|
* @since 3.3.3
|
|
* @cfg {Number} [simpleuploads_maxFileSize=null]
|
|
* @member CKEDITOR.config
|
|
*/
|
|
|
|
|
|
/**
|
|
* List of extensions that aren't allowed (blacklist)
|
|
*
|
|
* config.simpleuploads_invalidExtensions='exe|php';
|
|
*
|
|
* @since 3.3.3
|
|
* @cfg {String} [simpleuploads_invalidExtensions=null]
|
|
* @member CKEDITOR.config
|
|
*/
|
|
|
|
/**
|
|
* List of extensions that are accepted (whitelist). If the file doesn't have this extension it will be rejected
|
|
*
|
|
* config.simpleuploads_acceptedExtensions='jpg|png|pdf|zip';
|
|
*
|
|
* @since 3.3.3
|
|
* @cfg {String} [simpleuploads_acceptedExtensions=null]
|
|
* @member CKEDITOR.config
|
|
*/
|
|
|
|
|
|
/**
|
|
* If it's set to true, the plugin won't modify the "Quick Upload" button in the dialogs
|
|
* (just in case you are doing some special processing that isn't possible at the moment with the modified system)
|
|
* (if you have such situation, please, contact me so that I can improve the plugin and allow you to use the plugin for everything)
|
|
*
|
|
* config.simpleuploads_respectDialogUploads=true;
|
|
*
|
|
* @since 4.0
|
|
* @cfg {Boolean} [simpleuploads_respectDialogUploads=null]
|
|
* @member CKEDITOR.config
|
|
*/
|
|
|
|
/**
|
|
* If it's set to true, images will be uploaded without the preview progress, using the plain text upload
|
|
*
|
|
* CKEDITOR.config.simpleuploads_hideImageProgress=true;
|
|
*
|
|
* @since 4.1
|
|
* @cfg {Boolean} [simpleuploads_hideImageProgress=null]
|
|
* @member CKEDITOR.config
|
|
*/
|
|
|
|
/**
|
|
* If it's set to true, bmp images will be converted to png before uploading (you must add the "bmp" to the list of allowed extensions)
|
|
*
|
|
* CKEDITOR.config.simpleuploads_convertBmp=true;
|
|
*
|
|
* @since 4.2
|
|
* @cfg {Boolean} [simpleuploads_convertBmp=null]
|
|
* @member CKEDITOR.config
|
|
*/
|
|
|
|
/**
|
|
* It's an object that can contain two members: width and height specifying the maximum dimensions (in pixels) allowed for images.
|
|
* if the image is bigger in any of those dimensions, the upload will be rejected.
|
|
*
|
|
* CKEDITOR.config.simpleuploads_maximumDimensions={width:500, height:400};
|
|
*
|
|
* @since 4.2
|
|
* @cfg {Object} [simpleuploads_maximumDimensions=null]
|
|
* @member CKEDITOR.config
|
|
*/
|
|
|
|
/**
|
|
* Name of the input sent to the server with the file data
|
|
*
|
|
* CKEDITOR.config.simpleuploads_inputname="file";
|
|
*
|
|
* @since 4.3.9
|
|
* @cfg {String} [simpleuploads_inputname="upload"]
|
|
* @member CKEDITOR.config
|
|
*/
|