diff --git a/Gruntfile.js b/Gruntfile.js index 8148437753..20c9c1b758 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -504,6 +504,9 @@ var path = require('path'), 'bower_components/showdown/src/showdown.js', 'bower_components/moment/moment.js', + 'bower_components/jquery-ui/ui/jquery-ui.js', + 'bower_components/jquery-file-upload/js/jquery.fileupload.js', + 'core/shared/lib/showdown/extensions/ghostimagepreview.js', 'core/shared/lib/showdown/extensions/ghostgfm.js', ] diff --git a/core/client/assets/lib/uploader.js b/core/client/assets/lib/uploader.js new file mode 100644 index 0000000000..9f656ea644 --- /dev/null +++ b/core/client/assets/lib/uploader.js @@ -0,0 +1,262 @@ +import ghostPaths from 'ghost/utils/ghost-paths'; + +var UploadUi, + upload, + Ghost = ghostPaths(); + + +UploadUi = function ($dropzone, settings) { + var $url = '
', + $cancel = 'Delete', + $progress = $('', { + 'class' : 'js-upload-progress progress progress-success active', + 'role': 'progressbar', + 'aria-valuemin': '0', + 'aria-valuemax': '100' + }).append($('', { + 'class': 'js-upload-progress-bar bar', + 'style': 'width:0%' + })); + + $.extend(this, { + complete: function (result) { + var self = this; + + function showImage(width, height) { + $dropzone.find('img.js-upload-target').attr({'width': width, 'height': height}).css({'display': 'block'}); + $dropzone.find('.fileupload-loading').remove(); + $dropzone.css({'height': 'auto'}); + $dropzone.delay(250).animate({opacity: 100}, 1000, function () { + $('.js-button-accept').prop('disabled', false); + self.init(); + }); + } + + function animateDropzone($img) { + $dropzone.animate({opacity: 0}, 250, function () { + $dropzone.removeClass('image-uploader').addClass('pre-image-uploader'); + $dropzone.css({minHeight: 0}); + self.removeExtras(); + $dropzone.animate({height: $img.height()}, 250, function () { + showImage($img.width(), $img.height()); + }); + }); + } + + function preLoadImage() { + var $img = $dropzone.find('img.js-upload-target') + .attr({'src': '', 'width': 'auto', 'height': 'auto'}); + + $progress.animate({'opacity': 0}, 250, function () { + $dropzone.find('span.media').after(''); + if (!settings.editor) {$progress.find('.fileupload-loading').css({'top': '56px'}); } + }); + $dropzone.trigger('uploadsuccess', [result]); + $img.one('load', function () { + animateDropzone($img); + }).attr('src', result); + } + preLoadImage(); + }, + + bindFileUpload: function () { + var self = this; + + $dropzone.find('.js-fileupload').fileupload().fileupload('option', { + url: Ghost.subdir + '/ghost/upload/', + headers: { + 'X-CSRF-Token': $('meta[name=\'csrf-param\']').attr('content') + }, + add: function (e, data) { + /*jshint unused:false*/ + $('.js-button-accept').prop('disabled', true); + $dropzone.find('.js-fileupload').removeClass('right'); + $dropzone.find('.js-url').remove(); + $progress.find('.js-upload-progress-bar').removeClass('fail'); + $dropzone.trigger('uploadstart', [$dropzone.attr('id')]); + $dropzone.find('span.media, div.description, a.image-url, a.image-webcam') + .animate({opacity: 0}, 250, function () { + $dropzone.find('div.description').hide().css({'opacity': 100}); + if (settings.progressbar) { + $dropzone.find('div.js-fail').after($progress); + $progress.animate({opacity: 100}, 250); + } + data.submit(); + }); + }, + dropZone: settings.fileStorage ? $dropzone : null, + progressall: function (e, data) { + /*jshint unused:false*/ + var progress = parseInt(data.loaded / data.total * 100, 10); + if (!settings.editor) {$progress.find('div.js-progress').css({'position': 'absolute', 'top': '40px'}); } + if (settings.progressbar) { + $dropzone.trigger('uploadprogress', [progress, data]); + $progress.find('.js-upload-progress-bar').css('width', progress + '%'); + } + }, + fail: function (e, data) { + /*jshint unused:false*/ + $('.js-button-accept').prop('disabled', false); + $dropzone.trigger('uploadfailure', [data.result]); + $dropzone.find('.js-upload-progress-bar').addClass('fail'); + if (data.jqXHR.status === 413) { + $dropzone.find('div.js-fail').text('The image you uploaded was larger than the maximum file size your server allows.'); + } else if (data.jqXHR.status === 415) { + $dropzone.find('div.js-fail').text('The image type you uploaded is not supported. Please use .PNG, .JPG, .GIF, .SVG.'); + } else { + $dropzone.find('div.js-fail').text('Something went wrong :('); + } + $dropzone.find('div.js-fail, button.js-fail').fadeIn(1500); + $dropzone.find('button.js-fail').on('click', function () { + $dropzone.css({minHeight: 0}); + $dropzone.find('div.description').show(); + self.removeExtras(); + self.init(); + }); + }, + done: function (e, data) { + /*jshint unused:false*/ + self.complete(data.result); + } + }); + }, + + buildExtras: function () { + if (!$dropzone.find('span.media')[0]) { + $dropzone.prepend('Image Upload'); + } + if (!$dropzone.find('div.description')[0]) { + $dropzone.append('