Skip to content

Commit

Permalink
Fixed a bunch of upload related issues.
Browse files Browse the repository at this point in the history
  • Loading branch information
spocke committed Aug 28, 2015
1 parent 8b1264c commit bf7ed7c
Show file tree
Hide file tree
Showing 7 changed files with 232 additions and 101 deletions.
4 changes: 4 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
Version 4.2.5 (2015-08-xx)
Added fullscreen capability to embedded youtube and vimeo videos.
Fixed bug where the uploadImages call didn't work on IE 10.
Fixed bug where image place holders would be uploaded by uploadImages call.
Fixed bug where images marked with bogus would be uploaded by the uploadImages call.
Fixed bug where multiple calls to uploadImages would result in decreased performance.
Fixed so that the image uploads are concurrent for improved performance.
Version 4.2.4 (2015-08-17)
Added picture as a valid element to the HTML 5 schema. Patch contributed by Adam Taylor.
Fixed bug where contents would be duplicated on drag/drop within the same editor.
Expand Down
62 changes: 32 additions & 30 deletions js/tinymce/classes/EditorUpload.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ define("tinymce/EditorUpload", [
"tinymce/file/BlobCache"
], function(Arr, Uploader, ImageScanner, BlobCache) {
return function(editor) {
var blobCache = new BlobCache();
var blobCache = new BlobCache(), uploader, imageScanner;

// Replaces strings without regexps to avoid FF regexp to big issue
function replaceString(content, search, replace) {
Expand Down Expand Up @@ -53,53 +53,54 @@ define("tinymce/EditorUpload", [
}

function uploadImages(callback) {
var uploader = new Uploader({
url: editor.settings.images_upload_url,
basePath: editor.settings.images_upload_base_path,
credentials: editor.settings.images_upload_credentials,
handler: editor.settings.images_upload_handler
});

function imageInfosToBlobInfos(imageInfos) {
return Arr.map(imageInfos, function(imageInfo) {
return imageInfo.blobInfo;
if (!uploader) {
uploader = new Uploader({
url: editor.settings.images_upload_url,
basePath: editor.settings.images_upload_base_path,
credentials: editor.settings.images_upload_credentials,
handler: editor.settings.images_upload_handler
});
}

return scanForImages().then(imageInfosToBlobInfos).then(uploader.upload).then(function(result) {
result = Arr.map(result, function(uploadInfo) {
var image;
return scanForImages().then(function(imageInfos) {
var blobInfos;

image = editor.dom.select('img[src="' + uploadInfo.blobInfo.blobUri() + '"]')[0];
blobInfos = Arr.map(imageInfos, function(imageInfo) {
return imageInfo.blobInfo;
});

return uploader.upload(blobInfos).then(function(result) {
result = Arr.map(result, function(uploadInfo, index) {
var image = imageInfos[index].image;

if (image) {
replaceUrlInUndoStack(image.src, uploadInfo.url);

editor.$(image).attr({
src: uploadInfo.url,
'data-mce-src': editor.convertURL(uploadInfo.url, 'src')
});
}

return {
element: image,
status: uploadInfo.status
};
});
return {
element: image,
status: uploadInfo.status
};
});

if (callback) {
callback(result);
}
if (callback) {
callback(result);
}

return result;
}, function() {
// Silent
// TODO: Maybe execute some failure callback here?
return result;
});
});
}

function scanForImages() {
return ImageScanner.findAll(editor.getBody(), blobCache).then(function(result) {
if (!imageScanner) {
imageScanner = new ImageScanner(blobCache);
}

return imageScanner.findAll(editor.getBody()).then(function(result) {
Arr.each(result, function(resultItem) {
replaceUrlInUndoStack(resultItem.image.src, resultItem.blobInfo.blobUri());
resultItem.image.src = resultItem.blobInfo.blobUri();
Expand All @@ -111,6 +112,7 @@ define("tinymce/EditorUpload", [

function destroy() {
blobCache.destroy();
imageScanner = uploader = null;
}

function replaceBlobWithBase64(content) {
Expand Down
92 changes: 60 additions & 32 deletions js/tinymce/classes/file/ImageScanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,38 +17,19 @@
define("tinymce/file/ImageScanner", [
"tinymce/util/Promise",
"tinymce/util/Arr",
"tinymce/file/Conversions"
], function(Promise, Arr, Conversions) {
"tinymce/file/Conversions",
"tinymce/Env"
], function(Promise, Arr, Conversions, Env) {
var count = 0;

function mapAsync(array, fn) {
return new Promise(function(resolve) {
var result = [];
return function(blobCache) {
var cachedPromises = {};

function next(index) {
fn(array[index], function(value) {
result.push(value);
function findAll(elm) {
var images, promises;

if (index < array.length - 1) {
next(index + 1);
} else {
resolve(result);
}
});
}

if (array.length === 0) {
resolve(result);
} else {
next(0);
}
});
}

return {
findAll: function(elm, blobCache) {
function imageToBlobInfo(img, resolve) {
var base64, blobInfo, blobInfoId;
var base64, blobInfo;

if (img.src.indexOf('blob:') === 0) {
blobInfo = blobCache.getByUri(img.src);
Expand All @@ -63,7 +44,6 @@ define("tinymce/file/ImageScanner", [
return;
}

blobInfoId = 'blobid' + (count++);
base64 = Conversions.parseDataUri(img.src).data;
blobInfo = blobCache.findFirst(function(cachedBlobInfo) {
return cachedBlobInfo.base64() === base64;
Expand All @@ -76,7 +56,8 @@ define("tinymce/file/ImageScanner", [
});
} else {
Conversions.uriToBlob(img.src).then(function(blob) {
var blobInfo = blobCache.create(blobInfoId, blob, base64);
var blobInfoId = 'blobid' + (count++),
blobInfo = blobCache.create(blobInfoId, blob, base64);

blobCache.add(blobInfo);

Expand All @@ -88,9 +69,56 @@ define("tinymce/file/ImageScanner", [
}
}

return mapAsync(Arr.filter(elm.getElementsByTagName('img'), function(img) {
return img.src && (img.src.indexOf('data:') === 0 || img.src.indexOf('blob:') === 0);
}), imageToBlobInfo);
images = Arr.filter(elm.getElementsByTagName('img'), function(img) {
var src = img.src;

if (img.getAttribute('data-mce-bogus')) {
return false;
}

if (!src || src == Env.transparentSrc) {
return false;
}

return src.indexOf('data:') === 0 || src.indexOf('blob:') === 0;
});

promises = Arr.map(images, function(img) {
var newPromise;

if (cachedPromises[img.src]) {
// Since the cached promise will return the cached image
// We need to wrap it and resolve with the actual image
return new Promise(function(resolve) {
cachedPromises[img.src].then(function(imageInfo) {
resolve({
image: img,
blobInfo: imageInfo.blobInfo
});
});
});
}

newPromise = new Promise(function(resolve) {
imageToBlobInfo(img, resolve);
}).then(function(result) {
delete cachedPromises[result.image.src];
return result;
})['catch'](function(error) {
delete cachedPromises[img.src];
return error;
});

cachedPromises[img.src] = newPromise;

return newPromise;
});

return Promise.all(promises);
}

return {
findAll: findAll
};
};
});
82 changes: 44 additions & 38 deletions js/tinymce/classes/file/Uploader.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ define("tinymce/file/Uploader", [
"tinymce/util/Fun"
], function(Promise, Tools, Fun) {
return function(settings) {
var cachedPromises = {};

function fileName(blobInfo) {
var ext, extensions;

Expand Down Expand Up @@ -97,53 +99,57 @@ define("tinymce/file/Uploader", [
}

function upload(blobInfos) {
return new Promise(function(resolve, reject) {
var handler = settings.handler, queue, index = 0, uploadedIdMap = {};
var promises;

// If no url is configured then resolve
if (!settings.url && handler === defaultHandler) {
// If no url is configured then resolve
if (!settings.url && settings.handler === defaultHandler) {
return new Promise(function(resolve) {
resolve([]);
return;
}

queue = Tools.map(blobInfos, function(blobInfo) {
return {
status: false,
blobInfo: blobInfo,
url: ''
};
});
}

function uploadBlobInfo(blobInfo) {
return new Promise(function(resolve) {
var handler = settings.handler;

function uploadNext() {
var previousResult, queueItem = queue[index++];

if (!queueItem) {
resolve(queue);
return;
}

// Only upload unique blob once
previousResult = uploadedIdMap[queueItem.blobInfo.id()];
if (previousResult) {
queueItem.url = previousResult;
queueItem.status = true;
uploadNext();
return;
}

handler(blobInfoToData(queueItem.blobInfo), function(url) {
uploadedIdMap[queueItem.blobInfo.id()] = url;
queueItem.url = url;
queueItem.status = true;
uploadNext();
handler(blobInfoToData(blobInfo), function(url) {
resolve({
url: url,
blobInfo: blobInfo,
status: true
});
}, function(failure) {
queueItem.status = false;
reject(failure);
resolve({
url: '',
blobInfo: blobInfo,
status: false,
error: failure
});
});
});
}

promises = Tools.map(blobInfos, function(blobInfo) {
var newPromise, id = blobInfo.id();

if (cachedPromises[id]) {
return cachedPromises[id];
}

uploadNext();
newPromise = uploadBlobInfo(blobInfo).then(function(result) {
delete cachedPromises[id];
return result;
})['catch'](function(error) {
delete cachedPromises[id];
return error;
});

cachedPromises[id] = newPromise;

return newPromise;
});

return Promise.all(promises);
}

settings = Tools.extend({
Expand Down
1 change: 1 addition & 0 deletions tests/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

<!-- tinymce.file.* -->
<script src="tinymce/file/Conversions.js"></script>
<script src="tinymce/file/ImageScanner.js"></script>

<!-- tinymce.dom.* -->
<script src="tinymce/dom/DomQuery.js"></script>
Expand Down
Loading

0 comments on commit bf7ed7c

Please sign in to comment.