mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-17 23:44:39 -05:00
Merge pull request #338 from cobbspur/upload-plugin
Added image upload reusable plugin
This commit is contained in:
commit
ae7921104d
9 changed files with 276 additions and 8 deletions
BIN
ghost/admin/assets/img/AddImage.png
Normal file
BIN
ghost/admin/assets/img/AddImage.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 367 B |
BIN
ghost/admin/assets/img/returnImage.png
Normal file
BIN
ghost/admin/assets/img/returnImage.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
177
ghost/admin/assets/lib/uploader.js
Normal file
177
ghost/admin/assets/lib/uploader.js
Normal file
|
@ -0,0 +1,177 @@
|
|||
/*global jQuery, Ghost, document, Image, window */
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
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 />', {
|
||||
"class" : "js-upload-progress progress progress-success active",
|
||||
"style": "opacity:0",
|
||||
"role": "progressbar",
|
||||
"aria-valuemin": "0",
|
||||
"aria-valuemax": "100"
|
||||
}).append($("<div />", {
|
||||
"class": "js-upload-progress-bar bar",
|
||||
"style": "width:0%"
|
||||
}));
|
||||
|
||||
UploadUi = function ($dropzone, settings) {
|
||||
var source,
|
||||
$link = $('<a class="js-edit-image image-edit" href="#" >' +
|
||||
'<img src="/public/assets/img/addImage.png" width="16" height="16" alt="add, edit"></a>'),
|
||||
$back = $('<a class="js-return-image image-edit" href="#" >' +
|
||||
'<img src="/public/assets/img/returnImage.png" width="16" height="16" alt="add, edit"></a>');
|
||||
|
||||
$.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('<img class="fileupload-loading" src="/public/img/loadingcat.gif" />');
|
||||
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('<img class="js-upload-target" style="display: none" src="" />');
|
||||
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));
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
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>' +
|
||||
'<img class="js-upload-target" style="display: none" alt="alt" src="" />' +
|
||||
'<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">' +
|
||||
|
|
|
@ -15,13 +15,19 @@
|
|||
|
||||
<div class="form-group">
|
||||
<label><strong>Blog Logo</strong></label>
|
||||
<img src="/public/img/logo.png" alt="logo" height="38" width="381"/>
|
||||
<section class="js-drop-zone">
|
||||
<img id="logo" class="js-upload-target" src="{{logo}}"{{#unless logo}} style="display: none"{{/unless}} alt="logo"/>
|
||||
<input data-url="upload" class="js-fileupload" type="file" name="uploadimage">
|
||||
</section>
|
||||
<p>Display a logo on your site in place of blog title</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label><strong>Blog Icon</strong></label>
|
||||
<img src="/public/img/test-icon.png" alt="logo" height="38" width="38"/>
|
||||
<section class="js-drop-zone">
|
||||
<img id="icon" class="js-upload-target" src="{{icon}}"{{#unless icon}} style="display: none"{{/unless}} style="display: none" alt="icon"/>
|
||||
<input data-url="upload" class="js-fileupload" type="file" name="uploadimage">
|
||||
</section>
|
||||
<p>The icon for your blog, used in your browser tab and elsewhere</p>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue