diff --git a/ghost/admin/assets/img/AddImage.png b/ghost/admin/assets/img/AddImage.png
new file mode 100644
index 0000000000..8bcf8b33dc
Binary files /dev/null and b/ghost/admin/assets/img/AddImage.png differ
diff --git a/ghost/admin/assets/img/returnImage.png b/ghost/admin/assets/img/returnImage.png
new file mode 100644
index 0000000000..a59e8198d5
Binary files /dev/null and b/ghost/admin/assets/img/returnImage.png differ
diff --git a/ghost/admin/assets/lib/uploader.js b/ghost/admin/assets/lib/uploader.js
new file mode 100644
index 0000000000..7ffdd43600
--- /dev/null
+++ b/ghost/admin/assets/lib/uploader.js
@@ -0,0 +1,177 @@
+/*global jQuery, Ghost, document, Image, window */
+(function ($) {
+ "use strict";
+
+ var UploadUi,
+ $loader = 'Image Upload' +
+ '
Add image
' +
+ 'URL' +
+ '' +
+ 'Webcam',
+ $progress = $('', {
+ "class" : "js-upload-progress progress progress-success active",
+ "style": "opacity:0",
+ "role": "progressbar",
+ "aria-valuemin": "0",
+ "aria-valuemax": "100"
+ }).append($("", {
+ "class": "js-upload-progress-bar bar",
+ "style": "width:0%"
+ }));
+
+ UploadUi = function ($dropzone, settings) {
+ var source,
+ $link = $('' +
+ '
'),
+ $back = $('' +
+ '
');
+
+ $.extend(this, {
+ bindFileUpload: function () {
+ var self = this;
+
+ $dropzone.find('.js-fileupload').fileupload().fileupload("option", {
+ url: '/ghost/upload',
+ add: function (e, data) {
+ $dropzone.find('a.js-return-image').remove();
+ $dropzone.find('span.media, div.description, a.image-url, a.image-webcam')
+ .animate({opacity: 0}, 250, function () {
+ if (settings.progressbar) {
+ $dropzone.find('span.media').after($progress);
+ $progress.animate({opacity: 100}, 250);
+ }
+ data.submit();
+ });
+ },
+ dropZone: $dropzone,
+ progressall: function (e, data) {
+ 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) {
+ $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('
');
+ if (!settings.editor) {$progress.find('.fileupload-loading').css({"top": "56px"}); }
+ });
+ }
+ }
+
+ },
+ done: function (e, data) {
+ function showImage(width, height) {
+ $dropzone.find('img.js-upload-target').attr({"width": width, "height": height}).css({"display": "block"});
+ $dropzone.find('.fileupload-loading').removeClass('fileupload-loading');
+ $dropzone.css({"height": "auto"});
+ if (!$dropzone.find('a.js-edit-image')[0]) {
+ $link.css({"opacity": 100});
+ $dropzone.find('.js-upload-target').after($link);
+ }
+ $dropzone.delay(250).animate({opacity: 100}, 1000, function () {
+ 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'});
+ $img.one('load', function () { animateDropzone($img); })
+ .attr('src', data.result);
+ }
+ preloadImage();
+ }
+ });
+ },
+
+ removeExtras: function () {
+ $dropzone.find('div.description, span.media, div.js-upload-progress, a.image-url, a.image-webcam')
+ .remove();
+ },
+
+ initWithDropzone: function () {
+ var self = this;
+ //This is the start point if no image exists
+ $dropzone.find('img.js-upload-target').css({"display": "none"});
+ $dropzone.removeClass('pre-image-uploader').addClass('image-uploader');
+ if (!$dropzone.find('span.media')[0]) {
+ $dropzone.append($loader);
+ }
+ if ($dropzone.find('a.js-edit-image')[0]) {
+ $dropzone.find('a.js-edit-image').remove();
+ }
+
+ $back.on('click', function () {
+ $dropzone.find('a.js-return-image').remove();
+ $dropzone.find('img.js-upload-target').attr({"src": source}).css({"display": "block"});
+ self.removeExtras();
+ $dropzone.removeClass('image-uploader').addClass('pre-image-uploader');
+ self.init();
+ });
+ this.bindFileUpload();
+ },
+
+ initWithImage: function () {
+ var self = this;
+ // This is the start point if an image already exists
+ source = $dropzone.find('img.js-upload-target').attr('src');
+ $dropzone.removeClass('image-uploader').addClass('pre-image-uploader');
+
+ if (!$dropzone.find('a.js-edit-image')[0]) {
+ $link.css({"opacity": 100});
+ $dropzone.find('.js-upload-target').after($link);
+ }
+
+ $link.on('click', function () {
+ $dropzone.find('a.js-edit-image').remove();
+ $dropzone.find('img.js-upload-target').attr({"src": ""}).css({"display": "none"});
+ $back.css({"cursor": "pointer", "z-index": 9999, "opacity": 100});
+ $dropzone.find('.js-upload-target').after($back);
+ self.init();
+ });
+ },
+
+ init: function () {
+ var img;
+ // 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').attr('src') === '') {
+ this.initWithDropzone();
+ } else {
+ this.initWithImage();
+ }
+ } else {
+ // This ensures there is an image we can hook into to display uploaded image
+ $dropzone.prepend('
');
+ this.init();
+ }
+ }
+ });
+ };
+
+
+ $.fn.upload = function (options) {
+ var settings = $.extend({
+ progressbar: true,
+ editor: false
+ }, options);
+
+ return this.each(function () {
+ var $dropzone = $(this),
+ ui;
+
+ ui = new UploadUi($dropzone, settings);
+ ui.init();
+ });
+ };
+}(jQuery));
\ No newline at end of file
diff --git a/ghost/admin/assets/sass/layouts/editor.scss b/ghost/admin/assets/sass/layouts/editor.scss
index 6e5732e24c..042f4eb5b8 100644
--- a/ghost/admin/assets/sass/layouts/editor.scss
+++ b/ghost/admin/assets/sass/layouts/editor.scss
@@ -117,7 +117,7 @@
padding: 5px;
&:hover {
- @include icon($i-question, '', $brown)
+ @include icon($i-question, '', $brown);
}
}
@@ -255,7 +255,6 @@
@include breakpoint($netbook) {padding-top: 20px;}
@include breakpoint($mobile) {padding: 15px;}
}
-
}
// Special case, when scrolling, add shadows to content headers.
@@ -331,11 +330,21 @@
text-align: center;
}
}
-
+ a {
+ &.image-edit {
+ width: 16px;
+ height: 16px;
+ }
+ }
img {
width: 100%;
height: auto;
}
+ // prevent uploaded image from being streched in editor
+ .pre-image-uploader img {
+ width: auto;
+ }
+
}
diff --git a/ghost/admin/assets/sass/modules/global.scss b/ghost/admin/assets/sass/modules/global.scss
index b196eac15b..02be82aeee 100644
--- a/ghost/admin/assets/sass/modules/global.scss
+++ b/ghost/admin/assets/sass/modules/global.scss
@@ -1135,6 +1135,16 @@ main {
color: $brown;
text-decoration: none;
}
+ .image-edit {
+ line-height: 12px;
+ padding: 10px;
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0;
+ opacity: 0;
+ text-decoration: none;
+ }
.image-webcam {
@include icon($i-camera, 12px);
@@ -1146,9 +1156,10 @@ main {
right: 0;
color: $brown;
text-decoration: none;
+
}
- .fileupload {
+ input {
position: absolute;
right: 0;
margin: 0;
@@ -1162,7 +1173,7 @@ main {
.progress {
position: relative;
- top: -39px;
+ top: -22px;
margin: auto;
margin-bottom: -12px;
display: block;
@@ -1186,7 +1197,61 @@ main {
background: $blue;
}
}
+.pre-image-uploader {
+ @include box-sizing(border-box);
+ @include baseline;
+ position: relative;
+ overflow:hidden;
+ height: auto;
+ color: $brown;
+ input {
+ position: absolute;
+ left: 9999px;
+ opacity: 0;
+ }
+ .image-edit {
+
+ line-height: 12px;
+ padding: 10px;
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0;
+ opacity: 0;
+ text-decoration: none;
+ }
+}
+
+
+
+
+
+//.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
diff --git a/ghost/admin/assets/vendor/showdown/extensions/ghostdown.js b/ghost/admin/assets/vendor/showdown/extensions/ghostdown.js
index 6d8862b3ed..984c044974 100644
--- a/ghost/admin/assets/vendor/showdown/extensions/ghostdown.js
+++ b/ghost/admin/assets/vendor/showdown/extensions/ghostdown.js
@@ -9,6 +9,7 @@
return '' +
'Image Upload' +
'Add image of ' + alt + '
' +
+ '
' +
'' +
'URL' +
'' +
diff --git a/ghost/admin/tpl/settings/general.hbs b/ghost/admin/tpl/settings/general.hbs
index 0a89daf1bb..e9166ccf71 100644
--- a/ghost/admin/tpl/settings/general.hbs
+++ b/ghost/admin/tpl/settings/general.hbs
@@ -15,13 +15,19 @@
diff --git a/ghost/admin/views/editor.js b/ghost/admin/views/editor.js
index e951deb907..010fdd7493 100644
--- a/ghost/admin/views/editor.js
+++ b/ghost/admin/views/editor.js
@@ -303,6 +303,7 @@
var view = this,
preview = document.getElementsByClassName('rendered-markdown')[0];
preview.innerHTML = this.converter.makeHtml(this.editor.getValue());
+ view.$('.js-drop-zone').upload({editor: true});
Countable.once(preview, function (counter) {
view.$('.entry-word-count').text(counter.words + ' words');
view.$('.entry-character-count').text(counter.characters + ' characters');
diff --git a/ghost/admin/views/settings.js b/ghost/admin/views/settings.js
index ae6027ed7b..8da3272457 100644
--- a/ghost/admin/views/settings.js
+++ b/ghost/admin/views/settings.js
@@ -124,7 +124,10 @@
saveSettings: function () {
this.model.save({
title: this.$('#blog-title').val(),
- email: this.$('#email-address').val()
+ email: this.$('#email-address').val(),
+ logo: this.$('#logo').attr("src"),
+ icon: this.$('#icon').attr("src")
+
}, {
success: this.saveSuccess,
error: this.saveError
@@ -137,6 +140,12 @@
var settings = this.model.toJSON();
this.$('#blog-title').val(settings.title);
this.$('#email-address').val(settings.email);
+ },
+
+ afterRender: function () {
+ this.$el.attr('id', this.id);
+ this.$el.addClass('active');
+ this.$('.js-drop-zone').upload();
}
});