Added error handling

- refactored to build dropzone elements individually
- reduced markdown in ghostdown file
- added Try again button on failure of image upload
This commit is contained in:
cobbspur 2013-08-18 19:31:22 +01:00
parent b59575d26b
commit 2f4d29bf72
3 changed files with 89 additions and 72 deletions

View File

@ -3,11 +3,6 @@
"use strict"; "use strict";
var UploadUi, var UploadUi,
$loader = '<span class="media"><span class="hidden">Image Upload</span></span>' +
'<div class="description">Add image</div>' +
'<a class="image-url" title="Add image from URL"><span class="hidden">URL</span></a>' +
'<a class="image-webcam" title="Add image from webcam">' +
'<span class="hidden">Webcam</span></a>',
$progress = $('<div />', { $progress = $('<div />', {
"class" : "js-upload-progress progress progress-success active", "class" : "js-upload-progress progress progress-success active",
"style": "opacity:0", "style": "opacity:0",
@ -33,11 +28,13 @@
$dropzone.find('.js-fileupload').fileupload().fileupload("option", { $dropzone.find('.js-fileupload').fileupload().fileupload("option", {
url: '/ghost/upload', url: '/ghost/upload',
add: function (e, data) { add: function (e, data) {
$progress.find('.js-upload-progress-bar').removeClass('fail');
$dropzone.trigger('uploadstart');
$dropzone.find('a.js-return-image').remove(); $dropzone.find('a.js-return-image').remove();
$dropzone.find('span.media, div.description, a.image-url, a.image-webcam') $dropzone.find('span.media, div.description, a.image-url, a.image-webcam, div.js-fail, button.js-fail')
.animate({opacity: 0}, 250, function () { .animate({opacity: 0}, 250, function () {
if (settings.progressbar) { if (settings.progressbar) {
$dropzone.find('span.media').after($progress); $dropzone.find('div.js-fail').after($progress);
$progress.animate({opacity: 100}, 250); $progress.animate({opacity: 100}, 250);
} }
data.submit(); data.submit();
@ -48,16 +45,11 @@
var progress = parseInt(data.loaded / data.total * 100, 10); var progress = parseInt(data.loaded / data.total * 100, 10);
if (!settings.editor) {$progress.find('div.js-progress').css({"position": "absolute", "top": "40px"}); } if (!settings.editor) {$progress.find('div.js-progress').css({"position": "absolute", "top": "40px"}); }
if (settings.progressbar) { if (settings.progressbar) {
$dropzone.trigger("uploadprogress", [progress, data]);
$progress.find('.js-upload-progress-bar').css('width', progress + '%'); $progress.find('.js-upload-progress-bar').css('width', progress + '%');
if (data.loaded / data.total === 1) {
$progress.animate({opacity: 0}, 250, function () {
$dropzone.find('span.media').after('<img class="fileupload-loading" src="/public/img/loadingcat.gif" />');
if (!settings.editor) {$progress.find('.fileupload-loading').css({"top": "56px"}); }
});
}
} }
}, },
done: function (e, data) { done: function (e, data) {
function showImage(width, height) { function showImage(width, height) {
$dropzone.find('img.js-upload-target').attr({"width": width, "height": height}).css({"display": "block"}); $dropzone.find('img.js-upload-target').attr({"width": width, "height": height}).css({"display": "block"});
@ -83,19 +75,65 @@
}); });
} }
function preloadImage() { function failedImageUpload() {
$progress.find('.js-upload-progress-bar').addClass('fail');
$dropzone.find('div.js-fail').animate({"opacity": 100}, 1500);
$dropzone.find('button.js-fail').animate({"opacity": 100}, 1500).on('click', function () {
$dropzone.css({minHeight: 0});
if (source !== undefined && !$dropzone.find('a.js-return-image')[0]) {
console.log("source:", source);
$back.css({"opacity": 100});
$dropzone.find('.js-upload-target').after($back);
}
self.removeExtras();
self.init();
});
}
function preLoadImage() {
var $img = $dropzone.find('img.js-upload-target') var $img = $dropzone.find('img.js-upload-target')
.attr({'src': '', "width": 'auto', "height": 'auto'}); .attr({'src': '', "width": 'auto', "height": 'auto'});
$img.one('load', function () { animateDropzone($img); }) if (data.result === "Invalid filetype") {
.attr('src', data.result); $dropzone.trigger("uploadfailed", [data.result]);
failedImageUpload();
} else {
$progress.animate({opacity: 0}, 250, function () {
$dropzone.find('span.media').after('<img class="fileupload-loading" src="/public/img/loadingcat.gif" />');
if (!settings.editor) {$progress.find('.fileupload-loading').css({"top": "56px"}); }
});
$dropzone.trigger("uploadsuccess", [data.result]);
$img.one('load', function () { animateDropzone($img); })
.attr('src', data.result);
}
} }
preloadImage(); preLoadImage();
} }
}); });
}, },
buildExtras: function () {
if (!$dropzone.find('span.media')[0]) {
$dropzone.prepend('<span class="media"><span class="hidden">Image Upload</span></span>');
}
if (!$dropzone.find('div.description')[0]) {
$dropzone.append('<div class="description">Add image</div>');
}
if (!$dropzone.find('div.js-fail')[0]) {
$dropzone.append('<div class="js-fail failed" style="opacity: 0">Something went wrong :(</div>');
}
if (!$dropzone.find('button.js-fail')[0]) {
$dropzone.append('<button class="js-fail button-add" style="opacity: 0">Try Again</button>');
}
if (!$dropzone.find('a.image-url')[0]) {
$dropzone.append('<a class="image-url" title="Add image from URL"><span class="hidden">URL</span></a>');
}
if (!$dropzone.find('a.image-webcam')[0]) {
$dropzone.append('<a class="image-webcam" title="Add image from webcam"><span class="hidden">Webcam</span></a>');
}
},
removeExtras: function () { removeExtras: function () {
$dropzone.find('div.description, span.media, div.js-upload-progress, a.image-url, a.image-webcam') $dropzone.find('div.description, span.media, div.js-upload-progress, a.image-url, a.image-webcam, div.js-fail, button.js-fail')
.remove(); .remove();
}, },
@ -104,12 +142,10 @@
//This is the start point if no image exists //This is the start point if no image exists
$dropzone.find('img.js-upload-target').css({"display": "none"}); $dropzone.find('img.js-upload-target').css({"display": "none"});
$dropzone.removeClass('pre-image-uploader').addClass('image-uploader'); $dropzone.removeClass('pre-image-uploader').addClass('image-uploader');
if (!$dropzone.find('span.media')[0]) {
$dropzone.append($loader); this.buildExtras();
}
if ($dropzone.find('a.js-edit-image')[0]) { $dropzone.find('a.js-edit-image').remove();
$dropzone.find('a.js-edit-image').remove();
}
$back.on('click', function () { $back.on('click', function () {
$dropzone.find('a.js-return-image').remove(); $dropzone.find('a.js-return-image').remove();
@ -142,18 +178,16 @@
}, },
init: function () { init: function () {
var img;
// First check if field image is defined by checking for js-upload-target class // First check if field image is defined by checking for js-upload-target class
if ($dropzone.find('img.js-upload-target')[0]) { if (!$dropzone.find('img.js-upload-target')[0]) {
if ($dropzone.find('img.js-upload-target').attr('src') === '') {
this.initWithDropzone();
} else {
this.initWithImage();
}
} else {
// This ensures there is an image we can hook into to display uploaded image // This ensures there is an image we can hook into to display uploaded image
$dropzone.prepend('<img class="js-upload-target" style="display: none" src="" />'); $dropzone.prepend('<img class="js-upload-target" style="display: none" src="" />');
this.init(); }
if ($dropzone.find('img.js-upload-target').attr('src') === '') {
this.initWithDropzone();
} else {
this.initWithImage();
} }
} }
}); });
@ -162,9 +196,9 @@
$.fn.upload = function (options) { $.fn.upload = function (options) {
var settings = $.extend({ var settings = $.extend({
progressbar: true, progressbar: true,
editor: false editor: false
}, options); }, options);
return this.each(function () { return this.each(function () {
var $dropzone = $(this), var $dropzone = $(this),

View File

@ -1142,6 +1142,14 @@ main {
color: $brown; color: $brown;
text-decoration: none; text-decoration: none;
} }
.button-add {
display: inline-block;
position:relative;
z-index: 700;
color: #fff;
padding-left:5px;
}
.image-edit { .image-edit {
line-height: 12px; line-height: 12px;
padding: 10px; padding: 10px;
@ -1163,7 +1171,6 @@ main {
right: 0; right: 0;
color: $brown; color: $brown;
text-decoration: none; text-decoration: none;
} }
input { input {
@ -1199,11 +1206,21 @@ main {
background-size: contain; background-size: contain;
} }
.failed {
position: relative;
top: -40px;
font-size: 16px;
}
.bar { .bar {
height: 12px; height: 12px;
background: $blue; background: $blue;
&.fail {
background: $orange;
}
} }
} }
.pre-image-uploader { .pre-image-uploader {
@include box-sizing(border-box); @include box-sizing(border-box);
@include baseline; @include baseline;
@ -1231,35 +1248,6 @@ main {
} }
//.progress {
// position: relative;
// top: -39px;
// margin: auto;
// margin-bottom: -12px;
// display: block;
// overflow: hidden;
// @include linear-gradient(to bottom, #f5f5f5, #f9f9f9);
// border-radius: 12px;
// box-shadow: (rgba(0,0,0,0.1) 0 1px 2px inset);
//}
//
//.fileupload-loading {
// display: block;
// top: 50%;
// width: 35px;
// height: 28px;
// margin: -28px auto 0;
// background-size: contain;
//}
//
//.bar {
// height: 12px;
// background: $blue;
//}
/* ========================================================================== /* ==========================================================================
Misc Misc
========================================================================== */ ========================================================================== */

View File

@ -7,13 +7,8 @@
filter: function (source) { filter: function (source) {
return source.replace(/\n?!(?:image)?\[([^\n\]]*)\](?:\(([^\n\)]*)\))?/gi, function (match, alt, a) { return source.replace(/\n?!(?:image)?\[([^\n\]]*)\](?:\(([^\n\)]*)\))?/gi, function (match, alt, a) {
return '<section class="js-drop-zone image-uploader">' + return '<section class="js-drop-zone image-uploader">' +
'<span class="media"><span class="hidden">Image Upload</span></span>' +
'<div class="description">Add image of <strong>' + alt + '</strong></div>' + '<div class="description">Add image of <strong>' + alt + '</strong></div>' +
'<img class="js-upload-target" style="display: none" alt="alt" src="" />' +
'<input data-url="upload" class="js-fileupload fileupload" type="file" name="uploadimage">' + '<input data-url="upload" class="js-fileupload fileupload" type="file" name="uploadimage">' +
'<a class="image-url" title="Add image from URL"><span class="hidden">URL</span></a>' +
'<a class="image-webcam" title="Add image from webcam">' +
'<span class="hidden">Webcam</span></a>' +
'</section>'; '</section>';
}); });
} }