I'm building a photos uploader in Javascript and to read the already uploaded photos I've this code:
// Populate with existing photos
var index;
for (index = 0; index < params.photosToPopulate.length; ++index) {
// Get the data of the image
getDataUri(params.photosToPopulate[index], params, function(dataURI){
// Get the Blob
dataURItoBlob(dataURI, function(dataurl){
var blob = URL.createObjectURL(dataurl);
// fileItem
var fileItem = document.createElement("div");
fileItem.setAttribute('angle', 0);
fileItem.setAttribute('blob', blob);
fileItem.className = 'imageloaderplusFile';
filesdiv.appendChild(fileItem);
// fileImg
var fileImg = document.createElement("div");
fileImg.className = 'imageloaderplusImage';
fileImg.style.backgroundImage = 'url(' + dataURI + ')';
fileItem.appendChild(fileImg);
// fileRotate
var fileRotate = document.createElement("div");
fileRotate.className = 'imageloaderRotate';
fileRotate.setAttribute('title', 'Rotate');
fileItem.appendChild(fileRotate);
fileRotate.onclick = function(){
var angle;
switch(parseInt(this.parentNode.getAttribute('angle'))){
case 0:
angle = 90;
break;
case 90:
angle = 180;
break;
case 180:
angle = 270;
break;
case 270:
angle = 0;
break;
}
this.parentNode.setAttribute('angle', angle);
// css
var image = this.parentNode.firstChild;
image.style.webkitTransform = 'rotate(' + angle + 'deg)';
image.style.mozTransform = 'rotate(' + angle + 'deg)';
image.style.msTransform = 'rotate(' + angle + 'deg)';
image.style.oTransform = 'rotate(' + angle + 'deg)';
image.style.transform = 'rotate(' + angle + 'deg)';
// draw
ImageLoaderPlus.draw(this.parentNode, params);
}
// fileRemove
var fileRemove = document.createElement("div");
fileRemove.className = 'imageloaderRemove';
fileRemove.setAttribute('title', 'Remove');
fileItem.appendChild(fileRemove);
fileRemove.onclick = function(){
this.parentNode.parentNode.removeChild(this.parentNode);
}
// draw
ImageLoaderPlus.draw(fileItem, params);
});
});
} // End For Loop
In the For Loop I've the ordered photos, but some times because of the async functions getDataUri() and dataURItoBlob() the order of the items in the For Loop will not translate to the order in de UI/DOM and the photos are displayed in the incorrect order. How can I prevent this from happening?
The async functions are this ones:
function getDataUri(url, params, callback) {
var image = new Image();
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
//image.crossOrigin = "anonymous"; // This enables CORS
// get scale
var scale = (params.resize && (image.width > params.maxWidth || image.height > params.maxHeight)) ? Math.min(params.maxWidth / image.width, params.maxHeight / image.height) : 1;
image.onload = function (event) {
try {
canvas.width = Math.round(image.width * scale);
canvas.height = Math.round(image.height * scale);
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
//console.log( ctx.canvas.toDataURL('image/jpeg', params.jpegQuality) );
result = ctx.canvas.toDataURL('image/jpeg', params.jpegQuality)
callback(result);
} catch (e) {
alert(e);
}
};
image.src = url;
}
// To convert URL to Blob
function dataURItoBlob(dataURI, callback) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0) {
byteString = atob(dataURI.split(',')[1]);
} else {
byteString = unescape(dataURI.split(',')[1]);
}
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
try {
result = new Blob([ab], {type: mimeString});
//return new Blob([ab], {type: mimeString});
} catch (e) {
// The BlobBuilder API has been deprecated in favour of Blob, but older
// browsers don't know about the Blob constructor
// IE10 also supports BlobBuilder, but since the `Blob` constructor
// also works, there's no need to add `MSBlobBuilder`.
var BlobBuilder = window.WebKitBlobBuilder || window.MozBlobBuilder;
var bb = new BlobBuilder();
bb.append(ab);
result = bb.getBlob(mimeString);
//return bb.getBlob(mimeString);
}
callback(result);
}
Any clues on how to avoid this problem?
Best Regards,
fileItemsynchronously in the loop because it doesn't depend on async data? Or can you only append after you have all the data? Alternatively, collect all elements in an array, wait for all async calls to be done and then append all elements.